HAL
gatelibrary_tab_truth_table.cpp
Go to the documentation of this file.
2 #include <QLineEdit>
3 
4 #include "gui/gui_globals.h"
8 
9 namespace hal
10 {
11 
13  : GateLibraryTabInterface(parent), mGateType(nullptr)
14  {
15  mLayout = new QGridLayout(this);
16 
17 
18  mLutInit = new GatelibraryLutInit(this);
19  connect(mLutInit, &GatelibraryLutInit::initValueChanged, this, &GateLibraryTabTruthTable::handleLutInitValueChanged);
20  mLayout->addWidget(mLutInit);
21  mLutInit->hide();
22 
23  mTableWidget = new QTableWidget();
24 
25  mDisclaimer = new QLabel(this);
26  mDisclaimer->setAlignment(Qt::AlignCenter);
27  mLayout->addWidget(mDisclaimer);
28  mDisclaimer->hide();
29  mLayout->addWidget(mTableWidget);
30 
31  //mHeaderView = new QHeaderView(Qt::Horizontal);
32  //mTableWidget->setHorizontalHeader(mHeaderView);
33  }
34 
35  void GateLibraryTabTruthTable::setTableSize()
36  {
37  mTableWidget->setColumnCount(getColumnNumber());
38  mTableWidget->setRowCount(getRowNumber());
39  mTableWidget->verticalHeader()->hide();
40 
41  QStringList header;
42  std::vector<std::string> inputs = mGateType->get_input_pin_names();
43  std::vector<std::string> outputs = mGateType->get_output_pin_names();
44  for (const std::string& inputPinName : inputs)
45  header << "Input\n" + QString::fromStdString(inputPinName);
46  for (const std::string& outputPinName : outputs)
47  header << "Output\n" + QString::fromStdString(outputPinName);
48  mTableWidget->setHorizontalHeaderLabels(header);
49  }
50 
51  bool GateLibraryTabTruthTable::updateFlipFlop()
52  {
53  QHash<QString,int> inputColHash;
54  QHash<QString,int> outputColHash;
56  QStringList states;
57  QStringList header;
58  QSet<QString> requiredForOutput;
59  int columnNumber = 0;
60  int icolClock = -1;
61  int icolSet = -1;
62  int icolReset = -1;
63  int rsRows = 0;
64 
65  StateComponent* scomp = mGateType->get_component_as<StateComponent>([](const GateTypeComponent* c) { return StateComponent::is_class_of(c); });
66  if (!scomp) return false;
67  FFComponent* ffcomp = mGateType->get_component_as<FFComponent>([](const GateTypeComponent* c) { return FFComponent::is_class_of(c); });
68  if (!ffcomp) return false;
69 
70  for (auto & [out,bf] : mGateType->get_boolean_functions())
71  for (const std::string& var : bf.get_variable_names())
72  requiredForOutput << QString::fromStdString(var);
73 
74  auto resNextState = ffcomp->get_next_state_function().compute_truth_table();
75  QStringList nextStateInputs;
76  for (const std::string& nsi : ffcomp->get_next_state_function().get_variable_names())
77  nextStateInputs << QString::fromStdString(nsi);
78 
79  if (!resNextState.is_ok() || resNextState.get().size() != 1) return false;
80 
81  // input pins
82  for (GatePin* pin : mGateType->get_input_pins())
83  {
84  QString pinName = QString::fromStdString(pin->get_name());
85  header << "input\n" + QString::fromStdString(enum_to_string<PinType>(pin->get_type())) + "\n" + pinName;
86  switch (pin->get_type()) {
87  case PinType::clock:
88  icolClock = columnNumber;
89  break;
90  case PinType::set:
91  icolSet = columnNumber;
92  ++rsRows;
93  break;
94  case PinType::reset:
95  icolReset = columnNumber;
96  ++rsRows;
97  break;
98  default:
99  break;
100  }
101  inputColHash[pinName] = columnNumber++;
102  }
103 
104  if (rsRows == 2) rsRows = 3;
105 
106  // internal states
107  QStringList tempQ;
108 
109  for (int i=0; i<2; i++)
110  {
111  QString qx = QString::fromStdString(i ? scomp->get_neg_state_identifier()
112  : scomp->get_state_identifier());
113  if (requiredForOutput.contains(qx))
114  tempQ << qx;
115  }
116 
117  for (const QString& qx : tempQ)
118  {
119  header << "last\n" + qx;
120  stateHash[qx] = QPair<int,int>(columnNumber,columnNumber+tempQ.size());
121  inputColHash[qx] = columnNumber++;
122  }
123  for (const QString& qx : tempQ)
124  {
125  header << "next\n" + qx;
126  ++columnNumber;
127  }
128 
129  Q_ASSERT(!stateHash.isEmpty());
130 
131  // output pins
132  for (GatePin* pin : mGateType->get_output_pins())
133  {
134  QString pinName = QString::fromStdString(pin->get_name());
135  header << "output\n" + QString::fromStdString(enum_to_string<PinType>(pin->get_type())) + "\n" + pinName;
136  outputColHash[pinName] = columnNumber++;
137  }
138  mTableWidget->setColumnCount(columnNumber);
139 
140  auto tabNextState = resNextState.get().at(0);
141  mTableWidget->setRowCount(tabNextState.size()+2+rsRows);
142  mTableWidget->setHorizontalHeaderLabels(header);
143 
144  int irow = 0;
145 
146  if (icolSet >= 0)
147  {
148  for (int icol = 0; icol < inputColHash.size(); icol++)
149  {
150  if (icol == icolSet)
151  mTableWidget->setItem(irow, icol, new QTableWidgetItem("H")); // TODO check !S
152  else if (icol == icolReset)
153  mTableWidget->setItem(irow, icol, new QTableWidgetItem("L"));
154  else
155  mTableWidget->setItem(irow, icol, new QTableWidgetItem("X"));
156  }
157  mTableWidget->setItem(irow, stateHash.begin()->first, new QTableWidgetItem("X"));
158 
159  QString qx = "H";
160  mTableWidget->setItem(irow, stateHash.begin()->second, new QTableWidgetItem(qx));
161  for (int icol : outputColHash.values())
162  mTableWidget->setItem(irow, icol, new QTableWidgetItem(qx));
163 
164  ++irow;
165  }
166 
167  if (icolReset >= 0)
168  {
169  for (int icol = 0; icol < inputColHash.size(); icol++)
170  {
171  if (icol == icolSet)
172  mTableWidget->setItem(irow, icol, new QTableWidgetItem("L"));
173  else if (icol == icolReset)
174  mTableWidget->setItem(irow, icol, new QTableWidgetItem("H"));// TODO check !R
175  else
176  mTableWidget->setItem(irow, icol, new QTableWidgetItem("X"));
177  }
178  mTableWidget->setItem(irow, stateHash.begin()->first, new QTableWidgetItem("X"));
179 
180  QString qx = "L";
181  mTableWidget->setItem(irow, stateHash.begin()->second, new QTableWidgetItem(qx));
182  for (int icol : outputColHash.values())
183  mTableWidget->setItem(irow, icol, new QTableWidgetItem(qx));
184  ++irow;
185  }
186 
187  if (icolSet >= 0 && icolReset >= 0)
188  {
189  for (int icol = 0; icol < inputColHash.size(); icol++)
190  {
191  if (icol == icolSet)
192  mTableWidget->setItem(irow, icol, new QTableWidgetItem("H"));
193  else if (icol == icolReset)
194  mTableWidget->setItem(irow, icol, new QTableWidgetItem("H"));// TODO check !R
195  else
196  mTableWidget->setItem(irow, icol, new QTableWidgetItem("X"));
197  }
198  mTableWidget->setItem(irow, stateHash.begin()->first, new QTableWidgetItem("X"));
199 
200  QString qx = QString::fromStdString(enum_to_string<AsyncSetResetBehavior>(ffcomp->get_async_set_reset_behavior().first));
201  mTableWidget->setItem(irow, stateHash.begin()->second, new QTableWidgetItem(qx));
202  for (int icol : outputColHash.values())
203  mTableWidget->setItem(irow, icol, new QTableWidgetItem(qx));
204  ++irow;
205  }
206 
207  for (const BooleanFunction::Value& bfVal : resNextState.get().at(0))
208  {
209  mTableWidget->setItem(irow, stateHash.begin()->first, new QTableWidgetItem("X"));
210  for (int nsiCol = 0; nsiCol < nextStateInputs.size(); nsiCol++)
211  {
212  int icol = inputColHash.value(nextStateInputs.at(nsiCol),-1);
213  Q_ASSERT(icol >= 0);
214  QString cellVal(irow & (1<<nsiCol) ? "H" : "L");
215  mTableWidget->setItem(irow, icol, new QTableWidgetItem(cellVal));
216  }
217  setCellValue(irow,stateHash.begin()->second,bfVal);
218  if (icolClock >= 0)
219  mTableWidget->setItem(irow, icolClock, new QTableWidgetItem("UP")); // arrow up = QString(QChar(0x2191))
220  if (icolReset >= 0)
221  mTableWidget->setItem(irow, icolReset, new QTableWidgetItem("L"));
222  if (icolSet >= 0)
223  mTableWidget->setItem(irow, icolSet, new QTableWidgetItem("L"));
224  for (int icol : outputColHash.values())
225  setCellValue(irow,icol,bfVal);
226  ++irow;
227  }
228 
229  for (int ihold = 0; ihold < 2; ihold++)
230  {
231  for (int nsiCol = 0; nsiCol < nextStateInputs.size(); nsiCol++)
232  {
233  int icol = inputColHash.value(nextStateInputs.at(nsiCol),-1);
234  Q_ASSERT(icol >= 0);
235  mTableWidget->setItem(irow, icol, new QTableWidgetItem("X"));
236  }
237  if (icolClock >= 0)
238  mTableWidget->setItem(irow, icolClock, new QTableWidgetItem("-"));
239  if (icolReset >= 0)
240  mTableWidget->setItem(irow, icolReset, new QTableWidgetItem("L"));
241  if (icolSet >= 0)
242  mTableWidget->setItem(irow, icolSet, new QTableWidgetItem("L"));
243 
244  QString qx = ihold ? "H" : "L";
245  mTableWidget->setItem(irow, stateHash.begin()->first, new QTableWidgetItem(qx));
246  mTableWidget->setItem(irow, stateHash.begin()->second, new QTableWidgetItem(qx));
247  for (int icol : outputColHash.values())
248  mTableWidget->setItem(irow, icol, new QTableWidgetItem(qx));
249  ++irow;
250  }
251 
252  return true;
253  }
254 
255  void GateLibraryTabTruthTable::updateLookupTable()
256  {
257  setTableSize();
258  mLutInit->update(mGateType);
259  }
260 
262  {
263  mGateType = gt;
264 
266  {
267  updateLookupTable();
268  mLutInit->show();
269  mTableWidget->show();
270  mDisclaimer->hide();
271  return;
272  }
273 
274  mLutInit->hide();
275 
276  if (mGateType && mGateType->has_component_of_type(GateTypeComponent::ComponentType::ff))
277  {
278  if (updateFlipFlop())
279  {
280  mTableWidget->show();
281  mDisclaimer->hide();
282  return;
283  }
284  }
285 
286  if(mGateType)
287  {
288  if (getColumnNumber()-1 > 8)
289  {
290  mTableWidget->hide();
291  mDisclaimer->setText(QString("Cannot calculate truth table\nfor gate with %1 input pins\nand %2 output pins")
292  .arg(mGateType->get_input_pins().size())
293  .arg(mGateType->get_output_pins().size()));
294  mDisclaimer->show();
295  }
296  else
297  {
298  bool undefinedResult = false;
299 
300  setTableSize();
301 
302  std::vector<std::string> inputs = mGateType->get_input_pin_names();
303  BooleanFunction boolFunc = mGateType->get_boolean_function();
304  auto truthTable = boolFunc.compute_truth_table(inputs, false).get().at(0);
305 
306  for (uint irow = 0; irow < truthTable.size(); irow++)
307  {
308  //iterate from 0..0 to 1..1
309  for (uint icol = 0; icol < mGateType->get_input_pins().size(); icol++)
310  {
311  u8 inputBit = u8((irow >> icol) & 1);
312  QTableWidgetItem* item = new QTableWidgetItem(inputBit ? "H" : "L");
313  mTableWidget->setItem(irow, icol, item);
314  }
315 
316  //fill the output columns
317  for (uint icol = mGateType->get_input_pins().size(); icol < mGateType->get_output_pins().size()+mGateType->get_input_pins().size(); icol++)
318  {
319  if (!setCellValue(irow,icol,truthTable[irow]))
320  undefinedResult = true;
321  }
322  }
323  if (undefinedResult)
324  {
325  mDisclaimer->setText("Truth table calculation\nfor gate type <" + QString::fromStdString(mGateType->get_name()) + ">\nnot implemented so far");
326  mDisclaimer->show();
327  mTableWidget->hide();
328  }
329  else
330  {
331  mDisclaimer->hide();
332  mTableWidget->show();
333  }
334  }
335  }
336  else
337  {
338  mDisclaimer->setText("No gate type selected");
339  mDisclaimer->show();
340  mTableWidget->hide();
341  }
342  }
343 
344  bool GateLibraryTabTruthTable::setCellValue(int irow, int icol, BooleanFunction::Value bfval)
345  {
346 
347  if (bfval == BooleanFunction::Value::ZERO)
348  {
349  QTableWidgetItem* item = new QTableWidgetItem("L");
350  mTableWidget->setItem(irow, icol, item);
351  }
352  else if (bfval == BooleanFunction::Value::ONE)
353  {
354  QTableWidgetItem* item = new QTableWidgetItem("H");
355  mTableWidget->setItem(irow, icol, item);
356  }
357  else if (bfval == BooleanFunction::Value::Z)
358  {
359  QTableWidgetItem* item = new QTableWidgetItem("Z");
360  mTableWidget->setItem(irow, icol, item);
361  }
362  else
363  {
364  QTableWidgetItem* item = new QTableWidgetItem("X");
365  mTableWidget->setItem(irow, icol, item);
366  return false;
367  }
368  return true;
369  }
370 
371 
372  void GateLibraryTabTruthTable::handleLutInitValueChanged(u64 initValue)
373  {
374  setTableSize();
375 
376  for (int irow = 0; irow < mTableWidget->rowCount(); irow++)
377  {
378  //iterate from 0..0 to 1..1
379  for (uint icol = 0; icol < mGateType->get_input_pins().size(); icol++)
380  {
381  u8 inputBit = u8((irow >> icol) & 1);
382  QTableWidgetItem* item = new QTableWidgetItem(inputBit ? "H" : "L");
383  mTableWidget->setItem(irow, icol, item);
384  }
385 
386  //fill the output columns
387  for (uint icol = mGateType->get_input_pins().size(); icol < mGateType->get_output_pins().size()+mGateType->get_input_pins().size(); icol++)
388  {
389  u64 mask = 1;
390  mask <<= irow;
391  if (initValue & mask)
392  {
393  QTableWidgetItem* item = new QTableWidgetItem("H");
394  mTableWidget->setItem(irow, icol, item);
395  }
396  else
397  {
398  QTableWidgetItem* item = new QTableWidgetItem("L");
399  mTableWidget->setItem(irow, icol, item);
400  }
401  }
402  }
403  mDisclaimer->hide();
404  mTableWidget->show();
405  }
406 
407  int GateLibraryTabTruthTable::getRowNumber() const
408  {
409  return pow(2, mGateType->get_input_pins().size()); //iterate from 0..0 to 2^n
410  }
411 
412  int GateLibraryTabTruthTable::getColumnNumber() const
413  {
414  if(mGateType)
415  {
416  return mGateType->get_input_pins().size()+mGateType->get_output_pins().size();
417  }
418  return 0;
419  }
420 
422  : GatelibraryComponentFrame("LUT init hex value", parent)
423  {
424  mEdit = new QLineEdit(this);
425  connect(mEdit,&QLineEdit::textChanged,this,&GatelibraryLutInit::handleTextChanged);
426  mLayout->addWidget(mEdit);
427  setMaximumHeight(64);
428  }
429 
430  void GatelibraryLutInit::handleTextChanged(const QString& txt)
431  {
432  bool ok;
433  u64 val = txt.toULongLong(&ok,16);
434  if (ok) Q_EMIT initValueChanged(val);
435  }
436 
438  {
440  {
441  auto lut = gt->get_component_as<LUTComponent>([](const GateTypeComponent* c) { return LUTComponent::is_class_of(c); });
442 
443  if (lut != nullptr)
444  {
445  mEdit->setText("1");
447  show();
448  }
449  else
450  hide();
451  }
452  else
453  hide();
454 
455  }
456 }
Result< std::vector< std::vector< Value > > > compute_truth_table(const std::vector< std::string > &ordered_variables={}, bool remove_unknown_variables=false) const
Value
represents the type of the node
static bool is_class_of(const GateTypeComponent *component)
GateLibraryTabTruthTable(QWidget *parent=nullptr)
std::vector< std::string > get_input_pin_names() const
Definition: gate_type.cpp:277
std::vector< GatePin * > get_output_pins() const
Definition: gate_type.cpp:285
const std::string & get_name() const
Definition: gate_type.cpp:64
std::vector< std::string > get_output_pin_names() const
Definition: gate_type.cpp:293
bool has_component_of_type(const GateTypeComponent::ComponentType type) const
Definition: gate_type.cpp:54
std::vector< GatePin * > get_input_pins() const
Definition: gate_type.cpp:269
T * get_component_as(const std::function< bool(const GateTypeComponent *)> &filter=nullptr) const
Definition: gate_type.h:89
BooleanFunction get_boolean_function(const std::string &name) const
Definition: gate_type.cpp:714
const std::unordered_map< std::string, BooleanFunction > & get_boolean_functions() const
Definition: gate_type.cpp:746
GatelibraryLutInit(QWidget *parent=nullptr)
void initValueChanged(u64 initValue)
void update(GateType *gt) override
static bool is_class_of(const GateTypeComponent *component)
static bool is_class_of(const GateTypeComponent *component)
uint64_t u64
Definition: defines.h:42
uint8_t u8
Definition: defines.h:39
void addWidget(QWidget *widget, int row, int column, Qt::Alignment alignment)
QHash::iterator begin()
bool isEmpty() const const
int size() const const
const T value(const Key &key) const const
QList< T > values() const const
void setAlignment(Qt::Alignment)
void setText(const QString &)
void addWidget(QWidget *w)
void setText(const QString &)
void textChanged(const QString &text)
const T & at(int i) 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)
bool contains(const T &value) const const
QString arg(qlonglong a, int fieldWidth, int base, QChar fillChar) const const
QString fromStdString(const std::string &str)
qulonglong toULongLong(bool *ok, int base) const const
AlignCenter
QHeaderView * verticalHeader() const const
void setColumnCount(int columns)
void setHorizontalHeaderLabels(const QStringList &labels)
void setItem(int row, int column, QTableWidgetItem *item)
void setRowCount(int rows)
void hide()
QRegion mask() const const
void setMaximumHeight(int maxh)
void show()
void update()