HAL
gate_details_tab_widget.cpp
Go to the documentation of this file.
2 
4 #include "gui/gui_globals.h"
12 #include "hal_core/netlist/gate.h"
18 
19 #include <QApplication>
20 #include <QClipboard>
21 #include <QDebug>
23 // temporal debug includes
26 #include <QMenu>
27 
28 namespace hal
29 {
31  {
33 
34  //general tab
35  mGateInfoTable = new GateInfoTable(this);
36  mGateInformationFrame = new DetailsFrameWidget(mGateInfoTable, "Gate Information", this);
37  addTab("General", mGateInformationFrame, true);
38 
39  //groupings tab
40  mGroupingsOfItemTable = new GroupingsOfItemWidget;
41  mGroupingsFrame = new DetailsFrameWidget(mGroupingsOfItemTable, "Groupings", this); //replace QWidget
42  connect(mGroupingsOfItemTable, &GroupingsOfItemWidget::updateText, mGroupingsFrame, &DetailsFrameWidget::setText);
43  addTab("Groupings", mGroupingsFrame, false);
44 
45  //pins tab
46  mPinsTree = new GatePinTree(this);
47  mPinsFrame = new DetailsFrameWidget(mPinsTree, "Pins", this);
49 
50  addTab("Pins", mPinsFrame, false);
51 
52  //(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
53  mFfFunctionTable = new BooleanFunctionTable(this);
54  mLatchFunctionTable = new BooleanFunctionTable(this);
55  mLutFunctionTable = new BooleanFunctionTable(this);
56  mLutFunctionTable->setContextMenuPlainDescr(true);
57  mLutFunctionTable->setContextMenuPythonPlainDescr(true);
58  mLutFunctionTable->enableChangeBooleanFunctionOption(true);
59  mLutTable = new LUTTableWidget(this);
60  mLutConfigLabel = new QLabel("default", this);
62  mLutConfigLabel->setWordWrap(true);
63  mLutConfigLabel->setStyleSheet(QString("QLabel{color: %1;}").arg(PythonQssAdapter::instance()->numberColor().name())); //tmp.
64  connect(mLutConfigLabel, &QWidget::customContextMenuRequested, this, &GateDetailsTabWidget::handleLutConfigContextMenuRequested);
65 
66  mFfFrame = new DetailsFrameWidget(mFfFunctionTable, "FF Information", this);
67  mLatchFrame = new DetailsFrameWidget(mLatchFunctionTable, "Latch Information", this);
68  mLutFrame = new DetailsFrameWidget(mLutFunctionTable, "Boolean Function", this);
69  mLutConfigurationFrame = new DetailsFrameWidget(mLutConfigLabel, "Configuration String", this);
70  mTruthTableFrame = new DetailsFrameWidget(mLutTable, "Truth Table", this);
71 
72  QList<DetailsFrameWidget*> framesFfLatchLutTab({mFfFrame, mLatchFrame, mLutFrame, mLutConfigurationFrame, mTruthTableFrame});
73  mMultiTabIndex = addTab("(FF / Latch / LUT)", framesFfLatchLutTab); //save index of multi tab -> needed for show / hide
74  mMultiTabContent = widget(mMultiTabIndex); // save content of multi tab -> needed for show / hide
75 
76  //boolean functions tab
77  mFullFunctionTable = new BooleanFunctionTable(this);
78  mFullFunctionTable->setContextMenuPlainDescr(true);
79  mFullFunctionTable->setContextMenuPythonPlainDescr(true);
80  mBooleanFunctionsFrame = new DetailsFrameWidget(mFullFunctionTable, "Boolean Functions", this);
81 
82  addTab("Boolean Functions", mBooleanFunctionsFrame, false);
83  connect(gNetlistRelay, &NetlistRelay::gateBooleanFunctionChanged, this, &GateDetailsTabWidget::handleGateBooleanFunctionChanged);
84 
85  //data tab
86  mDataTable = new DataTableWidget(this);
87  mDataFrame = new DetailsFrameWidget(mDataTable, "Data", this);
88 
89  addTab("Data", mDataFrame, false);
90 
91  //comments tab, no frame is used here
92  mCommentWidget = new CommentWidget(this);
93  QTabWidget::addTab(mCommentWidget, "Comments");
94  }
95 
97  {
99 
100  //pass gate or other stuff to widgets
101  mCurrentGate = gate;
102  mGateInfoTable->setGate(gate);
103  mGroupingsOfItemTable->setGate(gate);
104  mPinsTree->setGate(gate);
105  mDataTable->setGate(gate);
106  mCommentWidget->nodeChanged(Node(gate->get_id(), Node::NodeType::Gate));
107 
108  // Logic for LUT/FF/LATCH
109  GateDetailsTabWidget::GateTypeCategory gateTypeCategory = getGateTypeCategory(gate);
110  hideOrShorMultiTab(gateTypeCategory);
111  setupBooleanFunctionTables(gate, gateTypeCategory);
112  }
113 
114  void GateDetailsTabWidget::handleGateBooleanFunctionChanged(Gate* g)
115  {
116  if (g == mCurrentGate && g != nullptr)
117  {
118  // Update the boolean function table and the LUT. Since we get no information about which BF changed
119  // we need to collect all BFs once again.
120  GateDetailsTabWidget::GateTypeCategory gateTypeCategory = getGateTypeCategory(g);
121  setupBooleanFunctionTables(g, gateTypeCategory);
122  }
123  }
124 
125  void GateDetailsTabWidget::hideOrShorMultiTab(GateDetailsTabWidget::GateTypeCategory gateTypeCategory)
126  {
127  if (gateTypeCategory != GateDetailsTabWidget::GateTypeCategory::none)
128  {
129  showMultiTab(gateTypeCategory);
130  }
131  else
132  {
133  hideMultiTab();
134  }
135  }
136 
137  void GateDetailsTabWidget::hideMultiTab()
138  {
139  if (mMultiTabVisible)
140  {
141  removeTab(mMultiTabIndex);
142  mMultiTabVisible = false;
143  }
144  }
145 
146  void GateDetailsTabWidget::showMultiTab(GateDetailsTabWidget::GateTypeCategory gateTypeCategory)
147  {
148  QString label = "";
149 
150  switch (gateTypeCategory)
151  {
152  case GateDetailsTabWidget::GateTypeCategory::lut: {
153  mLutFrame->setVisible(true);
154  mLutConfigurationFrame->setVisible(true);
155  mTruthTableFrame->setVisible(true);
156  mFfFrame->setVisible(false);
157  mLatchFrame->setVisible(false);
158  label = "LUT";
159  break;
160  }
161  case GateDetailsTabWidget::GateTypeCategory::ff: {
162  mLutFrame->setVisible(false);
163  mLutConfigurationFrame->setVisible(false);
164  mTruthTableFrame->setVisible(false);
165  mFfFrame->setVisible(true);
166  mLatchFrame->setVisible(false);
167  label = "Flip-Flop";
168  break;
169  }
170  case GateDetailsTabWidget::GateTypeCategory::latch: {
171  mLutFrame->setVisible(false);
172  mLutConfigurationFrame->setVisible(false);
173  mTruthTableFrame->setVisible(false);
174  mFfFrame->setVisible(false);
175  mLatchFrame->setVisible(true);
176  label = "Latch";
177  break;
178  }
179  default:
180  break;
181  }
182 
183  if (!mMultiTabVisible)
184  {
185  insertTab(mMultiTabIndex, mMultiTabContent, label);
186  mMultiTabVisible = true;
187  }
188  else
189  {
190  setTabText(mMultiTabIndex, label);
191  }
192  }
193 
194  GateDetailsTabWidget::GateTypeCategory GateDetailsTabWidget::getGateTypeCategory(Gate* gate) const
195  {
196  if (gate == nullptr)
197  {
198  return GateDetailsTabWidget::GateTypeCategory::none;
199  }
200 
201  GateType* type = gate->get_type();
202 
203  std::set<hal::GateTypeProperty> gateTypeProperties = type->get_properties();
204  std::set<hal::GateTypeProperty> relevantProperties{GateTypeProperty::c_lut, GateTypeProperty::latch, GateTypeProperty::ff};
205 
206  auto relevantFind = find_first_of(begin(gateTypeProperties), end(gateTypeProperties), begin(relevantProperties), end(relevantProperties));
207 
208  if (relevantFind == end(gateTypeProperties))
209  {
210  return GateDetailsTabWidget::GateTypeCategory::none;
211  }
212 
213  switch (*relevantFind)
214  {
216  return GateDetailsTabWidget::GateTypeCategory::lut;
217  break;
218  }
219  case GateTypeProperty::ff: {
220  return GateDetailsTabWidget::GateTypeCategory::ff;
221  break;
222  }
224  return GateDetailsTabWidget::GateTypeCategory::latch;
225  break;
226  }
227  default: {
228  return GateDetailsTabWidget::GateTypeCategory::none;
229  break;
230  }
231  }
232  }
233 
234  void GateDetailsTabWidget::handleLutConfigContextMenuRequested(QPoint pos)
235  {
236  QMenu menu;
237 
238  menu.addAction("Configuration string to clipboard", [this]() { QApplication::clipboard()->setText(mLutConfigLabel->text().remove(" 0x")); });
239  menu.addAction("Change configuration string", [this]() {
240  InputDialog ipd("Change configuration string", "New configuration string", mLutConfigLabel->text().remove("0x"));
241  HexadecimalValidator hexValidator;
242  ipd.addValidator(&hexValidator);
243  if (ipd.exec() == QDialog::Accepted && !ipd.textValue().isEmpty())
244  {
245  if (InitComponent* init_component = mCurrentGate->get_type()->get_component_as<InitComponent>([](const GateTypeComponent* c) { return InitComponent::is_class_of(c); });
246  init_component != nullptr)
247  {
248  std::string cat = init_component->get_init_category(), key = init_component->get_init_identifiers()[0];
249  QString data_type = "bit_vector";
250  ActionSetObjectData* act = new ActionSetObjectData(QString::fromStdString(cat), QString::fromStdString(key), data_type, ipd.textValue().toUpper());
251  act->setObject(UserActionObject(mCurrentGate->get_id(), UserActionObjectType::Gate));
252  act->exec();
253  setGate(mCurrentGate); //must update config string and data table, no signal for that
254  }
255  else
256  log_error("gui", "Could not load InitComponent from gate with id {}.", mCurrentGate->get_id());
257  }
258  });
259  menu.addAction(QIcon(":/icons/python"), "Get configuration string", [this]() {
260  if (InitComponent* init_component = mCurrentGate->get_type()->get_component_as<InitComponent>([](const GateTypeComponent* c) { return InitComponent::is_class_of(c); });
261  init_component != nullptr)
262  {
263  std::string cat = init_component->get_init_category(), key = init_component->get_init_identifiers()[0];
265  }
266  else
267  log_error("gui", "Could not load InitComponent from gate with id {}.", mCurrentGate->get_id());
268  });
269 
270  menu.exec(mLutConfigLabel->mapToGlobal(pos));
271  }
272 
273  void GateDetailsTabWidget::setupBooleanFunctionTables(Gate* gate, GateDetailsTabWidget::GateTypeCategory gateTypeCategory)
274  {
275  if (gate == nullptr)
276  {
277  return;
278  }
279 
280  static QSet<QString> ffBfNames = {
281  "clear",
282  "preset", // Both
283  "clock",
284  "clocked_on",
285  "clocked_on_also",
286  "next_state",
287  "power_down_function" // FF names
288  };
289 
290  static QSet<QString> latchBfNames = {
291  "clear",
292  "preset", // Both
293  "enable",
294  "data_in" // Latch names
295  };
296 
297  static QSet<QString> noSpecialBfNames = {};
298 
299  QSet<QString>* specialBfNames = &noSpecialBfNames;
300  if (gateTypeCategory == GateDetailsTabWidget::GateTypeCategory::ff)
301  {
302  specialBfNames = &ffBfNames;
303  }
304  else if (gateTypeCategory == GateDetailsTabWidget::GateTypeCategory::latch)
305  {
306  specialBfNames = &latchBfNames;
307  }
308 
309  std::unordered_map<std::string, BooleanFunction> allBfs = gate->get_boolean_functions(false);
310 
311  QMap<QString, BooleanFunction> specialFunctions;
312  QMap<QString, BooleanFunction> otherFunctions;
313 
314  for (auto& it : allBfs)
315  {
316  QString bfName = QString::fromStdString(it.first);
317  if (specialBfNames->contains(bfName))
318  {
319  // Function is a LUT/FF function
320  specialFunctions.insert(bfName, it.second);
321  }
322  else
323  {
324  // Function is not a LUT/FF function
325  otherFunctions.insert(bfName, it.second);
326  }
327  }
328 
332 
334 
335  for (i = specialFunctions.begin(); i != specialFunctions.end(); i++)
336  specialFunctionList.append(QSharedPointer<BooleanFunctionTableEntry>(new BooleanFunctionEntry(gate->get_id(), i.key(), i.value())));
337 
338  for (i = otherFunctions.begin(); i != otherFunctions.end(); i++)
339  otherFunctionList.append(QSharedPointer<BooleanFunctionTableEntry>(new BooleanFunctionEntry(gate->get_id(), i.key(), i.value())));
340 
341  GateType* gt = gate->get_type();
342  if (FFComponent* ff_component = gt->get_component_as<FFComponent>([](const GateTypeComponent* c) { return FFComponent::is_class_of(c); }); ff_component != nullptr)
343  {
344  if (ff_component->get_async_set_reset_behavior().first != AsyncSetResetBehavior::undef)
345  setPresetBehavior.append(QSharedPointer<BooleanFunctionTableEntry>(new FFComponentEntry(gate->get_id(), ff_component->get_async_set_reset_behavior())));
346  if (!ff_component->get_clock_function().is_empty())
347  setPresetBehavior.append(QSharedPointer<BooleanFunctionTableEntry>(new FFComponentEntry(gate->get_id(), FFComponentEntry::FFCompFunc::Clock, ff_component->get_clock_function())));
348  if (!ff_component->get_next_state_function().is_empty())
349  setPresetBehavior.append(
350  QSharedPointer<BooleanFunctionTableEntry>(new FFComponentEntry(gate->get_id(), FFComponentEntry::FFCompFunc::NextState, ff_component->get_next_state_function())));
351  if (!ff_component->get_async_set_function().is_empty())
352  setPresetBehavior.append(
353  QSharedPointer<BooleanFunctionTableEntry>(new FFComponentEntry(gate->get_id(), FFComponentEntry::FFCompFunc::AsyncSet, ff_component->get_async_set_function())));
354  if (!ff_component->get_async_reset_function().is_empty())
355  setPresetBehavior.append(
356  QSharedPointer<BooleanFunctionTableEntry>(new FFComponentEntry(gate->get_id(), FFComponentEntry::FFCompFunc::AsyncReset, ff_component->get_async_reset_function())));
357  }
358  else if (LatchComponent* latch_component = gt->get_component_as<LatchComponent>([](const GateTypeComponent* c) { return LatchComponent::is_class_of(c); }); latch_component != nullptr)
359  {
360  if (latch_component->get_async_set_reset_behavior().first != AsyncSetResetBehavior::undef)
361  setPresetBehavior.append(QSharedPointer<BooleanFunctionTableEntry>(new LatchComponentEntry(gate->get_id(), latch_component->get_async_set_reset_behavior())));
362  if (!latch_component->get_enable_function().is_empty())
363  setPresetBehavior.append(
364  QSharedPointer<BooleanFunctionTableEntry>(new LatchComponentEntry(gate->get_id(), LatchComponentEntry::LatchCompFunc::Enable, latch_component->get_enable_function())));
365  if (!latch_component->get_data_in_function().is_empty())
366  setPresetBehavior.append(
367  QSharedPointer<BooleanFunctionTableEntry>(new LatchComponentEntry(gate->get_id(), LatchComponentEntry::LatchCompFunc::DataInFunc, latch_component->get_data_in_function())));
368  if (!latch_component->get_async_set_function().is_empty())
369  setPresetBehavior.append(
370  QSharedPointer<BooleanFunctionTableEntry>(new LatchComponentEntry(gate->get_id(), LatchComponentEntry::LatchCompFunc::AsyncSet, latch_component->get_async_set_function())));
371  if (!latch_component->get_async_reset_function().is_empty())
372  setPresetBehavior.append(
373  QSharedPointer<BooleanFunctionTableEntry>(new LatchComponentEntry(gate->get_id(), LatchComponentEntry::LatchCompFunc::AsyncReset, latch_component->get_async_reset_function())));
374  }
375 
376  if (StateComponent* state_component = gt->get_component_as<StateComponent>([](const GateTypeComponent* c) { return StateComponent::is_class_of(c); }); state_component != nullptr)
377  {
378  if (state_component->get_state_identifier() != "")
380  new StateComponentEntry(gate->get_id(), StateComponentEntry::StateCompType::PosState, QString::fromStdString(state_component->get_state_identifier()))));
381  if (state_component->get_neg_state_identifier() != "")
383  new StateComponentEntry(gate->get_id(), StateComponentEntry::StateCompType::NegState, QString::fromStdString(state_component->get_neg_state_identifier()))));
384  }
385 
386  // Fill the category (LUT/FF/LATCH) widgets
387  switch (gateTypeCategory)
388  {
389  case GateDetailsTabWidget::GateTypeCategory::lut: {
390  const std::vector<std::string> lutPins = gate->get_type()->get_pin_names([](const GatePin* p) { return p->get_type() == PinType::lut; });
391  // LUT Boolean Function Table only shows the LUT function
393  for (auto bfEntry : otherFunctionList)
394  {
395  if (std::find(lutPins.begin(), lutPins.end(), bfEntry->getEntryIdentifier().toStdString()) != lutPins.end())
396  {
397  lutEntries.append(bfEntry);
398  }
399  }
400 
401  mLutFunctionTable->setEntries(lutEntries);
402  mLutFunctionTable->setGateInformation(gate);
403 
404  //Setup lut config (init) string
405  if (InitComponent* init_component = gt->get_component_as<InitComponent>([](const GateTypeComponent* c) { return InitComponent::is_class_of(c); }); init_component != nullptr)
406  {
407  auto typeAndValue = gate->get_data(init_component->get_init_category(), init_component->get_init_identifiers()[0]);
408  mLutConfigLabel->setText(" 0x" + QString::fromStdString(std::get<1>(typeAndValue)));
409  }
410  else
411  {
412  mLutConfigLabel->setText(" Could not load init string.");
413  }
414 
415  // The table is only updated if the gate has a LUT pin
416  if (lutPins.size() > 0)
417  {
418  // All LUT pins have the same boolean function
419  std::basic_string<char> outPin = lutPins.front();
420 
421  // Fill the LUL truth table
422  BooleanFunction lutFunction = gate->get_boolean_function(outPin);
423  mLutTable->setBooleanFunction(lutFunction, QString::fromStdString(outPin));
424  }
425  break;
426  }
427  case GateDetailsTabWidget::GateTypeCategory::ff: {
428  mFfFunctionTable->setEntries(specialFunctionList + setPresetBehavior);
429  break;
430  }
431  case GateDetailsTabWidget::GateTypeCategory::latch: {
432  mLatchFunctionTable->setEntries(specialFunctionList + setPresetBehavior);
433  break;
434  }
435  default:
436  break;
437  }
438  mFullFunctionTable->setEntries(specialFunctionList + otherFunctionList);
439  }
440 
441 } // namespace hal
A table view that shows BooleanFunctions and clear-preset behaviors.
void setContextMenuPlainDescr(bool enable)
void setEntries(QVector< QSharedPointer< BooleanFunctionTableEntry >> entries)
void enableChangeBooleanFunctionOption(bool enable)
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:58
GateType * get_type() const
Definition: gate.cpp:125
u32 get_id() const
Definition: gate.cpp:95
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 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
static QString pyCodeGateData(u32 gateId, QString category, QString key)
static PythonQssAdapter * instance()
#define log_error(channel,...)
Definition: log.h:78
NetlistRelay * gNetlistRelay
Definition: plugin_gui.cpp:81
PinType type
std::string name
void setText(const QString &text, QClipboard::Mode mode)
QClipboard * clipboard()
void setWordWrap(bool on)
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)
QString toUpper() const const
CustomContextMenu
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)
void setContextMenuPolicy(Qt::ContextMenuPolicy policy)
void customContextMenuRequested(const QPoint &pos)
QPoint mapToGlobal(const QPoint &pos) const const
void setStyleSheet(const QString &styleSheet)
virtual void setVisible(bool visible)