HAL  v4.5.0-251-g305763a14
The Hardware Analyzer - a comprehensive reverse engineering and manipulation framework for gate-level netlists.
gate_details_tab_widget.cpp
Go to the documentation of this file.
2 
4 #include "gui/gui_globals.h"
13 #include "hal_core/netlist/gate.h"
19 
20 #include <QApplication>
21 #include <QButtonGroup>
22 #include <QHBoxLayout>
23 #include <QRadioButton>
24 #include <QVBoxLayout>
25 #include <QClipboard>
26 #include <QDebug>
28 // temporal debug includes
32 
33 #include <QMenu>
34 
35 namespace hal
36 {
37  namespace
38  {
39  // Returns the hex digits (without "0x") of the INIT parameter of a LUT gate, padded with leading zeros to the
40  // declared width. Falls back to the default of the gate type if the gate holds no instance value.
41  Result<std::string> getLutInitHex(const Gate* gate, const std::string& initKey)
42  {
43  Result<Parameter> decl = gate->has_parameter(initKey) ? gate->get_parameter_declaration(initKey) : gate->get_type()->get_parameter(initKey);
44  if (decl.is_error())
45  {
46  return ERR_APPEND(decl.get_error(), "no INIT parameter '" + initKey + "' declared");
47  }
48 
49  std::string hex = gate->has_parameter(initKey) ? gate->get_parameter_value(initKey).get() : decl.get().get_default_value();
50  if (hex.size() >= 2 && hex[0] == '0' && (hex[1] == 'x' || hex[1] == 'X'))
51  {
52  hex = hex.substr(2);
53  }
54  if (hex.empty())
55  {
56  hex = "0";
57  }
58 
59  const size_t numDigits = (static_cast<size_t>(decl.get().get_size()) + 3) / 4;
60  if (hex.size() < numDigits)
61  {
62  hex.insert(0, numDigits - hex.size(), '0');
63  }
64  return OK(hex);
65  }
66  } // namespace
67 
69  {
71 
72  //general tab
73  mGateInfoTable = new GateInfoTable(this);
74  mGateInformationFrame = new DetailsFrameWidget(mGateInfoTable, "Gate Information", this);
75  addTab("General", mGateInformationFrame, true);
76 
77  //groupings tab
78  mGroupingsOfItemTable = new GroupingsOfItemWidget;
79  mGroupingsFrame = new DetailsFrameWidget(mGroupingsOfItemTable, "Groupings", this); //replace QWidget
80  connect(mGroupingsOfItemTable, &GroupingsOfItemWidget::updateText, mGroupingsFrame, &DetailsFrameWidget::setText);
81  addTab("Groupings", mGroupingsFrame, false);
82 
83  //pins tab
84  mPinsTree = new GatePinTree(this);
85  mPinsFrame = new DetailsFrameWidget(mPinsTree, "Pins", this);
87 
88  addTab("Pins", mPinsFrame, false);
89 
90  //(ff / latch / lut) tab - would love to use seperate tabs, but it's a hassle to hide multiple individual tabs witouth setTabVisible() from qt 5.15
91  mFfFunctionTable = new BooleanFunctionTable(this);
92  mLatchFunctionTable = new BooleanFunctionTable(this);
93  mLutPinButtonGroup = new QButtonGroup(this);
94  mLutPinButtonGroup->setExclusive(true);
95  mLutRadioWidget = new QWidget(this);
96  mLutRadioLayout = new QVBoxLayout(mLutRadioWidget);
97  mLutRadioLayout->setContentsMargins(4, 4, 4, 4);
98  mLutRadioLayout->setSpacing(4);
99  mLutTable = new LUTTableWidget(this);
100  mLutConfigLabel = new QLabel("default", this);
102  mLutConfigLabel->setWordWrap(true);
103  mLutConfigLabel->setStyleSheet(QString("QLabel{color: %1;}").arg(PythonQssAdapter::instance()->numberColor().name())); //tmp.
104  connect(mLutConfigLabel, &QWidget::customContextMenuRequested, this, &GateDetailsTabWidget::handleLutConfigContextMenuRequested);
105 
106  mFfFrame = new DetailsFrameWidget(mFfFunctionTable, "FF Information", this);
107  mLatchFrame = new DetailsFrameWidget(mLatchFunctionTable, "Latch Information", this);
108  mLutFrame = new DetailsFrameWidget(mLutRadioWidget, "Boolean Functions", this);
109  mLutConfigurationFrame = new DetailsFrameWidget(mLutConfigLabel, "Configuration String", this);
110  mTruthTableFrame = new DetailsFrameWidget(mLutTable, "Truth Table", this);
111  // DetailsFrameWidget sets Expanding vertical policy on all content widgets, which causes the
112  // container to distribute vertical space equally. Override for the two compact LUT frames so
113  // they stay at their natural content height and the truth table gets any remaining space.
115  mLutConfigurationFrame->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
116 
117  QList<DetailsFrameWidget*> framesFfLatchLutTab({mFfFrame, mLatchFrame, mLutFrame, mLutConfigurationFrame, mTruthTableFrame});
118  mMultiTabIndex = addTab("(FF / Latch / LUT)", framesFfLatchLutTab); //save index of multi tab -> needed for show / hide
119  mMultiTabContent = widget(mMultiTabIndex); // save content of multi tab -> needed for show / hide
120 
121  //boolean functions tab
122  mFullFunctionTable = new BooleanFunctionTable(this);
123  mFullFunctionTable->setContextMenuPlainDescr(true);
124  mFullFunctionTable->setContextMenuPythonPlainDescr(true);
125  mBooleanFunctionsFrame = new DetailsFrameWidget(mFullFunctionTable, "Boolean Functions", this);
126 
127  addTab("Boolean Functions", mBooleanFunctionsFrame, false);
128  connect(gNetlistRelay, &NetlistRelay::gateBooleanFunctionChanged, this, &GateDetailsTabWidget::handleGateBooleanFunctionChanged);
129 
130  //data tab
131  mDataTable = new DataTableWidget(this);
132  mDataFrame = new DetailsFrameWidget(mDataTable, "Data", this);
133 
134  addTab("Data", mDataFrame, false);
135 
136  //parameter tab
137  mParameterTable = new ParameterTableWidget(this);
138  mParameterFrame = new DetailsFrameWidget(mParameterTable, "Parameters", this);
139 
140  addTab("Parameters", mParameterFrame, false);
141 
142  //comments tab, no frame is used here
143  mCommentWidget = new CommentWidget(this);
144  QTabWidget::addTab(mCommentWidget, "Comments");
145  }
146 
148  {
150 
151  //pass gate or other stuff to widgets
152  mCurrentGate = gate;
153  mGateInfoTable->setGate(gate);
154  mGroupingsOfItemTable->setGate(gate);
155  mPinsTree->setGate(gate);
156  mDataTable->setGate(gate);
157  mParameterTable->setGate(gate);
158  mCommentWidget->nodeChanged(Node(gate->get_id(), Node::NodeType::Gate));
159 
160  // Logic for LUT/FF/LATCH
161  GateDetailsTabWidget::GateTypeCategory gateTypeCategory = getGateTypeCategory(gate);
162  hideOrShorMultiTab(gateTypeCategory);
163  setupBooleanFunctionTables(gate, gateTypeCategory);
164  }
165 
166  void GateDetailsTabWidget::handleGateBooleanFunctionChanged(Gate* g)
167  {
168  if (g == mCurrentGate && g != nullptr)
169  {
170  GateDetailsTabWidget::GateTypeCategory gateTypeCategory = getGateTypeCategory(g);
171  setupBooleanFunctionTables(g, gateTypeCategory);
172  mDataTable->setGate(g);
173  mParameterTable->setGate(g);
174  }
175  }
176 
177  void GateDetailsTabWidget::hideOrShorMultiTab(GateDetailsTabWidget::GateTypeCategory gateTypeCategory)
178  {
179  if (gateTypeCategory != GateDetailsTabWidget::GateTypeCategory::none)
180  {
181  showMultiTab(gateTypeCategory);
182  }
183  else
184  {
185  hideMultiTab();
186  }
187  }
188 
189  void GateDetailsTabWidget::hideMultiTab()
190  {
191  if (mMultiTabVisible)
192  {
193  removeTab(mMultiTabIndex);
194  mMultiTabVisible = false;
195  }
196  }
197 
198  void GateDetailsTabWidget::showMultiTab(GateDetailsTabWidget::GateTypeCategory gateTypeCategory)
199  {
200  QString label = "";
201 
202  switch (gateTypeCategory)
203  {
204  case GateDetailsTabWidget::GateTypeCategory::lut: {
205  mLutFrame->setVisible(true);
206  mLutConfigurationFrame->setVisible(true);
207  mTruthTableFrame->setVisible(true);
208  mFfFrame->setVisible(false);
209  mLatchFrame->setVisible(false);
210  label = "LUT";
211  break;
212  }
213  case GateDetailsTabWidget::GateTypeCategory::ff: {
214  mLutFrame->setVisible(false);
215  mLutConfigurationFrame->setVisible(false);
216  mTruthTableFrame->setVisible(false);
217  mFfFrame->setVisible(true);
218  mLatchFrame->setVisible(false);
219  label = "Flip-Flop";
220  break;
221  }
222  case GateDetailsTabWidget::GateTypeCategory::latch: {
223  mLutFrame->setVisible(false);
224  mLutConfigurationFrame->setVisible(false);
225  mTruthTableFrame->setVisible(false);
226  mFfFrame->setVisible(false);
227  mLatchFrame->setVisible(true);
228  label = "Latch";
229  break;
230  }
231  default:
232  break;
233  }
234 
235  if (!mMultiTabVisible)
236  {
237  insertTab(mMultiTabIndex, mMultiTabContent, label);
238  mMultiTabVisible = true;
239  }
240  else
241  {
242  setTabText(mMultiTabIndex, label);
243  }
244  }
245 
246  GateDetailsTabWidget::GateTypeCategory GateDetailsTabWidget::getGateTypeCategory(Gate* gate) const
247  {
248  if (gate == nullptr)
249  {
250  return GateDetailsTabWidget::GateTypeCategory::none;
251  }
252 
253  GateType* type = gate->get_type();
254 
255  std::set<hal::GateTypeProperty> gateTypeProperties = type->get_properties();
256  std::set<hal::GateTypeProperty> relevantProperties{GateTypeProperty::c_lut, GateTypeProperty::latch, GateTypeProperty::ff};
257 
258  auto relevantFind = find_first_of(begin(gateTypeProperties), end(gateTypeProperties), begin(relevantProperties), end(relevantProperties));
259 
260  if (relevantFind == end(gateTypeProperties))
261  {
262  return GateDetailsTabWidget::GateTypeCategory::none;
263  }
264 
265  switch (*relevantFind)
266  {
268  return GateDetailsTabWidget::GateTypeCategory::lut;
269  break;
270  }
271  case GateTypeProperty::ff: {
272  return GateDetailsTabWidget::GateTypeCategory::ff;
273  break;
274  }
276  return GateDetailsTabWidget::GateTypeCategory::latch;
277  break;
278  }
279  default: {
280  return GateDetailsTabWidget::GateTypeCategory::none;
281  break;
282  }
283  }
284  }
285 
286  void GateDetailsTabWidget::handleLutPinSelectionChanged(int id)
287  {
288  if (mCurrentGate == nullptr || id < 0 || id >= static_cast<int>(mCurrentLutPins.size()))
289  return;
290 
291  const std::string& pinName = mCurrentLutPins[id];
292  mSelectedLutPin = pinName;
293 
294  BooleanFunction bf = mCurrentGate->get_boolean_function(pinName);
295  mLutTable->setBooleanFunction(bf, QString::fromStdString(pinName));
296 
297  GateType* gt = mCurrentGate->get_type();
298 
299  LUTComponent* lut_component = gt->get_component_as<LUTComponent>([](const GateTypeComponent* c) { return LUTComponent::is_class_of(c); });
300  if (lut_component == nullptr)
301  {
302  mLutConfigLabel->setText(" Could not load init string.");
303  return;
304  }
305  const LUTComponent::LUTOutputConfig* cfg = lut_component->get_output_pin_config(pinName);
306  if (cfg == nullptr)
307  {
308  mLutConfigLabel->setText(" Could not load init string.");
309  return;
310  }
311  auto initHex = getLutInitHex(mCurrentGate, cfg->init_identifier);
312  if (initHex.is_error())
313  {
314  mLutConfigLabel->setText(" Could not load init string.");
315  return;
316  }
317  const auto sliceRes = LUTComponent::extract_init_slice(initHex.get(), cfg->bit_offset, cfg->bit_count);
318  const std::string displayHex = sliceRes.is_ok() ? sliceRes.get() : initHex.get();
319  mLutConfigLabel->setText(" 0x" + QString::fromStdString(displayHex));
320  }
321 
322  void GateDetailsTabWidget::handleLutConfigContextMenuRequested(QPoint pos)
323  {
324  // Resolve the INIT parameter and bit slice of the currently selected pin
325  const LUTComponent* lc = mCurrentGate->get_type()->get_component_as<LUTComponent>([](const GateTypeComponent* c) { return LUTComponent::is_class_of(c); });
326  const LUTComponent::LUTOutputConfig* cfg = (lc != nullptr) ? lc->get_output_pin_config(mSelectedLutPin) : nullptr;
327  if (cfg == nullptr)
328  {
329  log_error("gui", "Could not load LUT configuration of pin '{}' from gate with id {}.", mSelectedLutPin, mCurrentGate->get_id());
330  return;
331  }
332  const std::string initKey = cfg->init_identifier;
333  const u32 bitOffset = cfg->bit_offset;
334  const u32 bitCount = cfg->bit_count;
335 
336  QMenu menu;
337 
338  menu.addAction("Configuration string to clipboard", [this]() { QApplication::clipboard()->setText(mLutConfigLabel->text().remove(" 0x")); });
339  menu.addAction("Change configuration string", [this, initKey, bitOffset, bitCount]() {
340  // Strip leading " 0x" from the label to get the current hex digits
341  QString currentHex = mLutConfigLabel->text().trimmed();
342  if (currentHex.startsWith("0x", Qt::CaseInsensitive)) currentHex = currentHex.mid(2);
343 
344  InputDialog ipd("Change configuration string", "New configuration string", currentHex);
345  HexadecimalValidator hexValidator;
346  ipd.addValidator(&hexValidator);
347  if (ipd.exec() != QDialog::Accepted || ipd.textValue().isEmpty()) return;
348 
349  // the slice of the selected pin has a fixed number of digits, shorter input is padded with leading zeros
350  const int numDigits = (bitCount + 3) / 4;
351  QString sliceHex = ipd.textValue().toUpper();
352  if (sliceHex.size() > numDigits)
353  {
354  log_error("gui", "Configuration string '{}' exceeds the {} bits of pin '{}'.", sliceHex.toStdString(), bitCount, mSelectedLutPin);
355  return;
356  }
357  sliceHex = sliceHex.rightJustified(numDigits, '0');
358 
359  auto initHex = getLutInitHex(mCurrentGate, initKey);
360  if (initHex.is_error())
361  {
362  log_error("gui", "Could not load INIT parameter from gate with id {}: {}", mCurrentGate->get_id(), initHex.get_error().get());
363  return;
364  }
365  auto spliceRes = LUTComponent::splice_init_slice(initHex.get(), sliceHex.toStdString(), bitOffset, bitCount);
366  if (spliceRes.is_error())
367  {
368  log_error("gui", "Could not change configuration string of gate with id {}: {}", mCurrentGate->get_id(), spliceRes.get_error().get());
369  return;
370  }
371 
372  ActionSetParameterValue* act = new ActionSetParameterValue(QString::fromStdString(initKey), "0x" + QString::fromStdString(spliceRes.get()));
373  act->setObject(UserActionObject(mCurrentGate->get_id(), UserActionObjectType::Gate));
374  act->exec();
375  setGate(mCurrentGate); // must update config string and parameter table, no signal for that
376  });
377  menu.addAction(QIcon(":/icons/python"), "Get configuration string", [this, initKey]() {
379  });
380 
381  menu.exec(mLutConfigLabel->mapToGlobal(pos));
382  }
383 
384  void GateDetailsTabWidget::setupBooleanFunctionTables(Gate* gate, GateDetailsTabWidget::GateTypeCategory gateTypeCategory)
385  {
386  if (gate == nullptr)
387  {
388  return;
389  }
390 
391  static QSet<QString> ffBfNames = {
392  "clear",
393  "preset", // Both
394  "clock",
395  "clocked_on",
396  "clocked_on_also",
397  "next_state",
398  "power_down_function" // FF names
399  };
400 
401  static QSet<QString> latchBfNames = {
402  "clear",
403  "preset", // Both
404  "enable",
405  "data_in" // Latch names
406  };
407 
408  static QSet<QString> noSpecialBfNames = {};
409 
410  QSet<QString>* specialBfNames = &noSpecialBfNames;
411  if (gateTypeCategory == GateDetailsTabWidget::GateTypeCategory::ff)
412  {
413  specialBfNames = &ffBfNames;
414  }
415  else if (gateTypeCategory == GateDetailsTabWidget::GateTypeCategory::latch)
416  {
417  specialBfNames = &latchBfNames;
418  }
419 
420  std::unordered_map<std::string, BooleanFunction> allBfs = gate->get_boolean_functions(false);
421 
422  QMap<QString, BooleanFunction> specialFunctions;
423  QMap<QString, BooleanFunction> otherFunctions;
424 
425  for (auto& it : allBfs)
426  {
427  QString bfName = QString::fromStdString(it.first);
428  if (specialBfNames->contains(bfName))
429  {
430  // Function is a LUT/FF function
431  specialFunctions.insert(bfName, it.second);
432  }
433  else
434  {
435  // Function is not a LUT/FF function
436  otherFunctions.insert(bfName, it.second);
437  }
438  }
439 
443 
445 
446  for (i = specialFunctions.begin(); i != specialFunctions.end(); i++)
447  specialFunctionList.append(QSharedPointer<BooleanFunctionTableEntry>(new BooleanFunctionEntry(gate->get_id(), i.key(), i.value())));
448 
449  for (i = otherFunctions.begin(); i != otherFunctions.end(); i++)
450  otherFunctionList.append(QSharedPointer<BooleanFunctionTableEntry>(new BooleanFunctionEntry(gate->get_id(), i.key(), i.value())));
451 
452  GateType* gt = gate->get_type();
453  if (FFComponent* ff_component = gt->get_component_as<FFComponent>([](const GateTypeComponent* c) { return FFComponent::is_class_of(c); }); ff_component != nullptr)
454  {
455  if (ff_component->get_async_set_reset_behavior().first != AsyncSetResetBehavior::undef)
456  setPresetBehavior.append(QSharedPointer<BooleanFunctionTableEntry>(new FFComponentEntry(gate->get_id(), ff_component->get_async_set_reset_behavior())));
457  if (!ff_component->get_clock_function().is_empty())
458  setPresetBehavior.append(QSharedPointer<BooleanFunctionTableEntry>(new FFComponentEntry(gate->get_id(), FFComponentEntry::FFCompFunc::Clock, ff_component->get_clock_function())));
459  if (!ff_component->get_next_state_function().is_empty())
460  setPresetBehavior.append(
461  QSharedPointer<BooleanFunctionTableEntry>(new FFComponentEntry(gate->get_id(), FFComponentEntry::FFCompFunc::NextState, ff_component->get_next_state_function())));
462  if (!ff_component->get_async_set_function().is_empty())
463  setPresetBehavior.append(
464  QSharedPointer<BooleanFunctionTableEntry>(new FFComponentEntry(gate->get_id(), FFComponentEntry::FFCompFunc::AsyncSet, ff_component->get_async_set_function())));
465  if (!ff_component->get_async_reset_function().is_empty())
466  setPresetBehavior.append(
467  QSharedPointer<BooleanFunctionTableEntry>(new FFComponentEntry(gate->get_id(), FFComponentEntry::FFCompFunc::AsyncReset, ff_component->get_async_reset_function())));
468  }
469  else if (LatchComponent* latch_component = gt->get_component_as<LatchComponent>([](const GateTypeComponent* c) { return LatchComponent::is_class_of(c); }); latch_component != nullptr)
470  {
471  if (latch_component->get_async_set_reset_behavior().first != AsyncSetResetBehavior::undef)
472  setPresetBehavior.append(QSharedPointer<BooleanFunctionTableEntry>(new LatchComponentEntry(gate->get_id(), latch_component->get_async_set_reset_behavior())));
473  if (!latch_component->get_enable_function().is_empty())
474  setPresetBehavior.append(
475  QSharedPointer<BooleanFunctionTableEntry>(new LatchComponentEntry(gate->get_id(), LatchComponentEntry::LatchCompFunc::Enable, latch_component->get_enable_function())));
476  if (!latch_component->get_data_in_function().is_empty())
477  setPresetBehavior.append(
478  QSharedPointer<BooleanFunctionTableEntry>(new LatchComponentEntry(gate->get_id(), LatchComponentEntry::LatchCompFunc::DataInFunc, latch_component->get_data_in_function())));
479  if (!latch_component->get_async_set_function().is_empty())
480  setPresetBehavior.append(
481  QSharedPointer<BooleanFunctionTableEntry>(new LatchComponentEntry(gate->get_id(), LatchComponentEntry::LatchCompFunc::AsyncSet, latch_component->get_async_set_function())));
482  if (!latch_component->get_async_reset_function().is_empty())
483  setPresetBehavior.append(
484  QSharedPointer<BooleanFunctionTableEntry>(new LatchComponentEntry(gate->get_id(), LatchComponentEntry::LatchCompFunc::AsyncReset, latch_component->get_async_reset_function())));
485  }
486 
487  if (StateComponent* state_component = gt->get_component_as<StateComponent>([](const GateTypeComponent* c) { return StateComponent::is_class_of(c); }); state_component != nullptr)
488  {
489  if (state_component->get_state_identifier() != "")
491  new StateComponentEntry(gate->get_id(), StateComponentEntry::StateCompType::PosState, QString::fromStdString(state_component->get_state_identifier()))));
492  if (state_component->get_neg_state_identifier() != "")
494  new StateComponentEntry(gate->get_id(), StateComponentEntry::StateCompType::NegState, QString::fromStdString(state_component->get_neg_state_identifier()))));
495  }
496 
497  // Fill the category (LUT/FF/LATCH) widgets
498  switch (gateTypeCategory)
499  {
500  case GateDetailsTabWidget::GateTypeCategory::lut: {
501  const std::vector<std::string> lutPins = gate->get_type()->get_pin_names([](const GatePin* p) { return p->get_type() == PinType::lut; });
502 
503  // Clear existing radio buttons and layout
504  const auto existingButtons = mLutPinButtonGroup->buttons();
505  for (QAbstractButton* btn : existingButtons)
506  mLutPinButtonGroup->removeButton(btn);
507  while (QLayoutItem* item = mLutRadioLayout->takeAt(0))
508  {
509  if (QWidget* w = item->widget())
510  w->deleteLater();
511  delete item;
512  }
513  mCurrentLutPins.clear();
514 
515  // Build one radio-button row per LUT output pin
516  int idx = 0;
517  for (const std::string& pin : lutPins)
518  {
519  BooleanFunction bf = gate->get_boolean_function(pin);
520  QString rowText = QString::fromStdString(pin) + " = " + QString::fromStdString(bf.to_string());
521 
522  QWidget* row = new QWidget(mLutRadioWidget);
523  QHBoxLayout* rowLayout = new QHBoxLayout(row);
524  rowLayout->setContentsMargins(0, 0, 0, 0);
525  rowLayout->setSpacing(4);
526 
527  QRadioButton* rb = new QRadioButton(row);
528  mLutPinButtonGroup->addButton(rb, idx);
529 
530  QLabel* fnLabel = new QLabel(rowText, row);
531  fnLabel->setWordWrap(true);
533  connect(fnLabel, &QLabel::customContextMenuRequested, this, [this, pin, fnLabel](QPoint pos) {
534  if (!mCurrentGate) return;
535  const BooleanFunction bf = mCurrentGate->get_boolean_function(pin);
536  const QString bfStr = QString::fromStdString(bf.to_string());
537  const u32 gateId = mCurrentGate->get_id();
538  const QString pinQStr = QString::fromStdString(pin);
539  QMenu menu;
540  menu.addAction("Boolean function to clipboard", [bfStr]() {
542  });
543  menu.addAction("Change Boolean function", [this, pinQStr]() {
544  InputDialog ipd("Change Boolean function", "New function", "");
545  if (ipd.exec() == QDialog::Accepted && !ipd.textValue().isEmpty())
546  {
547  auto funcRes = BooleanFunction::from_string(ipd.textValue().toStdString());
548  if (funcRes.is_ok())
549  {
550  ActionAddBooleanFunction* act = new ActionAddBooleanFunction(pinQStr, funcRes.get(), mCurrentGate->get_id());
551  act->exec();
552  }
553  }
554  });
555  const QString pyCode = PyCodeProvider::pyCodeGateBooleanFunction(gateId, pinQStr);
556  if (!pyCode.isEmpty())
557  menu.addAction(QIcon(":/icons/python"), "Get boolean function", [pyCode]() {
558  QApplication::clipboard()->setText(pyCode);
559  });
560  menu.exec(fnLabel->mapToGlobal(pos));
561  });
562 
563  rowLayout->addWidget(rb, 0, Qt::AlignTop);
564  rowLayout->addWidget(fnLabel, 1);
565  mLutRadioLayout->addWidget(row);
566  mCurrentLutPins.push_back(pin);
567 
568  connect(rb, &QRadioButton::toggled, this, [this, idx](bool checked) {
569  if (checked) handleLutPinSelectionChanged(idx);
570  });
571  ++idx;
572  }
573  mLutRadioLayout->addStretch();
574 
575  // Restore the previously selected pin, falling back to the first pin.
576  int pinToSelect = 0;
577  if (!mSelectedLutPin.empty())
578  {
579  auto it = std::find(mCurrentLutPins.begin(), mCurrentLutPins.end(), mSelectedLutPin);
580  if (it != mCurrentLutPins.end())
581  pinToSelect = static_cast<int>(it - mCurrentLutPins.begin());
582  }
583  if (!mCurrentLutPins.empty())
584  if (QAbstractButton* btn = mLutPinButtonGroup->button(pinToSelect))
585  btn->setChecked(true);
586  break;
587  }
588  case GateDetailsTabWidget::GateTypeCategory::ff: {
589  mFfFunctionTable->setEntries(specialFunctionList + setPresetBehavior);
590  break;
591  }
592  case GateDetailsTabWidget::GateTypeCategory::latch: {
593  mLatchFunctionTable->setEntries(specialFunctionList + setPresetBehavior);
594  break;
595  }
596  default:
597  break;
598  }
599  mFullFunctionTable->setEntries(specialFunctionList + otherFunctionList);
600  }
601 
602 } // namespace hal
static Result< BooleanFunction > from_string(const std::string &expression)
A table view that shows BooleanFunctions and clear-preset behaviors.
void setContextMenuPlainDescr(bool enable)
void setEntries(QVector< QSharedPointer< BooleanFunctionTableEntry >> entries)
void setContextMenuPythonPlainDescr(bool enable)
void nodeChanged(const Node &nd)
A widget to display the data of a DataContainer (Module, Gate or Net)
void setGate(Gate *gate)
void setText(const QString &text)
int addTab(const QString &label, QList< DetailsFrameWidget * > frames)
void setIcon(SelectionDetailsIconProvider::IconCategory catg, u32 itemId=0)
GateDetailsTabWidget(QWidget *parent=nullptr)
Definition: gate.h:59
BooleanFunction get_boolean_function(const std::string &name) const
Definition: gate.cpp:246
GateType * get_type() const
Definition: gate.cpp:162
u32 get_id() const
Definition: gate.cpp:132
void setGate(Gate *gate)
A widget to display the pins of a given gate.
Definition: gate_pin_tree.h:43
void updateText(const QString &newHeadline)
void setGate(u32 gateID)
T * get_component_as(const std::function< bool(const GateTypeComponent *)> &filter=nullptr) const
Definition: gate_type.h:89
A TableView to display all groupings that contain a specified Gate, Net or Module.
void updateText(const QString &text)
static Result< std::string > extract_init_slice(const std::string &full_hex, u32 bit_offset, u32 bit_count)
static Result< std::string > splice_init_slice(const std::string &full_hex, const std::string &slice_hex, u32 bit_offset, u32 bit_count)
static bool is_class_of(const GateTypeComponent *component)
A view for truth-tables (based on the LUTTableModel)
void setBooleanFunction(BooleanFunction bf, QString functionName)
void gateBooleanFunctionChanged(Gate *g) const
The Node class object represents a module or a gate.
Definition: gui_def.h:61
A widget to display the typed parameters of a gate.
void setGate(Gate *gate) const
static QString pyCodeGateBooleanFunction(u32 gateId, QString booleanFunctionName)
static QString pyCodeGateParameterValue(u32 gateId, QString name)
static PythonQssAdapter * instance()
uint32_t u32
Definition: defines.h:41
#define log_error(channel,...)
Definition: log.h:78
#define OK(...)
Definition: result.h:56
#define ERR_APPEND(prev_error, message)
Definition: result.h:64
Definition: defines.h:45
NetlistRelay * gNetlistRelay
Definition: gui_globals.h:74
PinType type
std::string name
i32 id
void toggled(bool checked)
void addStretch(int stretch)
void addWidget(QWidget *widget, int stretch, Qt::Alignment alignment)
void setSpacing(int spacing)
virtual QLayoutItem * takeAt(int index) override
void addButton(QAbstractButton *button, int id)
QAbstractButton * button(int id) const const
QList< QAbstractButton * > buttons() const const
void setExclusive(bool)
void removeButton(QAbstractButton *button)
void setText(const QString &text, QClipboard::Mode mode)
QClipboard * clipboard()
void setText(const QString &)
void setWordWrap(bool on)
void setContentsMargins(int left, int top, int right, int bottom)
const Key & key() const const
T & value() const const
QMap::iterator begin()
QMap::iterator end()
QMap::iterator insert(const Key &key, const T &value)
QAction * addAction(const QString &text)
QAction * exec()
QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
bool contains(const T &value) const const
QString fromStdString(const std::string &str)
bool isEmpty() const const
QString mid(int position, int n) const const
QString rightJustified(int width, QChar fill, bool truncate) const const
int size() const const
bool startsWith(const QString &s, Qt::CaseSensitivity cs) const const
std::string toStdString() const const
QString toUpper() const const
AlignTop
CaseInsensitive
CustomContextMenu
QTextStream & hex(QTextStream &stream)
int addTab(QWidget *page, const QString &label)
int insertTab(int index, QWidget *page, const QString &label)
void removeTab(int index)
void setTabText(int index, const QString &label)
QWidget * widget(int index) const const
void append(const T &value)
QWidget(QWidget *parent, Qt::WindowFlags f)
void setContextMenuPolicy(Qt::ContextMenuPolicy policy)
void customContextMenuRequested(const QPoint &pos)
QPoint mapToGlobal(const QPoint &pos) const const
void setSizePolicy(QSizePolicy)
void setStyleSheet(const QString &styleSheet)
virtual void setVisible(bool visible)