HAL  v4.5.0-83-g30c8f0afc
The Hardware Analyzer - a comprehensive reverse engineering and manipulation framework for gate-level netlists.
wizard.cpp
Go to the documentation of this file.
8 
9 #include <QHeaderView>
10 #include <QFileDialog>
11 #include <QMessageBox>
12 #include <QPixmap>
13 
14 #include "gui/gui_globals.h"
15 #include "gui/gui_utils/graphics.h"
16 
17 
18 namespace hal {
19 
21  : QWizard(parent), mController(controller), mSettings(settings)
22  {
23  setWindowTitle("Simulation Wizard");
24 
26  sd.clearAll();
27  controller->reset();
28 
29  addPage(new PageSelectGates(mController, this));
30  addPage(new PageClock(mController, this));
31  addPage(new PageEngine(mController, this));
32  mPageEnginePropertiesId = addPage(new PageEngineProperties(mSettings,mController,this));
33  mPageInputDataId = addPage(new PageInputData(mController,this));
34  addPage(new PageRunSimulation(mController,this));
35  addPage(new PageLoadResults(mController,parent,this));
36  }
37 
39  : QWizardPage(parent), mController(controller)
40  {
41  setTitle(tr("Step 1 : Select Gates"));
42  setPixmap(QWizard::LogoPixmap, QPixmap(":/icons/sw_select_gates","PNG").scaled(128,128));
43 
44  QGridLayout* layout = new QGridLayout(this);
45  mButAll = new QPushButton("All gates", this);
46  layout->addWidget(mButAll,0,0);
47  mButSel = new QPushButton("Current GUI selection", this);
48  connect(mButSel,&QPushButton::clicked,this,&PageSelectGates::handleCurrentGuiSelection);
49  layout->addWidget(mButSel,0,1);
50  mButNone = new QPushButton("Clear selection", this);
51  layout->addWidget(mButNone,0,2);
52  mTableView = new QTableView(this);
53 
56 
57  GateSelectProxy* prox = new GateSelectProxy(this);
58 
59  GateSelectModel* modl = new GateSelectModel(false,QSet<u32>(),mTableView);
60  prox->setSourceModel(modl);
61  mTableView->setModel(prox);
63 
64  mTableView->setSortingEnabled(true);
65  mTableView->sortByColumn(2, Qt::AscendingOrder);
66  mTableView->resizeColumnsToContents();
67  mTableView->horizontalHeader()->setStretchLastSection(true);
68  mTableView->verticalHeader()->hide();
69  layout->addWidget(mTableView,1,0,1,3);
73  }
74 
75  void PageSelectGates::handleCurrentGuiSelection()
76  {
77  QSet<u32> guiGateSel = gSelectionRelay->selectedGates();
78  for (u32 modId : gSelectionRelay->selectedModules())
79  {
80  Module* m = gNetlist->get_module_by_id(modId);
81  if (!m) continue;
82  for (Gate* g : m->get_gates(nullptr,true))
83  {
84  guiGateSel.insert(g->get_id());
85  }
86  }
87 
88  const QAbstractItemModel* modl = mTableView->model(); // proxy model
89  int nrows = modl->rowCount();
90  mTableView->clearSelection();
91 
92  bool ok;
93 
94  for (int irow = 0; irow<nrows; irow++)
95  {
96  u32 gid = modl->data(modl->index(irow,0)).toUInt(&ok);
97  if (!ok) continue;
98  if (guiGateSel.contains(gid))
99  mTableView->selectRow(irow);
100  }
101  }
102 
103  std::vector<hal::Gate*> PageSelectGates::selectedGates() const
104  {
105  std::vector<Gate*> retval;
106  QItemSelectionModel *sm = mTableView->selectionModel();
107  if (!sm->hasSelection()) return retval;
108  QSet<u32> selGates;
109  bool ok;
110  for (const QModelIndex& inx : sm->selectedRows(0) )
111  {
112  u32 gid = mTableView->model()->data(inx).toUInt(&ok);
113  if (!ok) continue;
114  selGates.insert(gid);
115  }
116 
117  for (u32 gid: selGates)
118  {
119  Gate* g = gNetlist->get_gate_by_id(gid);
120  if (g) retval.push_back(g);
121  }
122  return retval;
123  }
124 
125  void PageSelectGates::onSelectionChanged(const QItemSelection &selected, const QItemSelection &deselected)
126  {
127  Q_UNUSED(selected);
128  Q_UNUSED(deselected);
129  int numSelectedGates = mTableView->selectionModel()->selectedRows().count();
130  QString txt("\nSelect the gates to be used for simulation.\n");
131  txt += QString::number(numSelectedGates) + " gates selected.";
132  setSubTitle(txt);
133  }
134 
136  {
137  mController->reset();
138  WaveDataList* wd = mController->get_waves();
140  mController->add_gates(selectedGates());
141  for (const Net* inpNet : mController->get_input_nets())
142  mController->get_waveform_by_net(inpNet);
143  if (mController->get_gates().empty() || mController->get_input_nets().empty())
144  return false;
145 
146  mController->compute_waveform_groups();
147  mController->load_waveform_groups(true);
148  return true;
149  }
150 
151 
153  : QWizardPage(parent), mController(controller)
154  {
155  setTitle(tr("Step 2 : Clock settings"));
156  setSubTitle(tr("\nSelect and generate the clock input\nor indicate that no clock generator is used\n(e.g. when clock signal provided in input data)"));
157  setPixmap(QWizard::LogoPixmap, QPixmap(":/icons/sw_select_clock","PNG").scaled(128,128));
158 
159  QGridLayout* layout = new QGridLayout(this);
160  mComboNet = new QComboBox(this);
161 
162  layout->addWidget(new QLabel("Select clock net:",this),0,0);
163  layout->addWidget(mComboNet,0,1);
164 
165  layout->addWidget(new QLabel("Clock period:",this),1,0);
166  mSpinPeriod = new QSpinBox(this);
167  mSpinPeriod->setMinimum(0);
168  mSpinPeriod->setMaximum(1000000);
169  mSpinPeriod->setValue(1000);
170  layout->addWidget(mSpinPeriod,1,1);
171 
172  layout->addWidget(new QLabel("Start value:",this),2,0);
173  mSpinStartValue = new QSpinBox(this);
174  mSpinStartValue->setMinimum(0);
175  mSpinStartValue->setMaximum(1);
176  layout->addWidget(mSpinStartValue,2,1);
177 
178  layout->addWidget(new QLabel("Duration:",this),3,0);
179  mSpinDuration = new QSpinBox(this);
180  mSpinDuration->setMinimum(0);
181  mSpinDuration->setMaximum(10000000);
182  mSpinDuration->setValue(100000);
183  layout->addWidget(mSpinDuration,3,1);
184 
185  mDontUseClock = new QCheckBox("Do not use clock generator in simulation",this);
186  mDontUseClock->setCheckState(Qt::Unchecked);
187  connect(mDontUseClock,&QCheckBox::stateChanged,this,&PageClock::dontUseClockChanged);
188  layout->addWidget(mDontUseClock,4,0,1,2);
189 
190  //mButtonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, this);
191  //connect(mButtonBox, &QDialogButtonBox::accepted, this, &QDialog::accept);
192  //connect(mButtonBox, &QDialogButtonBox::rejected, this, &QDialog::reject);
193  //layout->addWidget(mButtonBox,5,1);
194  }
195 
197  {
198  int j = 0;
199  int iclk = -1;
200 
201  for (const Net* n : mController->get_input_nets())
202  {
203  QString netName = QString::fromStdString(n->get_name());
204  QString upcase = netName.toUpper();
205  if (upcase == "CLK" || upcase == "CLOCK")
206  iclk = j;
207  else if ((upcase.contains("CLK") || upcase.contains("CLOCK")) && j<0 )
208  iclk = j;
209  mComboNet->insertItem(j++,QString("%1[%2]").arg(netName).arg(n->get_id()));
210  }
211  if (iclk >= 0) mComboNet->setCurrentIndex(iclk);
212  }
213 
214  void PageClock::dontUseClockChanged(bool state)
215  {
216  mComboNet->setDisabled(state);
217  mSpinPeriod->setDisabled(state);
218  mSpinStartValue->setDisabled(state);
219  mSpinDuration->setDisabled(state);
220  }
221 
223  {
224 
225  if (mDontUseClock->isChecked())
226  {
227  mController->set_no_clock_used();
228  }
229  else
230  {
231  int period = mSpinPeriod->value();
232  if (period <= 0)
233  {
234  return false;
235  QMessageBox::warning(this, "Error", "Invalid period specified.");
236  }
237 
238 
239  std::string clkNetName = mComboNet->currentText().toStdString();
240 
241  for (const Net* n : mController->get_input_nets())
242  {
243  size_t pos = clkNetName.find("[");
244  if (pos != std::string::npos)
245  clkNetName = clkNetName.substr(0, pos);
246 
247  if (clkNetName == n->get_name())
248  {
249  const Net* clk = n;
250  mController->add_clock_period(
251  clk, period, mSpinStartValue->value()==0, mSpinDuration->value());
252  break;
253  }
254  }
255  }
256 
257  // wurde clock ausgewählt???
258  return true;
259  }
260 
261 
263  : QWizardPage(parent), mController(controller), m_wizard(parent)
264  {
265  setTitle(tr("Step 3 : Engine settings"));
266  setSubTitle(tr("\nSelect the engine for the simulation\nIf the engine you are looking for is not listed,\nyou might have to load the plugin first"));
267  setPixmap(QWizard::LogoPixmap, QPixmap(":/icons/sw_select_engine","PNG").scaled(128,128));
268 
269  mLayout = new QVBoxLayout(this);
270 
272  {
273  QRadioButton *radioButton = new QRadioButton(QString::fromStdString(sef->name()), this);
274  mLayout->addWidget(radioButton);
275 
276  if (QString::fromStdString(sef->name()) == "verilator")
277  {
278  radioButton->setChecked(true);
279  }
280  }
281 
282  setLayout(mLayout);
283  }
284 
286  {
287 
288  QString selectedEngineName;
289 
290  for (int i = 0; i < mLayout->count(); ++i)
291  {
292  QRadioButton *radioButton = qobject_cast<QRadioButton *>(mLayout->itemAt(i)->widget());
293  if (radioButton && radioButton->isChecked())
294  {
295  selectedEngineName = radioButton->text();
296  break;
297  }
298  }
299  if (selectedEngineName.toStdString() == "verilator")
300  {
301  mVerilator = true;
302  }
303  else
304  {
305  mVerilator = false;
306  }
307 
308 
309  mController->create_simulation_engine(selectedEngineName.toStdString());
310  return true;
311  }
312 
313  int PageEngine::nextId() const
314  {
315  if (!m_wizard) return QWizardPage::nextId();
316  if (mVerilator)
317  {
318  return m_wizard->mPageEnginePropertiesId;
319  }
320  else
321  {
322  return m_wizard->mPageInputDataId;
323  }
324  }
325 
327  : QWizardPage(parent), mController(controller), mSettings(settings)
328  {
329  setTitle(tr("Step 3.1 : Engine properties"));
330  setSubTitle(tr("\nEnter engine properties for the verilator"));
331  setPixmap(QWizard::LogoPixmap, QPixmap(":/icons/sw_engine_par","PNG").scaled(128,128));
332 
333  mTableWidget = new QTableWidget(this);
334 
335  QMap<QString,QString> engProp = settings->engineProperties();
336  mTableWidget->setColumnCount(2);
337  mTableWidget->setColumnWidth(0,250);
338  mTableWidget->setColumnWidth(1,350);
339  mTableWidget->setRowCount(engProp.size()+3);
340  mTableWidget->setHorizontalHeaderLabels(QStringList() << "Property" << "Value");
341 
342  mAllItems << "" << "provided_models" << "num_of_threads" << "compiler" << "ssh_server";
343 
344  for (int irow = 0; irow < mTableWidget->rowCount(); ++irow)
345  {
346  QComboBox *comboBox = new QComboBox(this);
347  comboBox->addItems(mAllItems);
348  comboBox->setEditable(true);
349  mTableWidget->setCellWidget(irow, 0, comboBox);
350  connect(comboBox, &QComboBox::currentTextChanged, this, &PageEngineProperties::updateComboBoxes);
351  }
352 
353  int irow = 0;
354  for (auto it = engProp.constBegin(); it != engProp.constEnd(); ++it)
355  {
356  QComboBox *comboBox = qobject_cast<QComboBox *>(mTableWidget->cellWidget(irow, 0));
357  if (comboBox)
358  {
359  int index = comboBox->findText(it.key());
360  if (index != -1)
361  {
362  comboBox->setCurrentIndex(index);
363  }
364  else
365  {
366  comboBox->addItem(it.key());
367  comboBox->setCurrentText(it.key());
368  }
369  }
370  mTableWidget->setItem(irow, 1, new QTableWidgetItem(it.value()));
371  ++irow;
372  }
373  mTableWidget->horizontalHeader()->setStretchLastSection(true);
374 
375  mTableWidget->horizontalHeader()->setStretchLastSection(true);
376  connect(mTableWidget, &QTableWidget::cellChanged, this, &PageEngineProperties::handleCellChanged);
377 
379  layout->addWidget(mTableWidget);
380  setLayout(layout);
381 
385  }
386 
387  void PageEngineProperties::updateComboBoxes(const QString &selectedText)
388  {
389  if (selectedText == "")
390  return;
391  QStringList selectedItems;
392  for (int irow = 0; irow < mTableWidget->rowCount(); ++irow)
393  {
394  QComboBox *comboBox = qobject_cast<QComboBox *>(mTableWidget->cellWidget(irow, 0));
395  if (comboBox)
396  {
397  selectedItems << comboBox->currentText();
398  }
399  }
400 
401  for (int irow = 0; irow < mTableWidget->rowCount(); ++irow)
402  {
403  QComboBox *comboBox = qobject_cast<QComboBox *>(mTableWidget->cellWidget(irow, 0));
404  if (comboBox)
405  {
406 
407  comboBox->blockSignals(true);
408  QString currentText = comboBox->currentText();
409  comboBox->clear();
410 
411  for (const QString &item : mAllItems)
412  {
413  if (!selectedItems.contains(item) || item == currentText || item == "")
414  {
415  comboBox->addItem(item);
416  }
417  }
418  comboBox->setCurrentText(currentText);
419 
420  comboBox->blockSignals(false);
421  }
422  }
423  }
424 
425  void PageEngineProperties::handleCellChanged(int irow, int icolumn)
426  {
427  if ((icolumn == 1 && irow >= mTableWidget->rowCount()-2) ||
428  (icolumn == 0 && irow >= mTableWidget->rowCount()-1))
429  mTableWidget->setRowCount(mTableWidget->rowCount()+1);
430  }
431 
433  {
434 
435  QMap<QString, QString> engProp;
436  for (int irow = 0; irow < mTableWidget->rowCount(); ++irow)
437  {
438  QComboBox *comboBox = qobject_cast<QComboBox *>(mTableWidget->cellWidget(irow, 0));
439  if (!comboBox) continue;
440  QString key = comboBox->currentText().trimmed();
441  if (key.isEmpty() || key == "") continue;
442 
443  const QTableWidgetItem *wi = mTableWidget->item(irow, 1);
444  QString value = wi ? wi->text().trimmed() : QString();
445  if (value.isEmpty()) continue;
446 
447  // weißt man dem selben key zwei verschiedene values zu wird die erste überschrieben.
448  engProp[key] = value;
449  }
450  mSettings->setEngineProperties(engProp);
451  mSettings->sync();
452 
453  return true;
454  }
455 
456 
458  : QWizardPage(parent), mController(controller), mDisableToggleHandler(false)
459  {
460  setTitle(tr("Step 4 : Simulation Input Data"));
461  setSubTitle(tr("\nNo input data file selected so far"));
462  setPixmap(QWizard::LogoPixmap, QPixmap(":/icons/sw_select_input","PNG").scaled(128,128));
463 
464 
465  QVBoxLayout* layPage = new QVBoxLayout(this);
466 
467  // radio button to activate file input
468  mRadFile = new QRadioButton("Simulation input from file", this);
469  connect(mRadFile, &QRadioButton::toggled, this, &PageInputData::handleRadioToggled);
470  layPage->addWidget(mRadFile);
471 
472  mFrameFile = new QFrame(this);
474  mFrameFile->setLineWidth(3);
476  layPage->addWidget(mFrameFile);
477  QVBoxLayout* layFile = new QVBoxLayout(mFrameFile);
478  QHBoxLayout* hlayFile = new QHBoxLayout;
479 
480  mEditFilename = new QLineEdit(mFrameFile);
481  connect(mEditFilename, &QLineEdit::textChanged, this, &PageInputData::updateSubtitle);
482  hlayFile->addWidget(mEditFilename);
483 
484  mButFiledialog = new QPushButton(mFrameFile);
485  mButFiledialog->setIcon(gui_utility::getStyledSvgIcon("all->#3192C5", ":/icons/folder", "all->#515050"));
486  mButFiledialog->setIconSize(QSize(17, 17));
487  connect(mButFiledialog, &QPushButton::clicked, this, &PageInputData::openFileBrowser);
488 
489  hlayFile->addWidget(mButFiledialog);
490  layFile->addLayout(hlayFile);
491  layFile->addSpacing(0);
492 
493  // radio button to activate table input
494  mRadEditor = new QRadioButton("Enter simulation input manually", this);
495  connect(mRadEditor, &QRadioButton::toggled, this, &PageInputData::handleRadioToggled);
496  layPage->addWidget(mRadEditor);
497 
498  mFrameTable = new QFrame(this);
500  mFrameTable->setLineWidth(3);
502  layPage->addWidget(mFrameTable);
503  QVBoxLayout* layTable = new QVBoxLayout(mFrameTable);
504  QHBoxLayout* hlayTable = new QHBoxLayout;
505 
506  mDisplayHexValues = new QCheckBox("Display values as hex numbers", mFrameTable);
507  mDisplayHexValues->setChecked(true);
508  hlayTable->addWidget(mDisplayHexValues);
509  hlayTable->addStretch();
510 
511  mButFileimport = new QPushButton("Load data from file");
512  connect(mButFileimport, &QPushButton::clicked, this, &PageInputData::handleFileImport);
513  hlayTable->addWidget(mButFileimport);
514 
515  layTable->addLayout(hlayTable);
516  mTableEditor = new WavedataTableEditor(mFrameTable);
517  connect(mTableEditor, &WavedataTableEditor::lineAdded, this, &PageInputData::updateSubtitle);
518  connect(mDisplayHexValues, &QCheckBox::toggled, mTableEditor, &WavedataTableEditor::setDisplayHexValues);
519  layTable->addWidget(mTableEditor);
520  handleRadioToggled(true);
521  }
522 
524  {
525  // enter clock data must be omitted if clock is autogenerated
526  mTableEditor->setup(mController->get_input_column_headers(), !mController->is_no_clock_used());
527  handleRadioToggled(true);
528  }
529 
530  bool PageInputData::canFileImport(const QString& filename)
531  {
532  if (filename.isEmpty()) return false;
533  if (filename.endsWith("saleae.json")) return true;
534  if (filename.endsWith(".vcd")) return true;
535  if (filename.endsWith(".csv")) return true;
536  return false;
537  }
538 
539  void PageInputData::handleRadioToggled(bool checked)
540  {
541  if (mDisableToggleHandler) return;
542  bool setManualInput = false;
543  if (sender() == mRadEditor)
544  setManualInput = checked;
545  else
546  setManualInput = !checked;
547  mDisableToggleHandler = true;
548  if (setManualInput)
549  {
550  mFrameFile->setEnabled(false);
551  mFrameTable->setEnabled(true);
552  mRadEditor->setChecked(true);
553  mRadFile->setChecked(false);
554  mEditFilename->setEnabled(false);
555  mButFiledialog->setEnabled(false);
556  mButFileimport->setEnabled(canFileImport(mEditFilename->text().toLower()));
557  mDisplayHexValues->setEnabled(true);
558  mTableEditor->setEnabled(true);
559  }
560  else
561  {
562  mFrameFile->setEnabled(true);
563  mFrameTable->setEnabled(false);
564  mRadEditor->setChecked(false);
565  mRadFile->setChecked(true);
566  mEditFilename->setEnabled(true);
567  mButFiledialog->setEnabled(true);
568  mButFileimport->setEnabled(false);
569  mDisplayHexValues->setEnabled(false);
570  mTableEditor->setEnabled(false);
571  }
572  mDisableToggleHandler = false;
573  updateSubtitle();
574  }
575 
576  void PageInputData::openFileBrowser()
577  {
578  QString filter("Simulation data (saleae.json);;"
579  " VCD files (*.vcd);;"
580  " CSV files (*.csv)");
581 
582  QString filename =
583  QFileDialog::getOpenFileName(this, "Load input wave file", ".", filter);
584 
585  if (filename.isEmpty()) return;
586 
587  mEditFilename->setText(filename);
588  updateSubtitle();
589  }
590 
591  void PageInputData::updateSubtitle()
592  {
593  QString fileName = mEditFilename->text();
594  QString subtitle;
595 
596  if (mRadFile->isChecked())
597  {
598  if (fileName.isEmpty())
599  {
600  subtitle = "No input data file selected so far";
601  }
602  else
603  {
604  QFileInfo fileInfo(fileName);
605 
606  if (!fileInfo.isFile() || !fileInfo.isReadable())
607  {
608  subtitle = "File '" + fileName + "' is not readable";
609  }
610  else if (!fileName.toLower().endsWith(".vcd") && !fileName.toLower().endsWith(".csv") && !fileName.endsWith("saleae.json"))
611  {
612  subtitle = "Parsing input files with extension '." + fileInfo.suffix() + "' is not supported";
613  }
614  else
615  {
616  subtitle = "Run simulation with data file '" + fileName + "'";
617  }
618  }
619  }
620  else
621  {
622  int nLines = mTableEditor->validLines();
623  if (nLines < 2)
624  subtitle = "Please enter input data in table below";
625  else
626  subtitle = QString("%1 input events entered in table so far").arg(nLines);
627  }
628  setSubTitle(subtitle);
629  }
630 
631  void PageInputData::handleFileImport()
632  {
633  if (!mController->can_import_data())
634  return;
635 
636  QString filename = mEditFilename->text();
637 
638  if (filename.toLower().endsWith("saleae.json"))
639  {
640  mTableEditor->loadWaveData(filename);
641  return;
642  }
643 
644  SaleaeDirectory sd(mController->get_saleae_directory_filename(),false);
645  sd.clearAll();
646 
647  if (filename.toLower().endsWith(".vcd"))
649  else if (filename.toLower().endsWith(".csv"))
651  else
652  return;
653 
654  mTableEditor->loadWaveData(QString::fromStdString(sd.get_filename()));
655  }
656 
658  {
659  if (mRadFile->isChecked())
660  {
661  QString fileName = mEditFilename->text();
662  if (fileName.isEmpty())
663  {
664  QMessageBox::warning(this, "Error", "Please select a file to load.");
665  return false;
666  }
667 
668  QFileInfo fileInfo(fileName);
669  if (!fileInfo.exists() || !fileInfo.isFile())
670  {
671  QMessageBox::warning(this, "Error", "Please select a valid file to load.");
672  return false;
673  }
674 
675  if (fileName.endsWith("saleae.json"))
676  {
677  SaleaeDirectory externSD(fileName.toStdString(), false);
678 
679  std::unordered_map<Net*, int> lookupTable;
680  for (const Net* inpNet : mController->get_input_nets())
681  {
682  //TODO : keep clock ??
683  int inx = externSD.get_datafile_index(inpNet->get_name(), inpNet->get_id());
684  lookupTable[const_cast<Net*>(inpNet)] = inx;
685  }
686  mController->import_saleae(QFileInfo(fileName).absolutePath().toStdString(), lookupTable);
687  }
688  else if (mController->can_import_data() && fileName.toLower().endsWith(".vcd"))
690  else if (mController->can_import_data() && fileName.toLower().endsWith(".csv"))
692  else
693  {
694  QMessageBox::warning(this, "Error", "Please select a file ending with .vcd or .csv.");
695  log_warning(mController->get_name(), "Cannot parse file '{}' (unknown extension or wrong state).", fileName.toStdString());
696  return false;
697  }
698  }
699  else
700  {
701  if (mTableEditor->validLines() < 2)
702  {
703  QMessageBox::warning(this, "Error", "Not enough input data entered into table");
704  return false;
705  }
706  else
707  {
709  mController->get_waves()->updateFromSaleae();
710  mController->simulate(mTableEditor->maxTime());
711  }
712  }
713 
714  return true;
715  }
716 
718  : SimulationLogReceiver(parent)
719  {
720  mTextEdit = new QTextEdit(parent);
721  layout->addWidget(mTextEdit);
722  }
723 
725  {
726  mTextEdit->moveCursor(QTextCursor::End);
727  mTextEdit->insertHtml(txt);
728  mTextEdit->moveCursor(QTextCursor::End);
729  }
730 
732  {
733  mTextEdit->setHtml(QString::fromUtf8(ff.readAll()));
734  mTextEdit->moveCursor(QTextCursor::End);
735  }
736 
738  : QWizardPage(parent), mController(controller)
739  {
740  setTitle(tr("Step 5 : Run Simulation"));
741  setSubTitle(tr("\nStart simulation based on controller settings from previous steps"));
742  setPixmap(QWizard::LogoPixmap, QPixmap(":/icons/sw_run_simulation","PNG").scaled(128,128));
743 
744  QIcon runIconEnabled = gui_utility::getStyledSvgIcon("all->#20FF80", ":/icons/run");
745  QIcon runIconDisabled = gui_utility::getStyledSvgIcon("all->#808080", ":/icons/run");
746  QIcon runIcon;
747  runIcon.addPixmap(runIconEnabled.pixmap(32),QIcon::Normal);
748  runIcon.addPixmap(runIconDisabled.pixmap(32),QIcon::Disabled);
749  QVBoxLayout* layout = new QVBoxLayout(this);
750  mProcessOutput = new SimulationProcessOutput(this,layout);
751  mStart = new QPushButton("Run Simulation",this);
752  mStart->setIcon(runIcon);
753  connect(mStart,&QPushButton::clicked,this,&PageRunSimulation::handleStartClicked);
754  layout->addWidget(mStart);
755  mState = new QLabel("Ready to start simulation",this);
756  layout->addWidget(mState);
757  setLayout(layout);
758  }
759 
760  void PageRunSimulation::handleStartClicked()
761  {
762  mStart->setDisabled(true);
763  connect(mController,&NetlistSimulatorController::stateChanged,this,&PageRunSimulation::handleStateChanged);
765  mController->setLogReceiver(mProcessOutput);
766  if (!mController->run_simulation())
767  {
768  log_info(mController->get_name(),"Wizzard failed to start simulation");
769  mStart->setEnabled(true);
770  handleStateChanged(mController->get_state());
771  }
772  log_info(mController->get_name(),"Simulation started ...");
774  mLogfile.setFileName(fname);
775  if (mLogfile.open(QIODevice::ReadOnly))
776  {
777  connect(&mLogfile,&QIODevice::readyRead,this,&PageRunSimulation::handleLogfileRead);
778  }
779  }
780 
781  void PageRunSimulation::handleStateChanged(hal::NetlistSimulatorController::SimulationState state)
782  {
783  switch (state) {
784  case NetlistSimulatorController::NoGatesSelected: mState->setText("Controller state: NoGatesSelected"); break;
785  case NetlistSimulatorController::ParameterSetup: mState->setText("Controller state: ParameterSetup"); break;
786  case NetlistSimulatorController::ParameterReady: mState->setText("Ready to start simulation"); break;
787  case NetlistSimulatorController::SimulationRun: mState->setText("Simulation engine running, please wait ..."); break;
788  case NetlistSimulatorController::ShowResults: mState->setText("Simulation successful"); break;
789  case NetlistSimulatorController::EngineFailed: mState->setText("Simulation engine failed"); break;
790  }
791  }
792 
793  void PageRunSimulation::handleLogfileRead()
794  {
795  mProcessOutput->readFile(mLogfile);
796  }
797 
799  {
800  if (!success) return;
801  if (!mController->get_results())
802  log_warning(mController->get_name(), "Cannot get simulation results");
803  handleLogfileRead();
804  handleStateChanged(mController->get_state());
805  }
806 
808  {
809  return (mController->get_state()==NetlistSimulatorController::ShowResults ||
811  }
812 
814  {
815  if (mController->get_state()==NetlistSimulatorController::EngineFailed) return -1;
816  return QWizardPage::nextId();
817  }
818 
820  : QWizardPage(parent), mController(controller), mWaveWidget(ww)
821  {
822  setTitle(tr("Simulation Done : Load Simulation Results"));
823  setSubTitle("\nThis page is not ready yet.\nPlease invoke load results from toolbar.");
824  // setSubTitle("\nSelect simulated waveform to be loaded into viewer. If selection from graphical netlist is preferred please exit wizard, select nets and invoke load results from toolbar");
825  setPixmap(QWizard::LogoPixmap, QPixmap(":/icons/sw_select_results","PNG").scaled(128,128));
826 
827  QGridLayout* layout = new QGridLayout(this);
828 
829  mButAll = new QPushButton("Wave data for all nets", this);
830  layout->addWidget(mButAll,0,0);
831  mButGui = new QPushButton("Only nets selected in GUI", this);
832  layout->addWidget(mButGui,0,1);
833  mButNone = new QPushButton("Clear selection", this);
834  layout->addWidget(mButNone,0,2);
835 
836  mTableView = new QTableView(this);
837  mProxyModel = new QSortFilterProxyModel(this);
838  mWaveModel = new WaveSelectionTable(mTableView);
839  mProxyModel->setSourceModel(mWaveModel);
840  mTableView->setModel(mProxyModel);
841  mTableView->setSortingEnabled(true);
844  QHeaderView* hv = mTableView->horizontalHeader();
848  mTableView->setColumnWidth(0,36);
849  mTableView->setColumnWidth(1,256);
850  mTableView->setColumnWidth(2,36);
851  connect(mButAll,&QPushButton::clicked,mTableView,&QTableView::selectAll);
852  connect(mButGui,&QPushButton::clicked,this,&PageLoadResults::useGuiSelection);
854 
855  layout->addWidget(mTableView,1,0,1,3);
856  }
857 
858  void PageLoadResults::useGuiSelection()
859  {
860  QSet<u32> guiNetSel = gSelectionRelay->selectedNets();
861 
862  const QAbstractItemModel* modl = mTableView->model(); // proxy model
863  int nrows = modl->rowCount();
864  mTableView->clearSelection();
865 
866  bool ok;
867 
868  int n = mTableView->model()->columnCount();
869  for (int irow = 0; irow<nrows; irow++)
870  {
871  u32 gid = modl->data(modl->index(irow,0)).toUInt(&ok);
872  if (!ok) continue;
873  if (guiNetSel.contains(gid))
874  {
875  for (int i=0; i<n; i++)
876  {
877  QModelIndex inx = mTableView->model()->index(irow,i);
879  }
880  }
881  }
882  }
883 
885  {
886  QList<QModelIndex> selIndexList;
887  for (QModelIndex proxyInx : mTableView->selectionModel()->selectedIndexes())
888  {
889  selIndexList.append(mProxyModel->mapToSource(proxyInx));
890  }
891  if (!selIndexList.isEmpty())
892  {
893  WaveDataList* wd = mController->get_waves();
895  mWaveWidget->addSelectedResults(mWaveModel->entryMap(selIndexList));
896  mController->load_waveform_groups(false); // create waveform groups EXCEPT(=false) input groups
897  }
898  return true;
899  }
900 
902  {
903  mWaveModel->setEntryMap(mWaveWidget->addableEntries());
904  }
905 }
Definition: gate.h:58
The GateSelectModel class is the source model for module selection.
The GateSelectProxy class allows sorting and filtering of module tables.
void loadFeature(FacExtensionInterface::Feature ft, const QString &extension=QString())
const std::vector< Gate * > & get_gates() const
Definition: module.cpp:393
Definition: net.h:58
Gate * get_gate_by_id(const u32 gate_id) const
Definition: netlist.cpp:193
Module * get_module_by_id(u32 module_id) const
Definition: netlist.cpp:613
void engineFinished(bool success)
const std::unordered_set< const Gate * > & get_gates() const
bool import_vcd(const std::string &filename, FilterInputFlag filter)
std::vector< InputColumnHeader > get_input_column_headers() const
void add_gates(const std::vector< Gate * > &gates)
void import_csv(const std::string &filename, FilterInputFlag filter, u64 timescale=1000000000)
std::filesystem::path get_saleae_directory_filename() const
void stateChanged(hal::NetlistSimulatorController::SimulationState state)
void add_clock_period(const Net *clock_net, u64 period, bool start_at_zero=true, u64 duration=0)
void setLogReceiver(SimulationLogReceiver *logrec)
WaveData * get_waveform_by_net(const Net *n) const
SimulationEngine * create_simulation_engine(const std::string &name)
void import_saleae(const std::string &dirname, std::unordered_map< Net *, int > lookupTable, u64 timescale=1000000000)
const std::unordered_set< const Net * > & get_input_nets() const
PageClock(NetlistSimulatorController *controller, QWidget *parent=nullptr)
Definition: wizard.cpp:152
virtual bool validatePage() override
Definition: wizard.cpp:222
virtual void initializePage() override
Definition: wizard.cpp:196
PageEngine(NetlistSimulatorController *controller, Wizard *parent=nullptr)
Definition: wizard.cpp:262
virtual bool validatePage() override
Definition: wizard.cpp:285
int nextId() const override
Definition: wizard.cpp:313
PageEngineProperties(SimulationSettings *settings, NetlistSimulatorController *controller, QWidget *parent=nullptr)
Definition: wizard.cpp:326
virtual bool validatePage() override
Definition: wizard.cpp:432
PageInputData(NetlistSimulatorController *controller, QWidget *parent=nullptr)
Definition: wizard.cpp:457
virtual bool validatePage() override
Definition: wizard.cpp:657
virtual void initializePage() override
Definition: wizard.cpp:523
PageLoadResults(NetlistSimulatorController *controller, WaveWidget *ww, QWidget *parent=nullptr)
Definition: wizard.cpp:819
virtual bool validatePage() override
Definition: wizard.cpp:884
virtual void initializePage() override
Definition: wizard.cpp:901
virtual int nextId() const override
Definition: wizard.cpp:813
PageRunSimulation(NetlistSimulatorController *controller, QWidget *parent=nullptr)
Definition: wizard.cpp:737
virtual bool validatePage() override
Definition: wizard.cpp:807
void handleEngineFinished(bool success)
Definition: wizard.cpp:798
void onSelectionChanged(const QItemSelection &selected, const QItemSelection &deselected)
Definition: wizard.cpp:125
PageSelectGates(NetlistSimulatorController *controller, QWidget *parent=nullptr)
Definition: wizard.cpp:38
std::vector< Gate * > selectedGates() const
Definition: wizard.cpp:103
virtual bool validatePage() override
Definition: wizard.cpp:135
GuiPluginTable * mGuiPluginTable
Definition: plugin_relay.h:68
The SaleaeDirectory class provides the API for the SALEAE directory file. The SALEAE directory file w...
int get_datafile_index(const std::string &nam, uint32_t id) const
Get waveform datafile index for net identified by name and id.
void clearAll()
Remove all files and reset internal variables.
The SaleaeDirectoryStoreRequest class is useful to bundle requests for updating SALEAE directory....
const QSet< u32 > & selectedNets() const
const QSet< u32 > & selectedGates() const
const QSet< u32 > & selectedModules() const
static SimulationEngineFactories * instance()
void handleLog(const QString &txt) override
Definition: wizard.cpp:724
void readFile(QFile &ff)
Definition: wizard.cpp:731
SimulationProcessOutput(QWidget *parent, QLayout *layout)
Definition: wizard.cpp:717
QMap< QString, QString > engineProperties() const
void setEngineProperties(const QMap< QString, QString > &engProp)
SaleaeDirectory & saleaeDirectory()
Definition: wave_data.h:242
QMap< WaveSelectionEntry, int > entryMap(const QList< QModelIndex > &indexes) const
void setEntryMap(const QMap< WaveSelectionEntry, int > &entries)
QMap< WaveSelectionEntry, int > addableEntries() const
void addSelectedResults(const QMap< WaveSelectionEntry, int > &sel)
void loadWaveData(const QString &saleaDirectoryFile)
void generateSimulationInput(const QString &workdir)
void setup(const std::vector< NetlistSimulatorController::InputColumnHeader > &inpColHeads, bool omitClock)
Wizard(SimulationSettings *settings, NetlistSimulatorController *controller, WaveWidget *parent)
Definition: wizard.cpp:20
int mPageInputDataId
Definition: wizard.h:39
int mPageEnginePropertiesId
Definition: wizard.h:38
uint32_t u32
Definition: defines.h:41
#define log_info(channel,...)
Definition: log.h:70
#define log_warning(channel,...)
Definition: log.h:76
bool save(std::filesystem::path file_path, GateLibrary *gate_lib, bool overwrite=false)
QIcon getStyledSvgIcon(const QString &from_to_colors_enabled, const QString &svg_path, QString from_to_colors_disabled=QString())
Definition: graphics.cpp:60
Definition: defines.h:45
PluginRelay * gPluginRelay
Definition: plugin_gui.cpp:82
SelectionRelay * gSelectionRelay
Definition: plugin_gui.cpp:83
Netlist * gNetlist
Definition: gui_globals.h:69
bool isChecked() const const
void clicked(bool checked)
void setIcon(const QIcon &icon)
void setIconSize(const QSize &size)
void toggled(bool checked)
virtual int columnCount(const QModelIndex &parent) const const=0
virtual QVariant data(const QModelIndex &index, int role) const const=0
virtual QModelIndex index(int row, int column, const QModelIndex &parent) const const=0
virtual int rowCount(const QModelIndex &parent) const const=0
QAbstractItemModel * model() const const
virtual void selectAll()
void setSelectionBehavior(QAbstractItemView::SelectionBehavior behavior)
void setSelectionMode(QAbstractItemView::SelectionMode mode)
QItemSelectionModel * selectionModel() const const
void addLayout(QLayout *layout, int stretch)
void addSpacing(int size)
void addStretch(int stretch)
void addWidget(QWidget *widget, int stretch, Qt::Alignment alignment)
virtual int count() const const override
virtual QLayoutItem * itemAt(int index) const const override
void setCheckState(Qt::CheckState state)
void stateChanged(int state)
void addItem(const QString &text, const QVariant &userData)
void addItems(const QStringList &texts)
void clear()
void setCurrentIndex(int index)
void currentTextChanged(const QString &text)
void setEditable(bool editable)
int findText(const QString &text, Qt::MatchFlags flags) const const
void insertItem(int index, const QString &text, const QVariant &userData)
QString absoluteFilePath(const QString &fileName) const const
virtual bool open(QIODevice::OpenMode mode) override
void setFileName(const QString &name)
QString getOpenFileName(QWidget *parent, const QString &caption, const QString &dir, const QString &filter, QString *selectedFilter, QFileDialog::Options options)
QString absolutePath() const const
bool exists() const const
bool isFile() const const
void setLineWidth(int)
void setFrameStyle(int style)
void setSectionResizeMode(QHeaderView::ResizeMode mode)
void setStretchLastSection(bool stretch)
void addPixmap(const QPixmap &pixmap, QIcon::Mode mode, QIcon::State state)
QPixmap pixmap(const QSize &size, QIcon::Mode mode, QIcon::State state) const const
void readyRead()
bool hasSelection() const const
virtual void select(const QModelIndex &index, QItemSelectionModel::SelectionFlags command)
QModelIndexList selectedRows(int column) const const
void selectionChanged(const QItemSelection &selected, const QItemSelection &deselected)
void setText(const QString &)
void addWidget(QWidget *w)
virtual QWidget * widget()
void textChanged(const QString &text)
void append(const T &value)
bool isEmpty() const const
QMap::const_iterator constBegin() const const
QMap::const_iterator constEnd() const const
int size() const const
QMessageBox::StandardButton warning(QWidget *parent, const QString &title, const QString &text, QMessageBox::StandardButtons buttons, QMessageBox::StandardButton defaultButton)
bool blockSignals(bool block)
QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
QObject * parent() const const
QObject * sender() const const
QString tr(const char *sourceText, const char *disambiguation, int n)
bool contains(const T &value) const const
QSet::iterator insert(const T &value)
void sync()
virtual QModelIndex mapToSource(const QModelIndex &proxyIndex) const const override
virtual void setSourceModel(QAbstractItemModel *sourceModel) override
void setMaximum(int max)
void setMinimum(int min)
void setValue(int val)
QString arg(qlonglong a, int fieldWidth, int base, QChar fillChar) const const
bool contains(QChar ch, Qt::CaseSensitivity cs) const const
bool endsWith(const QString &s, Qt::CaseSensitivity cs) const const
QString fromStdString(const std::string &str)
QString fromUtf8(const char *str, int size)
bool isEmpty() const const
QString number(int n, int base)
QString toLower() const const
std::string toStdString() const const
QString toUpper() const const
QString trimmed() const const
bool contains(const QString &str, Qt::CaseSensitivity cs) const const
Unchecked
AscendingOrder
void sortByColumn(int column)
QHeaderView * horizontalHeader() const const
void resizeColumnsToContents()
void selectRow(int row)
void setColumnWidth(int column, int width)
virtual void setModel(QAbstractItemModel *model) override
void setSortingEnabled(bool enable)
QHeaderView * verticalHeader() const const
void cellChanged(int row, int column)
QWidget * cellWidget(int row, int column) const const
QTableWidgetItem * item(int row, int column) const const
void setCellWidget(int row, int column, QWidget *widget)
void setColumnCount(int columns)
void setHorizontalHeaderLabels(const QStringList &labels)
void setItem(int row, int column, QTableWidgetItem *item)
void setRowCount(int rows)
QString text() const const
void setHtml(const QString &text)
void insertHtml(const QString &text)
void moveCursor(QTextCursor::MoveOperation operation, QTextCursor::MoveMode mode)
uint toUInt(bool *ok) const const
void setEnabled(bool)
void hide()
QLayout * layout() const const
void setDisabled(bool disable)
void setLayout(QLayout *layout)
void setSizePolicy(QSizePolicy)
void setWindowTitle(const QString &)
int addPage(QWizardPage *page)
virtual int nextId() const const
void setPixmap(QWizard::WizardPixmap which, const QPixmap &pixmap)
void setSubTitle(const QString &subTitle)
void setTitle(const QString &title)