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