HAL  v4.5.0-133-g64838ea8d
The Hardware Analyzer - a comprehensive reverse engineering and manipulation framework for gate-level netlists.
wait_to_be_seated.cpp
Go to the documentation of this file.
2 
3 #include "gui/gui_globals.h"
7 
8 #include <QDebug>
9 #include <QMap>
10 #include <QTextStream>
11 #include <QIODevice>
12 
13 namespace hal
14 {
16  {
17  mNode = Node(id, t);
18  }
19 
20  void WaitToBeSeatedEntry::setPredecessorIds(const QMap<u32, WaitToBeSeatedEntry*>& gateMap)
21  {
22  if (getId() <= 0)
23  return;
24 
25  std::vector<Net*> inputNets;
26  if (isModule())
27  {
28  const Module* m = gNetlist->get_module_by_id(getId());
29  if (m)
30  {
31  inputNets = utils::to_vector(m->get_input_nets());
32  }
33  }
34  else
35  {
36  const Gate* g = gNetlist->get_gate_by_id(getId());
37  if (g)
38  inputNets = g->get_fan_in_nets();
39  }
40 
41  for (Net* n : inputNets)
42  {
43  for (const Endpoint* ep : n->get_sources())
44  {
45  Gate* inpGate = ep->get_gate();
46  if (inpGate->is_gnd_gate() || inpGate->is_vcc_gate())
47  break;
48  u32 inpGateId = inpGate->get_id();
49  WaitToBeSeatedEntry* inpEntry = gateMap.value(inpGateId);
50  if (inpEntry)
51  mPredecessorSet.insert(inpEntry);
52  }
53  }
54  }
55 
57  {
58  return QString("%1%2").arg(isModule() ? 'M' : 'G').arg(getId());
59  }
60 
62  {
63  return mNode.isModule() && mNode.id() > 0;
64  }
65 
66  //---------------------------------------------------
68  {
69  return a->getId() < b->getId();
70  }
71 
72  double WaitToBeSeatedEntry::distance(const QPoint& pos, double defaultDistance) const
73  {
74  double retval = 0;
75  int n = mPredecessorSet.size();
76  Q_ASSERT(n > 0);
77 
78  // distance to predecessors already placed
79  for (const QPoint& source : mPredecessorPositions)
80  retval += distance(source, pos);
81 
82  // predecessors not placed yet
83  retval += (n - mPredecessorPositions.size()) * defaultDistance * 4;
84 
85  // average
86  retval /= n;
87 
88  // to break a tie : add module/gate id
89  retval += getId() / 1000000.;
90  return retval;
91  }
92 
93  int WaitToBeSeatedEntry::distance(const QPoint& source, const QPoint& pos)
94  {
95  int dx = abs(source.x() + 1 - pos.x());
96  int dy = abs(source.y() - pos.y()) - 1;
97  if (dy < 0)
98  {
99  // immediate neighbour
100  if (!dx)
101  return 1;
102  dy = 0;
103  }
104  return 5 + 4 * (dx + dy);
105  }
106 
107  //---------------------------------------------------
108  WaitToBeSeatedList::WaitToBeSeatedList() : mPlacementRound(0), mSideLength(0)
109  {
110  ;
111  }
112 
114  {
115  for (WaitToBeSeatedEntry* wtse : *this)
116  delete wtse;
117  }
118 
120  {
121  for (WaitToBeSeatedEntry* wtse : *this)
122  wtse->setPredecessorIds(mGateMap);
123 
124  for (WaitToBeSeatedEntry* wtse : *this)
125  for (WaitToBeSeatedEntry* wtsePred : wtse->mPredecessorSet)
126  if (wtsePred)
127  wtsePred->mSuccessorSet.insert(wtse);
128 
129  for (WaitToBeSeatedEntry* wtse : *this)
130  if (wtse->mPredecessorSet.isEmpty())
131  {
132  if (wtse->mSuccessorSet.isEmpty())
133  mIsolated.append(wtse);
134  else
135  mStartpoint.append(wtse);
136  }
137 
138  if (mIsolated.size() > 1)
139  std::sort(mIsolated.begin(), mIsolated.end(), compareWaitToBeSeated);
140 
141  if (mStartpoint.size() > 1)
142  std::sort(mStartpoint.begin(), mStartpoint.end(), compareWaitToBeSeated);
143 
144  mSideLength = sqrt(size());
145  }
146 
148  {
149  Q_ASSERT(wtse);
150  append(wtse);
151  if (wtse->isModule())
152  {
153  const Module* m = gNetlist->get_module_by_id(wtse->getId());
154  if (m)
155  {
156  for (const Gate* g : m->get_gates(nullptr, true))
157  if (g)
158  mGateMap.insert(g->get_id(), wtse);
159  }
160  }
161  else
162  mGateMap.insert(wtse->getId(), wtse);
163  }
164 
166  {
167  bool isEdge = pos.x() == 0 || pos.y() == 0;
168  if (!mIsolated.isEmpty() && (isEdge || mWaiting.isEmpty()))
169  {
170  return doPlacement(pos, mIsolated.takeFirst());
171  }
172  if (!mStartpoint.isEmpty() && (isEdge || mWaiting.isEmpty()))
173  {
174  return doPlacement(pos, mStartpoint.takeFirst());
175  }
176 
177  if (mWaiting.isEmpty() && !placementDone())
178  {
179  for (WaitToBeSeatedEntry* wtse : *this)
180  if (!mPlaced.contains(wtse))
181  {
182  mWaiting.insert(wtse, mPlacementRound);
183  break;
184  }
185  }
186 
187  if (!mWaiting.isEmpty())
188  {
189  double minDistance = 0;
190  QMap<WaitToBeSeatedEntry*, int>::iterator jt = mWaiting.end();
191  for (QMap<WaitToBeSeatedEntry*, int>::iterator it = mWaiting.begin(); it != mWaiting.end(); ++it)
192  {
193  double distance = it.key()->distance(pos, mSideLength) - 0.5 * (mPlacementRound - it.value());
194  if (jt == mWaiting.end() || distance < minDistance)
195  {
196  minDistance = distance;
197  jt = it;
198  }
199  }
200  Q_ASSERT(jt != mWaiting.end());
201  WaitToBeSeatedEntry* closest = jt.key();
202  mWaiting.erase(jt);
203  return doPlacement(pos, closest);
204  }
205 
206  return nullptr;
207  }
208 
210  {
211  assert(!mPlaced.contains(wtse));
212  ++mPlacementRound;
213  mPlaced.insert(wtse);
214  for (WaitToBeSeatedEntry* wtseSucc : wtse->mSuccessorSet)
215  {
216  wtseSucc->mPredecessorPositions.append(pos);
217  if (!mWaiting.contains(wtseSucc) && !mPlaced.contains(wtseSucc))
218  mWaiting.insert(wtseSucc, mPlacementRound);
219  }
220  return wtse;
221  }
222 
224  {
225  QTextStream xout(stdout, QIODevice::WriteOnly);
226  xout << "WaitToBeSeatedList\n";
227  for (WaitToBeSeatedEntry* wtse : *this)
228  {
229  xout.setFieldWidth(4);
230  xout << wtse->getId();
231  xout << (wtse->isModule() ? "MOD" : "GAT");
232  xout << "<<<";
233  for (WaitToBeSeatedEntry* wtsePred : wtse->mPredecessorSet)
234  {
235  xout << wtsePred->tagName();
236  }
237  xout << ">>>";
238  for (WaitToBeSeatedEntry* wtseSucc : wtse->mSuccessorSet)
239  {
240  xout << wtseSucc->tagName();
241  }
242  xout.setFieldWidth(0);
243  xout << "\n";
244  }
245  xout << "------------------------\n";
246  }
247 
248 } // namespace hal
Definition: gate.h:58
const std::vector< Net * > & get_fan_in_nets() const
Definition: gate.cpp:591
const std::vector< Gate * > & get_gates() const
Definition: module.cpp:400
const std::unordered_set< Net * > & get_input_nets() const
Definition: module.cpp:549
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
The Node class object represents a module or a gate.
Definition: gui_def.h:61
bool isModule() const
isModule test wheter node is a module
Definition: gui_def.h:95
u32 id() const
id getter for ID information
Definition: gui_def.h:77
bool isModule() const
QString tagName() const
double distance(const QPoint &pos, double defaultDistance) const
u32 getId() const
WaitToBeSeatedEntry(Node::NodeType t=Node::Module, u32 id=0)
void add(WaitToBeSeatedEntry *wtse)
const WaitToBeSeatedEntry * doPlacement(const QPoint &pos, WaitToBeSeatedEntry *wtse)
const WaitToBeSeatedEntry * nextPlacement(const QPoint &pos)
uint32_t u32
Definition: defines.h:41
std::vector< T > to_vector(const Container< T, Args... > &container)
Definition: utils.h:559
Definition: defines.h:45
bool compareWaitToBeSeated(const WaitToBeSeatedEntry *a, const WaitToBeSeatedEntry *b)
Netlist * gNetlist
Definition: gui_globals.h:69
void append(const T &value)
QList::iterator begin()
QList::iterator end()
bool isEmpty() const const
int size() const const
T takeFirst()
const Key & key() const const
const T value(const Key &key, const T &defaultValue) const const
int x() const const
int y() const const
QString arg(qlonglong a, int fieldWidth, int base, QChar fillChar) const const
void setFieldWidth(int width)