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