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