HAL  v4.5.0-83-g30c8f0afc
The Hardware Analyzer - a comprehensive reverse engineering and manipulation framework for gate-level netlists.
module_model.cpp
Go to the documentation of this file.
2 
3 #include "gui/gui_globals.h"
4 
7 
9 #include "hal_core/netlist/net.h"
10 #include <QMimeData>
11 
12 namespace hal
13 {
14  ModuleModel::ModuleModel(QObject* parent) : BaseTreeModel(parent), mIsModifying(false), mResetInProgress(false)
15  {
16  // use root item to store header information
17  setHeaderLabels(QStringList() << "Name" << "ID" << "Type");
18  connect(gNetlistRelay, &NetlistRelay::moduleCreated, this, &ModuleModel::handleModuleCreated);
19  connect(gNetlistRelay, &NetlistRelay::moduleNameChanged, this, &ModuleModel::handleModuleNameChanged);
20  connect(gNetlistRelay, &NetlistRelay::moduleTypeChanged, this, &ModuleModel::handleModuleTypeChanged);
21  connect(gNetlistRelay, &NetlistRelay::moduleParentChanged, this, &ModuleModel::handleModuleParentChanged);
22  connect(gNetlistRelay, &NetlistRelay::moduleSubmoduleAdded, this, &ModuleModel::handleModuleSubmoduleAdded);
23  connect(gNetlistRelay, &NetlistRelay::moduleSubmoduleRemoved, this, &ModuleModel::handleModuleSubmoduleRemoved);
24  connect(gNetlistRelay, &NetlistRelay::moduleGateAssigned, this, &ModuleModel::handleModuleGateAssigned);
25  connect(gNetlistRelay, &NetlistRelay::moduleGatesAssignBegin, this, &ModuleModel::handleModuleGatesAssignBegin);
26  connect(gNetlistRelay, &NetlistRelay::moduleGatesAssignEnd, this, &ModuleModel::handleModuleGatesAssignEnd);
27  connect(gNetlistRelay, &NetlistRelay::moduleGateRemoved, this, &ModuleModel::handleModuleGateRemoved);
28  connect(gNetlistRelay, &NetlistRelay::moduleRemoved, this, &ModuleModel::handleModuleRemoved);
29  connect(gNetlistRelay, &NetlistRelay::gateNameChanged, this, &ModuleModel::handleGateNameChanged);
30  connect(gNetlistRelay, &NetlistRelay::netCreated, this, &ModuleModel::handleNetCreated);
31  connect(gNetlistRelay, &NetlistRelay::netRemoved, this, &ModuleModel::handleNetRemoved);
32  connect(gNetlistRelay, &NetlistRelay::netNameChanged, this, &ModuleModel::handleNetNameChanged);
33  connect(gNetlistRelay, &NetlistRelay::netSourceAdded, this, &ModuleModel::handleNetUpdated);
34  connect(gNetlistRelay, &NetlistRelay::netSourceRemoved, this, &ModuleModel::handleNetUpdated);
35  connect(gNetlistRelay, &NetlistRelay::netDestinationAdded, this, &ModuleModel::handleNetUpdated);
36  connect(gNetlistRelay, &NetlistRelay::netDestinationRemoved, this, &ModuleModel::handleNetUpdated);
37  }
38 
39  QVariant ModuleModel::data(const QModelIndex& index, int role) const
40  {
41  if (!index.isValid())
42  return QVariant();
43 
44  ModuleItem* item = static_cast<ModuleItem*>(index.internalPointer());
45 
46  if (!item)
47  return QVariant();
48 
49  switch (role)
50  {
51  case Qt::DecorationRole:
52  {
53  if (index.column() == 0)
54  {
55  switch(item->getType()){
62  }
63  }
64  break;
65  }
66  case Qt::DisplayRole:
67  {
68  return item->getData(index.column());
69  }
70  case Qt::ForegroundRole:
71  {
72  if (item->highlighted())
73  return QColor(QColor(255, 221, 0)); // USE STYLESHEETS
74  else
75  return QColor(QColor(255, 255, 255)); // USE STYLESHEETS
76  }
78  return index.column() == 1
80  : Qt::AlignLeft;
81  default:
82  return QVariant();
83  }
84  return QVariant();
85  }
86 
87  QMimeData* ModuleModel::mimeData(const QModelIndexList &indexes) const
88  {
89  QMimeData* retval = new QMimeData;
90  // only single row allowed
91  int row = -1;
92  for (const QModelIndex& inx : indexes)
93  {
94  if (row < 0)
95  row = inx.row();
96  else if (row != inx.row())
97  return retval;
98  }
99  if (row < 0)
100  return retval;
101 
102  QModelIndex firstIndex = indexes.at(0);
103  BaseTreeItem* bti = getItemFromIndex(firstIndex);
104  row = firstIndex.row();
105  BaseTreeItem* parentItem = bti->getParent();
106  ModuleItem* item = dynamic_cast<ModuleItem*>(bti);
107  if (!item)
108  {
109  qDebug() << "cannot cast" << indexes.at(0);
110  return retval;
111  }
112  QByteArray encodedData;
113  QDataStream stream(&encodedData, QIODevice::WriteOnly);
114  QString moveText;
115  int id = item->id();
116 
117  switch (item->getType())
118  {
120  moveText = PyCodeProvider::pyCodeModule(id);
121  break;
123  moveText = PyCodeProvider::pyCodeGate(id);
124  break;
126  moveText = PyCodeProvider::pyCodeNet(id);
127  break;
128  }
129 
130  stream << item->getType() << id << row << (quintptr) parentItem;
131  retval->setText(moveText);
132  retval->setData("modulemodel/item", encodedData);
133  return retval;
134 
135  }
136 
138  {
139  if (!index.isValid())
140  return 0;
141 
143  }
144 
146  {
147  if (index.isValid())
148  return static_cast<ModuleItem*>(index.internalPointer());
149  else
150  return nullptr;
151  }
152 
154  {
155  return mModuleItemMaps[(int)type]->value(id);
156  }
157 
159  {
160  return mModuleItemMaps[(int)type]->values(id);
161  }
162 
164  {
165  beginResetModel();
166 
168  mModuleMap.clear();
169  mGateMap.clear();
170  mNetMap.clear();
171  endResetModel();
172  }
173 
174  void ModuleModel::populateFromGatelist(const std::vector<Gate *> &gates)
175  {
176  setIsModifying(true);
177  beginResetModel();
178  clear();
179 
180  QMap<Module*,ModuleItem*> parentMap;
181  for (const Gate* g : gates)
182  {
183  Module* parentModule = g->get_module();
184  ModuleItem* parentItem;
185  bool insertToRoot = true;
186  ModuleItem* childItem = new ModuleItem(g->get_id(), ModuleItem::TreeItemType::Gate, this);
187 
188  while (parentModule && insertToRoot)
189  {
190  parentItem = parentMap.value(parentModule);
191  if (!parentItem)
192  {
193  parentItem = new ModuleItem(parentModule->get_id(), ModuleItem::TreeItemType::Module, this);
194  parentMap.insert(parentModule, parentItem);
195  }
196  else
197  {
198  insertToRoot = false;
199  }
200  parentItem->appendChild(childItem);
201  parentModule = parentModule->get_parent_module();
202  childItem = parentItem;
203  }
204 
205  if (insertToRoot)
206  {
207  mRootItem->appendChild(parentItem);
208  }
209  }
210 
211  setIsModifying(false);
212  endResetModel();
213  }
214 
215  void ModuleModel::populateTree(const QVector<u32>& modIds, const QVector<u32>& gateIds, const QVector<u32>& netIds)
216  {
217  setIsModifying(true);
218  mResetInProgress = true;
219  beginResetModel();
220  // Might want to add parameter for container of moduleIds that don't get recursively inserted.
221  clear();
222 
223  QList<ModuleItem*> newRootList;
224  for(u32 id : modIds)
227 
228  for(u32 id : gateIds)
229  newRootList.append(new ModuleItem(id, ModuleItem::TreeItemType::Gate, this));
230 
231  for(u32 id : netIds)
232  newRootList.append(new ModuleItem(id, ModuleItem::TreeItemType::Net, this));
233 
234  for(auto item : newRootList)
235  mRootItem->appendChild(item);
236  mResetInProgress = false;
237  setIsModifying(false);
238  endResetModel();
239  }
240 
241  void ModuleModel::addModule(u32 id, u32 parentId)
242  {
243  Q_ASSERT(gNetlist->get_module_by_id(id));
244  Q_ASSERT(gNetlist->get_module_by_id(parentId));
245 
246  for (auto it = mModuleMap.lowerBound(parentId); it != mModuleMap.upperBound(parentId); ++it)
247  {
248  ModuleItem* parentItem = it.value();
250  }
251  }
252 
253  void ModuleModel::addGate(u32 id, u32 parentId)
254  {
255  Q_ASSERT(gNetlist->get_gate_by_id(id));
256  Q_ASSERT(gNetlist->get_module_by_id(parentId));
257 
258 
259  for (auto it = mModuleMap.lowerBound(parentId); it != mModuleMap.upperBound(parentId); ++it)
260  {
262  }
263  }
264 
265  void ModuleModel::addNet(u32 id, u32 parentId)
266  {
267  Q_ASSERT(gNetlist->get_net_by_id(id));
268  Q_ASSERT(gNetlist->get_module_by_id(parentId));
269 
270  for (auto it = mModuleMap.lowerBound(parentId); it != mModuleMap.upperBound(parentId); ++it)
271  {
273  }
274  }
275 
277  {
278  Q_ASSERT(module);
279  ModuleItem* moduleItem = createChildItem(module->get_id(), ModuleItem::TreeItemType::Module, parentItem ? parentItem : mRootItem);
280  Q_ASSERT(moduleItem);
281  for(const Module* subModule : module->get_submodules())
282  addRecursively(subModule, moduleItem);
283 
284  for(const Gate* g : module->get_gates())
285  createChildItem(g->get_id(), ModuleItem::TreeItemType::Gate, moduleItem);
286  }
287 
289  {
290  QList<ModuleItem*> trashcan; // access items to delete without map
291 
292  for (auto it = mModuleMap.lowerBound(id); it != mModuleMap.upperBound(id); ++it)
293  trashcan.append(it.value());
294 
295  for (ModuleItem* item : trashcan)
296  {
297  BaseTreeItem* parentItem = item->getParent();
298  removeChildItem(item,parentItem);
299  }
300  }
301 
303  {
304  QList<ModuleItem*> trashcan; // access items to delete without map
305 
306  for (auto it = mGateMap.lowerBound(id); it != mGateMap.upperBound(id); ++it)
307  trashcan.append(it.value());
308 
309  for (ModuleItem* item : trashcan)
310  {
311  BaseTreeItem* parentItem = item->getParent();
312  removeChildItem(item,parentItem);
313  }
314  }
315 
317  {
318  QList<ModuleItem*> trashcan; // access items to delete without map
319 
320  for (auto it = mNetMap.lowerBound(id); it != mNetMap.upperBound(id); ++it)
321  trashcan.append(it.value());
322 
323  for (ModuleItem* item : trashcan)
324  {
325  BaseTreeItem* parentItem = item->getParent();
326  removeChildItem(item,parentItem);
327  }
328  }
329 
331  {
332  ModuleItem* retval = new ModuleItem(id, itemType, this);
333 
334  if (!parentItem) parentItem = mRootItem;
335 
336  if (mResetInProgress)
337  {
338  // the enclosing model reset already makes the views re-read everything. Emitting row signals in
339  // between is undefined behavior and would make an attached proxy re-map its rows for every item.
340  parentItem->appendChild(retval);
341  return retval;
342  }
343 
344  QModelIndex index = getIndexFromItem(parentItem);
345  int row = parentItem->getChildCount();
346  const bool wasModifying = mIsModifying;
347  mIsModifying = true;
348  beginInsertRows(index, row, row);
349  parentItem->appendChild(retval);
350  endInsertRows();
351  mIsModifying = wasModifying;
352 
353  return retval;
354  }
355 
356  void ModuleModel::removeChildItem(ModuleItem *itemToRemove, BaseTreeItem *parentItem)
357  {
358  Q_ASSERT(itemToRemove);
359  Q_ASSERT(parentItem);
360 
361  while (itemToRemove->getChildCount())
362  {
363  ModuleItem* childItem = static_cast<ModuleItem*>(itemToRemove->getChildren().at(0));
364  removeChildItem(childItem,itemToRemove);
365  }
366 
367  if (mResetInProgress)
368  {
369  // see createChildItem(), the enclosing model reset covers this removal
370  parentItem->removeChild(itemToRemove);
371  delete itemToRemove;
372  return;
373  }
374 
375  QModelIndex index = getIndexFromItem(parentItem);
376 
377  int row = itemToRemove->getOwnRow();
378 
379  const bool wasModifying = mIsModifying;
380  mIsModifying = true;
381  beginRemoveRows(index, row, row);
382  parentItem->removeChild(itemToRemove);
383  endRemoveRows();
384  mIsModifying = wasModifying;
385 
386  delete itemToRemove;
387  }
388 
389  void ModuleModel::handleModuleNameChanged(Module* mod)
390  {
391  updateModuleName(mod->get_id());
392  }
393 
394  void ModuleModel::handleModuleTypeChanged(Module* mod)
395  {
396  updateModuleType(mod->get_id());
397  }
398 
399  void ModuleModel::handleModuleRemoved(Module* mod)
400  {
401  removeModule(mod->get_id());
402  }
403 
404  void ModuleModel::handleModuleCreated(Module* mod)
405  {
406  if (mod->get_parent_module() == nullptr) return;
407  addModule(mod->get_id(), mod->get_parent_module()->get_id());
408  }
409 
410  void ModuleModel::handleModuleGateAssigned(Module* mod, u32 gateId)
411  {
412  if (mTempGateAssignment.isAccumulate())
413  mTempGateAssignment.assignGateToModule(gateId,mod);
414  else
415  {
416  moduleAssignGate(mod->get_id(), gateId);
417  moduleAssignNets({gateId});
418  }
419  }
420 
421  void ModuleModel::handleModuleGateRemoved(Module* mod, u32 gateId)
422  {
423  QList<QPair<ModuleItem*,ModuleItem*> > trashcan; // item to delete, parent
424 
425  if (mTempGateAssignment.isAccumulate())
426  mTempGateAssignment.removeGateFromModule(gateId,mod);
427  else
428  {
429  for (auto it = mGateMap.lowerBound(gateId); it != mGateMap.upperBound(gateId); ++it)
430  {
431  ModuleItem* item = it.value();
432  if (item->isToplevelItem()) continue;;
433 
434  ModuleItem* parentItem = static_cast<ModuleItem*>(item->getParent());
435  if (parentItem->id() == mod->get_id())
436  trashcan.append(QPair<ModuleItem*,ModuleItem*>(item, parentItem));
437  }
438  }
439 
440  for (const QPair<ModuleItem*,ModuleItem*>& trash : trashcan)
441  removeChildItem(trash.first, trash.second);
442  }
443 
444  void ModuleModel::handleModuleGatesAssignBegin(Module* mod, u32 numberGates)
445  {
446  Q_UNUSED(mod);
447  Q_UNUSED(numberGates);
448  mTempGateAssignment.beginAccumulate();
449  }
450 
451  void ModuleModel::handleModuleGatesAssignEnd(Module* mod, u32 numberGates)
452  {
453  Q_UNUSED(mod);
454  Q_UNUSED(numberGates);
455  mTempGateAssignment.endAccumulate();
456  if (!mTempGateAssignment.isAccumulate())
457  {
458  for (auto it = mTempGateAssignment.mGateAssign.begin(); it != mTempGateAssignment.mGateAssign.end(); ++it)
459  {
460  moduleAssignGate(it.value()->get_id(), it.key()); // moduleId, gateId
461  }
462  moduleAssignNets(mTempGateAssignment.mGateAssign.keys());
463  mTempGateAssignment.mGateAssign.clear();
464  mTempGateAssignment.mGateRemove.clear();
465  }
466  }
467 
468  void ModuleModel::handleGateRemoved(Gate* gat)
469  {
470  removeGate(gat->get_id());
471  }
472 
473  void ModuleModel::handleGateCreated(Gate* gat)
474  {
475  Module* mod = gat->get_module();
476  if (mod) moduleAssignGate(mod->get_id(), gat->get_id());
477  }
478 
479  void ModuleModel::handleGateNameChanged(Gate* gat)
480  {
481  updateGateName(gat->get_id());
482  }
483 
484  void ModuleModel::handleNetCreated(Net* net)
485  {
486  addNet(net->get_id(), gNetlist->get_top_module()->get_id());
487  }
488 
489  void ModuleModel::handleNetRemoved(Net* net)
490  {
491  removeNet(net->get_id());
492  }
493 
494  void ModuleModel::handleNetNameChanged(Net* net)
495  {
496  updateNetName(net->get_id());
497  }
498 
499  void ModuleModel::handleNetUpdated(Net* net, u32 data)
500  {
501  Q_UNUSED(data);
503  }
504 
505  void ModuleModel::handleModuleParentChanged(const Module* mod)
506  {
507  Q_ASSERT(mod);
508  updateModuleParent(mod);
509 
510  QHash<const Net*,ModuleItem*> parentAssignment;
511  std::unordered_set<Net*> assignedNets;
512  findNetParentRecursion(mRootItem, parentAssignment, assignedNets);
513 
514  for(Net* net : mod->get_nets())
515  updateNetParent(net, &parentAssignment);
516  }
517 
518  void ModuleModel::handleModuleSubmoduleAdded(Module* mod, u32 submodId)
519  {
520  Q_UNUSED(mod);
521  Q_UNUSED(submodId);
522  }
523 
524  void ModuleModel::handleModuleSubmoduleRemoved(Module* mod, u32 submodId)
525  {
526  Q_UNUSED(mod);
527  Q_UNUSED(submodId);
528  }
529 
530  void ModuleModel::findNetParentRecursion(BaseTreeItem* parent, QHash<const Net *, ModuleItem *> &parentAssignment, std::unordered_set<Net*>& assignedNets) const
531  {
532  for (BaseTreeItem* bti : parent->getChildren())
533  {
534  ModuleItem* item = dynamic_cast<ModuleItem*>(bti);
535  if (!item || item->getType() != ModuleItem::TreeItemType::Module) continue;
536  findNetParentRecursion(item, parentAssignment, assignedNets);
537  Module* m = gNetlist->get_module_by_id(item->id());
538  Q_ASSERT(m);
539  std::unordered_set<Net*> internalNets = m->get_nets();
540  if (!internalNets.empty())
541  {
542  for (Net* n : assignedNets)
543  internalNets.erase(n);
544  for (Net* n : m->get_input_nets())
545  internalNets.erase(n);
546  for (Net* n : m->get_output_nets())
547  internalNets.erase(n);
548  }
549  for (Net* n : internalNets)
550  {
551  parentAssignment[n] = item;
552  assignedNets.insert(n);
553  }
554  }
555  }
556 
557  Module* ModuleModel::findNetParent(const Net *net) const
558  {
559  QHash<Module*,int> modHash;
560  if (net->is_global_input_net() || net->is_global_output_net()) return nullptr;
561  int maxDepth = 0;
562 
563  for (const Endpoint* ep : net->get_sources())
564  {
565  Module* m = ep->get_gate()->get_module();
566  Q_ASSERT(m);
567  int depth = m->get_submodule_depth();
568  if (depth > maxDepth) maxDepth = depth;
569  modHash.insert(m,depth);
570  }
571 
572  for (const Endpoint* ep : net->get_destinations())
573  {
574  Module* m = ep->get_gate()->get_module();
575  Q_ASSERT(m);
576  int depth = m->get_submodule_depth();
577  if (depth > maxDepth) maxDepth = depth;
578  modHash.insert(m,depth);
579  }
580 
581  while (modHash.size() > 1 && maxDepth > 0)
582  {
583  auto it = modHash.begin();
584  while (it != modHash.end())
585  {
586  if (it.value() == maxDepth)
587  {
588  Module* parentMod = it.key()->get_parent_module();
589  modHash.erase(it);
590  if (parentMod) modHash.insert(parentMod,maxDepth-1);
591  break;
592  }
593  ++it;
594  }
595  if (it == modHash.end())
596  --maxDepth;
597  }
598  if (modHash.empty()) return nullptr;
599  return modHash.begin().key();
600  }
601 
602  void ModuleModel::moduleAssignGate(const u32 moduleId, const u32 gateId)
603  {
604  // Don't need new function handleModuleGateRemoved(), because the GateAssinged event always follows GateRemoved
605  // or NetlistInternalManager updates Net connections when a gate is deleted.
606 
607  QSet<ModuleItem*> parentsHandled;
608  Q_ASSERT(gNetlist->get_gate_by_id(gateId));
609 
610  QList<QPair<ModuleItem*,ModuleItem*> > trashcan; // item to delete, parent
611  for (auto itGat = mGateMap.lowerBound(gateId); itGat != mGateMap.upperBound(gateId); ++itGat)
612  {
613  ModuleItem* gatItem = itGat.value();
614  if (gatItem->isToplevelItem()) continue;
615  ModuleItem* oldParentItem = static_cast<ModuleItem*>(gatItem->getParent());
616  Q_ASSERT(oldParentItem);
617 
618  if (oldParentItem->id() != moduleId)
619  {
620  trashcan.append(QPair<ModuleItem*,ModuleItem*>(gatItem,oldParentItem));
621  }
622  else
623  {
624  parentsHandled.insert(oldParentItem);
625  }
626  }
627  for (const QPair<ModuleItem*,ModuleItem*>& trash : trashcan)
628  removeChildItem(trash.first, trash.second);
629 
630  if (!moduleId) return;
631  for (auto itMod = mModuleMap.lowerBound(moduleId); itMod != mModuleMap.upperBound(moduleId); ++itMod)
632  {
633  ModuleItem* parentItem = itMod.value();
634  if (parentsHandled.contains(parentItem)) continue;
635  createChildItem(gateId, ModuleItem::TreeItemType::Gate, parentItem);
636  }
637 
638  }
639 
641  {
642  QHash<const Net*,ModuleItem*> parentAssignment;
643  std::unordered_set<Net*> assignedNets;
644  findNetParentRecursion(mRootItem, parentAssignment, assignedNets);
645 
646  QSet<const Net*> netsToAssign;
647  if (gateIds.isEmpty())
648  {
649 #if (QT_VERSION >= QT_VERSION_CHECK(5, 14, 0))
650  QList<const Net*> tempKeys = parentAssignment.keys();
651  netsToAssign = QSet(tempKeys.begin(),tempKeys.end());
652 #else
653  netsToAssign = parentAssignment.keys().toSet();
654 #endif
655  }
656  else
657  {
658  for (u32 id : gateIds)
659  {
660  Gate* gate = gNetlist->get_gate_by_id(id);
661  for(Net* in_net : gate->get_fan_in_nets())
662  netsToAssign.insert(in_net);
663  for(Net* out_net : gate->get_fan_out_nets())
664  netsToAssign.insert(out_net);
665  }
666  }
667 
668  for (const Net* n: netsToAssign)
669  updateNetParent(n, &parentAssignment);
670  }
671 
673  {
674  Q_ASSERT(net);
675  u32 netId = net->get_id();
676 
677  QSet<ModuleItem*> parentsHandled;
678  u32 newParentId = 0;
679  if (parentAssignment)
680  {
681  ModuleItem* modItem = parentAssignment->value(net);
682  if (modItem)
683  newParentId = modItem->id();
684  }
685  else
686  {
687  Module* newParentModule = findNetParent(net);
688  if (newParentModule)
689  newParentId = newParentModule->get_id();
690  }
691 
692  QList<QPair<ModuleItem*,ModuleItem*> > trashcan; // item to delete, parent
693 
694  for (auto itNet = mNetMap.lowerBound(netId); itNet != mNetMap.upperBound(netId); ++itNet)
695  {
696  if (itNet.value()->isToplevelItem()) continue;
697 
698  ModuleItem* netItem = itNet.value();
699  ModuleItem* oldParentItem = static_cast<ModuleItem*>(netItem->getParent());
700  Q_ASSERT(oldParentItem);
701 
702  if (newParentId == 0 || newParentId != oldParentItem->id())
703  {
704  trashcan.append(QPair<ModuleItem*,ModuleItem*>(netItem,oldParentItem));
705  break;
706  }
707  else
708  {
709  parentsHandled.insert(oldParentItem);
710  }
711  }
712 
713  for (const QPair<ModuleItem*,ModuleItem*>& trash : trashcan)
714  removeChildItem(trash.first, trash.second);
715 
716  if (!newParentId) return;
717  for (auto itMod = mModuleMap.lowerBound(newParentId); itMod != mModuleMap.upperBound(newParentId); ++itMod)
718  {
719  ModuleItem* parentItem = itMod.value();
720  if (parentsHandled.contains(parentItem)) continue;
721  createChildItem(net->get_id(), ModuleItem::TreeItemType::Net, parentItem);
722  }
723  }
724 
726  {
727  ModuleItem* moduleItemToBeMoved = nullptr;
728  bool moduleItemReassigned = false;
729 
730  Q_ASSERT(module);
731  u32 id = module->get_id();
732  Q_ASSERT(id != 1);
733 
734  QSet<ModuleItem*> parentsHandled;
735  u32 parentId = module->get_parent_module()->get_id();
736  Q_ASSERT(parentId > 0);
737 
738  QList<QPair<ModuleItem*,ModuleItem*> > trashcan; // item to delete, parent
739 
740  for (auto itSubm = mModuleMap.lowerBound(id); itSubm != mModuleMap.upperBound(id); ++itSubm)
741  {
742  ModuleItem* submItem = itSubm.value();
743  if (submItem->isToplevelItem()) continue;
744 
745  ModuleItem* oldParentItem = static_cast<ModuleItem*>(submItem->getParent());
746  Q_ASSERT(oldParentItem);
747 
748  if (oldParentItem->id() != parentId)
749  {
750  if (moduleItemToBeMoved)
751  {
752  // remove tree item recursively
753  trashcan.append(QPair<ModuleItem*,ModuleItem*>(submItem,oldParentItem));
754  }
755  else
756  {
757  // save tree item for reassignment
758  moduleItemToBeMoved = submItem;
759  QModelIndex index = getIndexFromItem(oldParentItem);
760 
761  int row = submItem->getOwnRow();
762 
763  mIsModifying = true;
764  beginRemoveRows(index, row, row);
765  oldParentItem->removeChild(submItem);
766  endRemoveRows();
767  mIsModifying = false;
768  }
769  }
770  else
771  {
772  parentsHandled.insert(oldParentItem);
773  }
774  }
775  for (const QPair<ModuleItem*,ModuleItem*>& trash : trashcan)
776  removeChildItem(trash.first, trash.second);
777 
778  if (!parentId) return;
779  for (auto itMod = mModuleMap.lowerBound(parentId); itMod != mModuleMap.upperBound(parentId); ++itMod)
780  {
781  ModuleItem* parentItem = itMod.value();
782  if (parentsHandled.contains(parentItem)) continue;
783  if (moduleItemToBeMoved && !moduleItemReassigned)
784  {
785  QModelIndex index = getIndexFromItem(parentItem);
786  int row = parentItem->getChildCount();
787  mIsModifying = true;
788  beginInsertRows(index, row, row);
789  parentItem->appendChild(moduleItemToBeMoved);
790  endInsertRows();
791  mIsModifying = false;
792  moduleItemReassigned = true;
793  }
794  else
795  {
796  addRecursively(module, parentItem);
797  }
798  }
799 
800  if (moduleItemToBeMoved && !moduleItemReassigned)
801  {
802  removeChildItem(moduleItemToBeMoved, moduleItemToBeMoved->getParent());
803  }
804 
805  }
806 
808  {
809  Q_ASSERT(gNetlist->get_module_by_id(id));
810 
811  for (auto it = mModuleMap.lowerBound(id); it != mModuleMap.upperBound(id); ++it)
812  {
813  ModuleItem* item = it.value();
814  Q_ASSERT(item);
815 
817 
820  }
821  }
822 
824  {
825  Q_ASSERT(gNetlist->get_module_by_id(id));
826 
827  for (auto it = mModuleMap.lowerBound(id); it != mModuleMap.upperBound(id); ++it)
828  {
829  ModuleItem* item = it.value();
830  Q_ASSERT(item);
831 
833 
836  }
837  }
838 
840  {
841  Q_ASSERT(gNetlist->get_gate_by_id(id));
842 
843  for (auto it = mGateMap.lowerBound(id); it != mGateMap.upperBound(id); ++it)
844  {
845  ModuleItem* item = it.value();
846  Q_ASSERT(item);
847 
848  item->setName(QString::fromStdString(gNetlist->get_gate_by_id(id)->get_name())); // REMOVE & ADD AGAIN
849 
852  }
853  }
854 
856  {
857  Q_ASSERT(gNetlist->get_net_by_id(id));
858 
859  // if net elment not in model loop will reject
860  for (auto it = mNetMap.lowerBound(id); it != mNetMap.upperBound(id); ++it)
861  {
862  ModuleItem* item = it.value();
863  Q_ASSERT(item);
864 
865  item->setName(QString::fromStdString(gNetlist->get_net_by_id(id)->get_name())); // REMOVE & ADD AGAIN
866 
869  }
870  }
871 
873  {
874  return mIsModifying;
875  }
876 
877  void ModuleModel::setIsModifying(bool pIsModifying)
878  {
879  mIsModifying = pIsModifying;
880  }
881 }
(Future) Base class for all tree models related to the details widget.
virtual QList< BaseTreeItem * > getChildren() const
virtual bool removeChild(BaseTreeItem *child)
virtual BaseTreeItem * getParent() const
virtual int getChildCount() const
virtual void appendChild(BaseTreeItem *child)
virtual int getOwnRow()
The BaseTreeModel implements generic standard functions of a tree model.
QModelIndex getIndexFromItem(BaseTreeItem *item) const
RootTreeItem * mRootItem
virtual QModelIndex index(int row, int column, const QModelIndex &parent=QModelIndex()) const override
virtual void clear()
void setHeaderLabels(const QStringList &label)
BaseTreeItem * getItemFromIndex(QModelIndex index) const
Definition: gate.h:58
const std::vector< Net * > & get_fan_in_nets() const
Definition: gate.cpp:591
const std::string & get_name() const
Definition: gate.cpp:105
const std::vector< Net * > & get_fan_out_nets() const
Definition: gate.cpp:735
Module * get_parent_module() const
Definition: module.cpp:125
const std::vector< Gate * > & get_gates() const
Definition: module.cpp:393
std::string get_name() const
Definition: module.cpp:87
std::vector< Module * > get_submodules(const std::function< bool(Module *)> &filter=nullptr, bool recursive=false) const
Definition: module.cpp:261
std::string get_type() const
Definition: module.cpp:106
u32 get_id() const
Definition: module.cpp:82
An item in the ModuleModel.
Definition: module_item.h:48
QVariant getData(int column) const override
Definition: module_item.cpp:88
bool isToplevelItem() const
void setName(const QString &name)
u32 id() const
bool highlighted() const
TreeItemType getType() const
void setModuleType(const QString &moduleType)
Definition: module_item.cpp:79
void updateModuleParent(const Module *module)
Qt::ItemFlags flags(const QModelIndex &index) const override
void updateNetName(const u32 id)
void updateModuleType(const u32 id)
void addRecursively(const Module *module, BaseTreeItem *parentItem=nullptr)
void addNet(const u32 id, const u32 parentId)
void removeGate(const u32 id)
void moduleAssignNets(const QList< u32 > &gateIds=QList< u32 >())
void removeModule(const u32 id)
QList< ModuleItem * > getItems(const u32 id, ModuleItem::TreeItemType type=ModuleItem::TreeItemType::Module) const
void addGate(const u32 id, const u32 parentId)
ModuleItem * getItem(const QModelIndex &index) const
void populateFromGatelist(const std::vector< Gate * > &gates)
ModuleItem * createChildItem(u32 id, ModuleItem::TreeItemType itemType, BaseTreeItem *parentItem=nullptr)
void updateGateName(const u32 id)
void addModule(const u32 id, const u32 parentId)
QVariant data(const QModelIndex &index, int role) const override
void updateNetParent(const Net *net, const QHash< const Net *, ModuleItem * > *parentAssignment=nullptr)
void setIsModifying(bool pIsModifying)
ModuleModel(QObject *parent=nullptr)
void removeNet(const u32 id)
QMimeData * mimeData(const QModelIndexList &indexes) const override
void updateModuleName(const u32 id)
void clear() override
void removeChildItem(ModuleItem *itemToRemove, BaseTreeItem *parentItem)
void populateTree(const QVector< u32 > &modIds={}, const QVector< u32 > &gatIds={}, const QVector< u32 > &netIds={})
friend class ModuleItem
Definition: module_model.h:55
void moduleAssignGate(const u32 moduleId, const u32 gateId)
Definition: net.h:58
const std::string & get_name() const
Definition: net.cpp:98
Module * get_top_module() const
Definition: netlist.cpp:608
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
Net * get_net_by_id(u32 net_id) const
Definition: netlist.cpp:353
void netDestinationRemoved(Net *n, const u32 dst_gate_id) const
void moduleGatesAssignEnd(Module *m, u32 number_gates) const
void moduleTypeChanged(Module *m) const
void netCreated(Net *n) const
void netSourceAdded(Net *n, const u32 src_gate_id) const
void moduleGateRemoved(Module *m, const u32 removed_gate) const
void moduleGateAssigned(Module *m, const u32 assigned_gate) const
void netSourceRemoved(Net *n, const u32 src_gate_id) const
void netRemoved(Net *n) const
void netDestinationAdded(Net *n, const u32 dst_gate_id) const
void moduleSubmoduleRemoved(Module *m, const u32 removed_module) const
void moduleNameChanged(Module *m) const
void gateNameChanged(Gate *g) const
void moduleRemoved(Module *m) const
void moduleParentChanged(Module *m) const
void moduleSubmoduleAdded(Module *m, const u32 added_module) const
void moduleCreated(Module *m) const
void moduleGatesAssignBegin(Module *m, u32 number_gates) const
void netNameChanged(Net *n) const
static QString pyCodeModule(u32 moduleId)
static QString pyCodeNet(u32 netId)
static QString pyCodeGate(u32 gateId)
static SelectionDetailsIconProvider * instance()
uint32_t u32
Definition: defines.h:41
const Module * module(const Gate *g, const NodeBoxes &boxes)
Definition: defines.h:45
Netlist * gNetlist
Definition: gui_globals.h:69
NetlistRelay * gNetlistRelay
Definition: gui_globals.h:74
PinType type
Net * net
void beginInsertRows(const QModelIndex &parent, int first, int last)
void beginRemoveRows(const QModelIndex &parent, int first, int last)
void dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight, const QVector< int > &roles)
virtual Qt::ItemFlags flags(const QModelIndex &index) const const
const Key & key() const const
QHash::iterator begin()
bool empty() const const
QHash::iterator end()
QHash::iterator erase(QHash::iterator pos)
QHash::iterator insert(const Key &key, const T &value)
QList< Key > keys() const const
int size() const const
const T value(const Key &key) const const
void append(const T &value)
QList::iterator begin()
QList::iterator end()
bool isEmpty() const const
QMap::iterator insert(const Key &key, const T &value)
const T value(const Key &key, const T &defaultValue) const const
void setData(const QString &mimeType, const QByteArray &data)
void setText(const QString &text)
int column() const const
void * internalPointer() const const
bool isValid() const const
int row() const const
Q_EMITQ_EMIT
QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
QObject * parent() const const
bool contains(const T &value) const const
QSet::iterator insert(const T &value)
QString fromStdString(const std::string &str)
AlignRight
DecorationRole
typedef ItemFlags