AMF-Placer  2.0
An Open-Source Timing-driven Analytical Mixed-size FPGA Placer
GeneralSpreader.cc
Go to the documentation of this file.
1 
27 #include "GeneralSpreader.h"
28 
29 #include <cmath>
30 #include <omp.h>
31 #include <queue>
32 #include <thread>
33 
34 GeneralSpreader::GeneralSpreader(PlacementInfo *placementInfo, std::map<std::string, std::string> &JSONCfg,
35  std::string &sharedCellType, int currentIteration, float capacityShrinkRatio,
36  bool verbose)
37  : placementInfo(placementInfo), JSONCfg(JSONCfg), sharedCellType(sharedCellType),
38  currentIteration(currentIteration), capacityShrinkRatio(capacityShrinkRatio), verbose(verbose),
39  binGrid(placementInfo->getBinGrid(placementInfo->getSharedBELTypeId(sharedCellType)))
40 {
41  overflowBins.clear();
42  if (JSONCfg.find("jobs") != JSONCfg.end())
43  {
44  nJobs = std::stoi(JSONCfg["jobs"]);
45  }
46  if (JSONCfg.find("SpreaderSimpleExpland") != JSONCfg.end())
47  {
48  useSimpleExpland = JSONCfg["SpreaderSimpleExpland"] == "true";
49  }
50 }
51 
52 void GeneralSpreader::spreadPlacementUnits(float forgetRatio, bool enableClockRegionAware, float displacementLimit,
53  unsigned int spreadRegionBinSizeLimit)
54 {
55  if (verbose) // usually commented for debug
56  print_status("GeneralSpreader: starts to spreadPlacementUnits for type: [" + sharedCellType + "]");
57 
58  std::deque<int> overflowBinNumQ;
59 
60  int loopCnt = 0;
61  // int nthreads = omp_get_num_threads();
62  // float totalBinNum = binGrid.size() * binGrid[0].size();
63 
64  std::vector<int> historyTotalCellNum(0);
65  while (true)
66  {
67  if (loopCnt % 5 == 0)
68  {
69  for (auto &row : binGrid)
70  {
71  for (auto curBin : row)
72  {
73  curBin->resetBinShrinkRatio();
74  curBin->resetNoOverflowCounter();
75  curBin->resetOverflowCounter();
76  }
77  }
78  }
79  loopCnt++;
80  if (loopCnt > 10)
81  break;
82  if (JSONCfg.find("DumpLUTFFCoordTrace-GeneralSpreader") != JSONCfg.end())
83  {
84  std::string dumpFile = JSONCfg["DumpLUTFFCoordTrace-GeneralSpreader"];
85  }
86 
87  if (verbose)
88  print_status("GeneralSpreader: finding overflow regions");
90  if (overflowBins.size() == 0)
91  break;
92  int totalCellNum = 0;
93  for (auto curBin : overflowBins)
94  totalCellNum += curBin->getCells().size();
95 
96  if (verbose) // usually commented for debug
97  {
98  print_info("found " + std::to_string(overflowBins.size()) + " overflowed bins");
99  print_info("found " + std::to_string(totalCellNum) + " cells in them");
100  print_info("spread for " + std::to_string(loopCnt) + " iterations");
101  }
102  coveredBinSet.clear();
103  expandedRegions.clear();
104  std::set<PlacementInfo::PlacementUnit *> involvedPUs;
105  std::set<DesignInfo::DesignCell *> involvedCells;
106  std::vector<PlacementInfo::PlacementUnit *> involvedPUVec;
107  involvedPUVec.clear();
108  involvedPUs.clear();
109  involvedCells.clear();
110  for (auto curBin : overflowBins)
111  {
112  if (coveredBinSet.find(curBin) != coveredBinSet.end())
113  continue;
114  GeneralSpreader::SpreadRegion *newRegion =
115  expandFromABin(curBin, capacityShrinkRatio, spreadRegionBinSizeLimit);
116  coveredBinSet.insert(curBin);
117  bool overlappedWithPreviousRegion = false;
118  for (auto curRegion : expandedRegions)
119  {
120  if (curRegion->isRegionOverlap(newRegion))
121  {
122  overlappedWithPreviousRegion = true;
123  std::cout << "newRegion: "
124  << " left:" << newRegion->left() << " right:" << newRegion->right()
125  << " top:" << newRegion->top() << " bottom:" << newRegion->bottom() << "\n";
126  std::cout << "====================================================\n";
127  for (auto curbin0 : newRegion->getBinsInRegion())
128  {
129  std::cout << "-----------------\n";
130  std::cout << curbin0 << " sharedBELStr:" << curbin0->getSharedCellType()
131  << " X: " << curbin0->X() << " Y: " << curbin0->Y() << " left:" << curbin0->left()
132  << " right:" << curbin0->right() << " top:" << curbin0->top()
133  << " bottom:" << curbin0->bottom() << "\n";
134  }
135  std::cout << "\n\n\nexistingRegion: "
136  << " left:" << curRegion->left() << " right:" << curRegion->right()
137  << " top:" << curRegion->top() << " bottom:" << curRegion->bottom() << "\n";
138  std::cout << "====================================================\n";
139  for (auto curbin0 : curRegion->getBinsInRegion())
140  {
141  std::cout << "-----------------\n";
142  std::cout << curbin0 << " sharedBELStr:" << curbin0->getSharedCellType()
143  << " X: " << curbin0->X() << " Y: " << curbin0->Y() << " left:" << curbin0->left()
144  << " right:" << curbin0->right() << " top:" << curbin0->top()
145  << " bottom:" << curbin0->bottom() << "\n";
146  }
147  break;
148  }
149  }
150  if (!overlappedWithPreviousRegion)
151  {
152  coveredBinSet.insert(curBin);
153  expandedRegions.push_back(newRegion);
154  }
155  else
156  {
157  assert(false && "should not overlap");
158  delete newRegion;
159  }
160  }
161 
162  // we don't need that high parallelism here since regionNum will be small in later iterations
163  // if (nJobs > 4)
164  // omp_set_num_threads(4);
165 #pragma omp parallel sections
166  {
167 #pragma omp section
168  {
169 
170  if (verbose) // usually commented for debug
171  print_status("involved regions cover " + std::to_string(coveredBinSet.size()) + " bins.");
172  if (verbose)
173  {
174  print_status("GeneralSpreader: spreading cells in the regions");
175  }
176 
177  int regionNum = expandedRegions.size();
178  if (coveredBinSet.size() > 256 && regionNum > 32)
179  {
180 #pragma omp parallel for schedule(dynamic, 4)
181  for (int regionId = 0; regionId < regionNum; regionId++)
182  {
183  GeneralSpreader::SpreadRegion *curRegion = expandedRegions[regionId];
184  assert(curRegion);
185  assert(curRegion->getCells().size() > 0);
186  SpreadRegion::SubBox *newBox =
187  new SpreadRegion::SubBox(placementInfo, curRegion, binGrid, capacityShrinkRatio, 100, true);
188  newBox->spreadAndPartition();
189  delete newBox;
190  }
191  }
192  else
193  {
194  for (int regionId = 0; regionId < regionNum; regionId++)
195  {
196  GeneralSpreader::SpreadRegion *curRegion = expandedRegions[regionId];
197  assert(curRegion);
198  assert(curRegion->getCells().size() > 0);
199  SpreadRegion::SubBox *newBox =
200  new SpreadRegion::SubBox(placementInfo, curRegion, binGrid, capacityShrinkRatio, 100, true);
201  newBox->spreadAndPartition();
202  delete newBox;
203  }
204  }
205  }
206 #pragma omp section
207  {
208  if (verbose)
209  print_status("GeneralSpreader: loading involved placement units");
210 
211  for (auto curRegion : expandedRegions)
212  {
213  assert(curRegion);
214  assert(curRegion->getCells().size() > 0);
215  for (auto curCell : curRegion->getCells())
216  {
217  if (involvedCells.find(curCell) == involvedCells.end())
218  {
219  auto tmpPU = placementInfo->getPlacementUnitByCell(curCell);
220  if (involvedPUs.find(tmpPU) == involvedPUs.end())
221  {
222  involvedPUs.insert(tmpPU);
223  involvedPUVec.push_back(tmpPU);
224  }
225  involvedCells.insert(curCell);
226  }
227  }
228  }
229  }
230  }
231 
232  omp_set_num_threads(nJobs);
233 
234  for (auto curRegion : expandedRegions)
235  {
236  delete curRegion;
237  }
238 
239  if (verbose)
240  print_status("GeneralSpreader: updating Placement Units With Spreaded Cell Locations");
241  updatePlacementUnitsWithSpreadedCellLocations(involvedPUs, involvedCells, involvedPUVec, forgetRatio,
242  enableClockRegionAware, displacementLimit);
243  if (verbose)
244  print_status("GeneralSpreader: updated Placement Units With Spreaded Cell Locations");
246  }
247 
248  if (verbose)
249  print_status("GeneralSpreader: processed all overflow regions");
250 
252 
253  if (JSONCfg.find("Dump Cell Density") != JSONCfg.end())
254  {
255  dumpSiteGridDensity(JSONCfg["Dump Cell Density"]);
256  }
258 
259  print_status("GeneralSpreader: accomplished spreadPlacementUnits for type: [" + sharedCellType + "]");
260 }
261 
263 {
264  return (a->getUtilizationRate() > b->getUtilizationRate());
265 }
266 
267 void GeneralSpreader::findOverflowBins(float overflowThreshold)
268 {
269  overflowBins.clear();
270  overflowBinSet.clear();
271  for (auto &row : binGrid)
272  {
273  for (auto curBin : row)
274  {
275  if (curBin->isOverflow(overflowThreshold))
276  {
277  overflowBins.push_back(curBin);
278  overflowBinSet.insert(curBin);
279  curBin->countOverflow();
280  if (curBin->getOverflowCounter() > 5)
281  {
282  if (curBin->getBinShrinkRatio() > 0.8)
283  {
284  curBin->shrinkBinBy(0.015);
285  }
286  else
287  {
288  curBin->resetBinShrinkRatio();
289  }
290  curBin->resetOverflowCounter();
291  }
292  }
293  else
294  {
295  curBin->countNoOverflow();
296  curBin->resetOverflowCounter();
297  if (curBin->getNoOverflowCounter() > 5)
298  {
299  curBin->resetBinShrinkRatio();
300  }
301  }
302  }
303  }
304  sort(overflowBins.begin(), overflowBins.end(), siteSortCmp);
305 }
306 
308  PlacementInfo *placementInfo, std::set<PlacementInfo::PlacementUnit *> &involvedPUs,
309  std::set<DesignInfo::DesignCell *> &involvedCells, std::vector<PlacementInfo::PlacementUnit *> &involvedPUVec,
310  float forgetRatio, float displacementLimit, int startId, int endId)
311 {
312  bool displacementLimitEnable = displacementLimit > 0;
313  std::vector<PlacementInfo::Location> &cellLoc = placementInfo->getCellId2location();
314  for (int curPUID = startId; curPUID < endId; curPUID++)
315  {
316  assert((unsigned int)curPUID < involvedPUVec.size());
317  auto curPU = involvedPUVec[curPUID];
318  if (auto curUnpackedCell = dynamic_cast<PlacementInfo::PlacementUnpackedCell *>(curPU))
319  {
320  float cellX = curUnpackedCell->X();
321  float cellY = curUnpackedCell->Y();
322  DesignInfo::DesignCell *curCell = curUnpackedCell->getCell();
323  if (curPU->isFixed() || curPU->isLocked())
324  {
325  cellLoc[curCell->getCellId()].X = cellX;
326  cellLoc[curCell->getCellId()].Y = cellY;
327  }
328  else
329  {
330  makeCellInLegalArea(placementInfo, cellLoc[curCell->getCellId()].X, cellLoc[curCell->getCellId()].Y);
331  if (displacementLimitEnable)
332  curPU->setSpreadLocation_WithLimitDisplacement(cellLoc[curCell->getCellId()].X,
333  cellLoc[curCell->getCellId()].Y, forgetRatio,
334  displacementLimit);
335  else
336  curPU->setSpreadLocation(cellLoc[curCell->getCellId()].X, cellLoc[curCell->getCellId()].Y,
337  forgetRatio);
338  placementInfo->transferCellBinInfo(curCell->getCellId(), curPU->X(), curPU->Y());
339  cellLoc[curCell->getCellId()].X = curPU->X();
340  cellLoc[curCell->getCellId()].Y = curPU->Y();
341  }
342  }
343  else if (auto curMacro = dynamic_cast<PlacementInfo::PlacementMacro *>(curPU))
344  {
345  if (curPU->isFixed() || curPU->isLocked())
346  {
347  for (int vId = 0; vId < curMacro->getNumOfCells(); vId++)
348  {
349  float offsetX_InMacro, offsetY_InMacro;
351  curMacro->getVirtualCellInfo(vId, offsetX_InMacro, offsetY_InMacro, cellType);
352 
353  float cellX = curMacro->X() + offsetX_InMacro;
354  float cellY = curMacro->Y() + offsetY_InMacro;
355 
356  DesignInfo::DesignCell *curCell = curMacro->getCell(vId);
357 
358  cellLoc[curCell->getCellId()].X = cellX;
359  cellLoc[curCell->getCellId()].Y = cellY;
360  }
361  }
362  else
363  {
364  double tmpTotalX = 0.0;
365  double tmpTotalY = 0.0;
366 
367  int numCellsInvolvedInSpreading = 0;
368  for (int vId = 0; vId < curMacro->getNumOfCells(); vId++)
369  {
370  DesignInfo::DesignCell *curCell = curMacro->getCell(vId);
371  if (involvedCells.find(curCell) != involvedCells.end())
372  {
373  float offsetX_InMacro, offsetY_InMacro;
375  curMacro->getVirtualCellInfo(vId, offsetX_InMacro, offsetY_InMacro, cellType);
376  makeCellInLegalArea(placementInfo, cellLoc[curCell->getCellId()].X,
377  cellLoc[curCell->getCellId()].Y);
378  tmpTotalX += cellLoc[curCell->getCellId()].X - offsetX_InMacro;
379  tmpTotalY += cellLoc[curCell->getCellId()].Y - offsetY_InMacro;
380  numCellsInvolvedInSpreading++;
381  }
382  }
383  tmpTotalX /= (double)numCellsInvolvedInSpreading;
384  tmpTotalY /= (double)numCellsInvolvedInSpreading;
385 
386  float curNewPUX = tmpTotalX;
387  float curNewPUY = tmpTotalY;
388  placementInfo->legalizeXYInArea(curPU, curNewPUX, curNewPUY);
389  if (displacementLimitEnable)
390  curPU->setSpreadLocation_WithLimitDisplacement(curNewPUX, curNewPUY, forgetRatio,
391  displacementLimit);
392  else
393  curPU->setSpreadLocation(curNewPUX, curNewPUY, forgetRatio);
395  for (int vId = 0; vId < curMacro->getNumOfCells(); vId++)
396  {
397  float offsetX_InMacro, offsetY_InMacro;
399  curMacro->getVirtualCellInfo(vId, offsetX_InMacro, offsetY_InMacro, cellType);
400 
401  float cellX = curMacro->X() + offsetX_InMacro;
402  float cellY = curMacro->Y() + offsetY_InMacro;
403 
404  DesignInfo::DesignCell *curCell = curMacro->getCell(vId);
405  placementInfo->transferCellBinInfo(curCell->getCellId(), cellX, cellY);
406  cellLoc[curCell->getCellId()].X = cellX;
407  cellLoc[curCell->getCellId()].Y = cellY;
408  }
409  }
410  }
411  }
412 }
413 
415  std::set<PlacementInfo::PlacementUnit *> &involvedPUs, std::set<DesignInfo::DesignCell *> &involvedCells,
416  std::vector<PlacementInfo::PlacementUnit *> &involvedPUVec, float forgetRatio, bool enableClockRegionAware,
417  float displacementLimit)
418 {
419  std::vector<PlacementInfo::Location> &cellLoc = placementInfo->getCellId2location();
420  bool displacementLimitEnable = displacementLimit > 0;
421  // if (enableClockRegionAware)
422  // {
423  // auto &PU2ClockRegionColumn = placementInfo->getPU2ClockRegionColumn();
424  // auto &clockRegions = placementInfo->getDeviceInfo()->getClockRegions();
425  // for (auto curCell : involvedCells)
426  // {
427  // auto PU = placementInfo->getPlacementUnitByCellId(curCell->getCellId());
428  // if (PU2ClockRegionColumn.find(PU) != PU2ClockRegionColumn.end())
429  // {
430  // int clockRegionX = PU2ClockRegionColumn[PU];
431  // float rLeft = clockRegions[0][clockRegionX]->getLeft();
432  // float rRight = clockRegions[0][clockRegionX]->getRight();
433  // if (cellLoc[curCell->getCellId()].X < rLeft)
434  // cellLoc[curCell->getCellId()].X = rLeft + 0.1;
435  // if (cellLoc[curCell->getCellId()].X > rRight)
436  // cellLoc[curCell->getCellId()].X = rRight - 0.1;
437  // }
438  // }
439  // }
440 
441  // VCU108 Optimization
442  if (enableClockRegionAware)
443  {
444  auto &PU2ClockRegionColumn = placementInfo->getPU2ClockRegionColumn();
445  auto &clockRegions = placementInfo->getDeviceInfo()->getClockRegions();
446  for (auto curCell : involvedCells)
447  {
448  auto PU = placementInfo->getPlacementUnitByCellId(curCell->getCellId());
449  if (PU2ClockRegionColumn.find(PU) != PU2ClockRegionColumn.end())
450  {
451  int clockRegionX = PU2ClockRegionColumn[PU];
452  if (clockRegionX == 2)
453  {
454  float rLeft = clockRegions[0][clockRegionX]->getLeft();
455  float rRight = clockRegions[0][clockRegionX]->getRight();
456  if (cellLoc[curCell->getCellId()].X < rLeft)
457  cellLoc[curCell->getCellId()].X = rLeft + 0.1;
458  if (cellLoc[curCell->getCellId()].X > rRight)
459  cellLoc[curCell->getCellId()].X = rRight - 0.1;
460  }
461  else if (clockRegionX < 2)
462  {
463  float rRight = clockRegions[0][1]->getRight();
464  if (cellLoc[curCell->getCellId()].X > rRight)
465  cellLoc[curCell->getCellId()].X = rRight - 0.1;
466  }
467  else if (clockRegionX > 2)
468  {
469  float rLeft = clockRegions[0][3]->getLeft();
470  if (cellLoc[curCell->getCellId()].X < rLeft)
471  cellLoc[curCell->getCellId()].X = rLeft + 0.1;
472  }
473  }
474  }
475  }
476 
477  if (involvedPUs.size() > 100)
478  {
479  std::vector<std::thread *> threadsVec;
480  threadsVec.clear();
481  int eachThreadPUNum = involvedPUVec.size() / nJobs;
482  std::vector<std::pair<int, int>> startEndPairs;
483  startEndPairs.clear();
484 
485  for (int threadId = 0, startId = 0, endId = eachThreadPUNum; threadId < nJobs;
486  threadId++, startId += eachThreadPUNum, endId += eachThreadPUNum)
487  {
488  if (threadId == nJobs - 1)
489  {
490  endId = involvedPUVec.size();
491  }
492  startEndPairs.emplace_back(startId, endId);
493  }
494  for (int threadId = 0; threadId < nJobs; threadId++)
495  {
496  std::thread *newThread =
498  std::ref(involvedPUs), std::ref(involvedCells), std::ref(involvedPUVec),
499  std::ref(forgetRatio), std::ref(displacementLimit),
500  std::ref(startEndPairs[threadId].first), std::ref(startEndPairs[threadId].second));
501  threadsVec.push_back(newThread);
502  }
503  for (int threadId = 0; threadId < nJobs; threadId++)
504  {
505  threadsVec[threadId]->join();
506  delete threadsVec[threadId];
507  }
508  }
509  else
510  {
511  for (auto curPU : involvedPUVec)
512  {
513  if (auto curUnpackedCell = dynamic_cast<PlacementInfo::PlacementUnpackedCell *>(curPU))
514  {
515  float cellX = curUnpackedCell->X();
516  float cellY = curUnpackedCell->Y();
517  DesignInfo::DesignCell *curCell = curUnpackedCell->getCell();
518  if (curPU->isFixed() || curPU->isLocked())
519  {
520  cellLoc[curCell->getCellId()].X = cellX;
521  cellLoc[curCell->getCellId()].Y = cellY;
522  }
523  else
524  {
525  makeCellInLegalArea(placementInfo, cellLoc[curCell->getCellId()].X,
526  cellLoc[curCell->getCellId()].Y);
527 
528  if (displacementLimitEnable)
529  curPU->setSpreadLocation_WithLimitDisplacement(cellLoc[curCell->getCellId()].X,
530  cellLoc[curCell->getCellId()].Y, forgetRatio,
531  displacementLimit);
532  else
533  curPU->setSpreadLocation(cellLoc[curCell->getCellId()].X, cellLoc[curCell->getCellId()].Y,
534  forgetRatio);
535  placementInfo->transferCellBinInfo(curCell->getCellId(), curPU->X(), curPU->Y());
536  cellLoc[curCell->getCellId()].X = curPU->X();
537  cellLoc[curCell->getCellId()].Y = curPU->Y();
538  }
539  }
540  else if (auto curMacro = dynamic_cast<PlacementInfo::PlacementMacro *>(curPU))
541  {
542  if (curPU->isFixed() || curPU->isLocked())
543  {
544  for (int vId = 0; vId < curMacro->getNumOfCells(); vId++)
545  {
546  float offsetX_InMacro, offsetY_InMacro;
548  curMacro->getVirtualCellInfo(vId, offsetX_InMacro, offsetY_InMacro, cellType);
549 
550  float cellX = curMacro->X() + offsetX_InMacro;
551  float cellY = curMacro->Y() + offsetY_InMacro;
552 
553  DesignInfo::DesignCell *curCell = curMacro->getCell(vId);
554 
555  cellLoc[curCell->getCellId()].X = cellX;
556  cellLoc[curCell->getCellId()].Y = cellY;
557  }
558  }
559  else
560  {
561  double tmpTotalX = 0.0;
562  double tmpTotalY = 0.0;
563 
564  int numCellsInvolvedInSpreading = 0;
565  for (int vId = 0; vId < curMacro->getNumOfCells(); vId++)
566  {
567  DesignInfo::DesignCell *curCell = curMacro->getCell(vId);
568  if (involvedCells.find(curCell) != involvedCells.end())
569  {
570  float offsetX_InMacro, offsetY_InMacro;
572  curMacro->getVirtualCellInfo(vId, offsetX_InMacro, offsetY_InMacro, cellType);
573  makeCellInLegalArea(placementInfo, cellLoc[curCell->getCellId()].X,
574  cellLoc[curCell->getCellId()].Y);
575  tmpTotalX += cellLoc[curCell->getCellId()].X - offsetX_InMacro;
576  tmpTotalY += cellLoc[curCell->getCellId()].Y - offsetY_InMacro;
577  numCellsInvolvedInSpreading++;
578  }
579  }
580  tmpTotalX /= (double)numCellsInvolvedInSpreading;
581  tmpTotalY /= (double)numCellsInvolvedInSpreading;
582  float curNewPUX = tmpTotalX;
583  float curNewPUY = tmpTotalY;
584  placementInfo->legalizeXYInArea(curPU, curNewPUX, curNewPUY);
585 
586  if (displacementLimitEnable)
587  curPU->setSpreadLocation_WithLimitDisplacement(curNewPUX, curNewPUY, forgetRatio,
588  displacementLimit);
589  else
590  curPU->setSpreadLocation(curNewPUX, curNewPUY, forgetRatio);
591 
593  for (int vId = 0; vId < curMacro->getNumOfCells(); vId++)
594  {
595  float offsetX_InMacro, offsetY_InMacro;
597  curMacro->getVirtualCellInfo(vId, offsetX_InMacro, offsetY_InMacro, cellType);
598 
599  float cellX = curMacro->X() + offsetX_InMacro;
600  float cellY = curMacro->Y() + offsetY_InMacro;
601 
602  DesignInfo::DesignCell *curCell = curMacro->getCell(vId);
603  placementInfo->transferCellBinInfo(curCell->getCellId(), cellX, cellY);
604  cellLoc[curCell->getCellId()].X = cellX;
605  cellLoc[curCell->getCellId()].Y = cellY;
606  }
607  }
608  }
609  }
610  }
611 }
612 
614  float capacityShrinkRatio, unsigned int numBinThr)
615 { // Our Region Expanding (1.4x faster)
616  GeneralSpreader::SpreadRegion *resRegion =
618 
619  float binUnitSize = std::min(curBin->right() - curBin->left(), curBin->top() - curBin->bottom());
620  if (!useSimpleExpland)
621  {
622  while (resRegion->getOverflowRatio() > capacityShrinkRatio &&
623  resRegion->smartFindExpandDirection(coveredBinSet) && resRegion->getBinsInRegion().size() < numBinThr)
624  {
625  resRegion->smartExpand(coveredBinSet);
626  }
627  }
628  else
629  {
630  while (resRegion->getOverflowRatio() > capacityShrinkRatio &&
631  resRegion->simpleFindExpandDirection(coveredBinSet) && resRegion->getBinsInRegion().size() < numBinThr)
632  {
633  resRegion->simpleExpand(coveredBinSet);
634  }
635  }
636 
637  // assert(!resRegion->isOverflow() && "TODO: how to handle the situation that the resource is not enough.");
638  return resRegion;
639 }
640 
641 // GeneralSpreader::SpreadRegion *GeneralSpreader::expandFromABin(PlacementInfo::PlacementBinInfo *curBin,
642 // float capacityShrinkRatio)
643 // { // RippleFPGA Region Expanding
644 // GeneralSpreader::SpreadRegion *resRegion =
645 // new GeneralSpreader::SpreadRegion(curBin, placementInfo, binGrid, capacityShrinkRatio);
646 
647 // while (resRegion->getOverflowRatio() > capacityShrinkRatio &&
648 // resRegion->simpleFindExpandDirection(coveredBinSet))
649 // {
650 // resRegion->simpleExpand(coveredBinSet);
651 // }
652 // // assert(!resRegion->isOverflow() && "TODO: how to handle the situation that the resource is not enough.");
653 // return resRegion;
654 // }
655 
656 void GeneralSpreader::SpreadRegion::addBinRegion(int newRegionTopBinY, int newRegionBottomBinY, int newRegionLeftBinX,
657  int newRegionRightBinX,
658  std::set<PlacementInfo::PlacementBinInfo *> &coveredBinSet)
659 {
660  assert(!isRegionOverlap(newRegionTopBinY, newRegionBottomBinY, newRegionLeftBinX, newRegionRightBinX));
661  if (newRegionTopBinY > topBinY)
662  topBinY = newRegionTopBinY;
663  if (newRegionBottomBinY < bottomBinY)
664  bottomBinY = newRegionBottomBinY;
665  if (newRegionLeftBinX < leftBinX)
666  leftBinX = newRegionLeftBinX;
667  if (newRegionRightBinX > rightBinX)
668  rightBinX = newRegionRightBinX;
669 
670  assert(0 <= newRegionBottomBinY);
671  assert(0 <= newRegionTopBinY);
672  assert((unsigned int)newRegionBottomBinY < binGrid.size());
673  assert((unsigned int)newRegionTopBinY < binGrid.size());
674  assert(0 <= newRegionLeftBinX);
675  assert(0 <= newRegionRightBinX);
676  assert((unsigned int)newRegionLeftBinX < binGrid[0].size());
677  assert((unsigned int)newRegionRightBinX < binGrid[0].size());
678  for (int i = newRegionBottomBinY; i <= newRegionTopBinY; i++)
679  for (int j = newRegionLeftBinX; j <= newRegionRightBinX; j++)
680  {
681  assert(binSetInRegion.find(binGrid[i][j]) == binSetInRegion.end());
682  assert(binGrid[i][j]->X() == j && binGrid[i][j]->Y() == i);
683  binsInRegion.push_back(binGrid[i][j]);
684  binSetInRegion.insert(binGrid[i][j]);
685  assert(coveredBinSet.find(binGrid[i][j]) == coveredBinSet.end());
686  coveredBinSet.insert(binGrid[i][j]);
687  for (auto curCell : binGrid[i][j]->getCells())
688  {
689  cellsInRegion.insert(curCell);
690  cellsInRegionVec.push_back(curCell);
691  }
692  totalCapacity += binGrid[i][j]->getCapacity();
693  totalUtilization += binGrid[i][j]->getUtilization();
694  }
696 }
697 
699 {
700  for (auto tmpPU : placementInfo->getPlacementUnits())
701  {
702  tmpPU->recordSpreadLocatin();
703  }
704 }
705 
707 {
708  if (level == 0)
709  return;
710  if (topBinY - bottomBinY < minExpandSize - 1 && rightBinX - leftBinX < minExpandSize - 1)
711  {
712  return;
713  }
714 
715  SubBox *boxA = nullptr, *boxB = nullptr;
716  if (dirIsH)
717  {
718  if (rightBinX - leftBinX >= minExpandSize - 1)
719  {
720  spreadCellsH(&boxA, &boxB);
721  }
722  if (!(boxA || boxB) && topBinY - bottomBinY >= minExpandSize - 1)
723  {
724  spreadCellsV(&boxA, &boxB);
725  }
726  }
727  else
728  {
729  if (topBinY - bottomBinY >= minExpandSize - 1)
730  {
731  spreadCellsV(&boxA, &boxB);
732  }
733  if (!(boxA || boxB) && rightBinX - leftBinX >= minExpandSize - 1)
734  {
735  spreadCellsH(&boxA, &boxB);
736  }
737  }
738  if (boxA)
739  {
740  boxA->spreadAndPartition();
741  }
742  if (boxB)
743  {
744  boxB->spreadAndPartition();
745  }
746  if (boxA)
747  delete boxA;
748  if (boxB)
749  delete boxB;
750 }
751 
753 {
754  // refer to paper of POLAR and RippleFPGA
755 
756  if (cellIds.size() == 0)
757  return;
758  if (cellIds.size() > 1)
759  quick_sort(cellIds, 0, cellIds.size() - 1, true);
760 
761  std::vector<float> colCapacity(rightBinX - leftBinX + 1, 0.0);
762  float totalCapacity = 0;
763 
764  assert(leftBinX >= 0);
765  assert(bottomBinY >= 0);
766  assert((unsigned int)topBinY < binGrid.size());
767  assert((unsigned int)rightBinX < binGrid[topBinY].size());
768  // calculate capacity
769  for (int binX = leftBinX; binX <= rightBinX; binX++)
770  {
771  for (int y = bottomBinY; y <= topBinY; y++)
772  {
773  float binCapacity = capacityShrinkRatio * binGrid[y][binX]->getCapacity();
774  colCapacity[binX - leftBinX] += binCapacity;
775  totalCapacity += binCapacity;
776  }
777  }
778 
779  // get the boundary of the sub boxes
780  // @ | | @
781  // @ boxA | | boxB @
782  // @ | | @
783  int boxALeft = leftBinX;
784  int boxBRight = rightBinX;
785  for (int binX = leftBinX; binX <= rightBinX; binX++, boxALeft++)
786  {
787  if (colCapacity[binX - leftBinX] > 0)
788  break;
789  }
790  for (int binX = rightBinX; binX >= leftBinX; binX--, boxBRight--)
791  {
792  if (colCapacity[binX - leftBinX] > 0)
793  break;
794  }
795  if (boxBRight <= boxALeft)
796  {
797  return;
798  assert(false && "should not happen");
799  }
800 
801  // | @ @ |
802  // | boxA @ @ boxB |
803  // | @ @ |
804  int boxARight = boxALeft;
805  int boxBLeft = boxBRight;
806  float leftCapacity = colCapacity[boxARight - leftBinX];
807  float rightCapacity = colCapacity[boxBLeft - leftBinX];
808  while (boxARight < boxBLeft - 1)
809  {
810  if (leftCapacity <= rightCapacity)
811  {
812  boxARight++;
813  leftCapacity += colCapacity[boxARight - leftBinX];
814  }
815  else
816  {
817  boxBLeft--;
818  rightCapacity += colCapacity[boxBLeft - leftBinX];
819  }
820  }
821 
822  // splits the cells into two part
823  float leftUtilRatio = leftCapacity / totalCapacity;
824  float totalUtilization = 0;
825  for (auto cellId : cellIds)
826  {
827  totalUtilization += placementInfo->getActualOccupationByCellId(cellId);
828  }
829  float leftUtil = totalUtilization * leftUtilRatio;
830 
831  int cutLineIdX = -1;
832  if (leftUtil > eps)
833  {
834  for (auto cellId : cellIds)
835  {
836  leftUtil -= placementInfo->getActualOccupationByCellId(cellId);
837  cutLineIdX++;
838  if (leftUtil <= eps)
839  break;
840  }
841  }
842 
843  // assign cells into two subbox A and B
844  *boxA = new SubBox(this, topBinY, bottomBinY, boxALeft, boxARight, 0, cutLineIdX);
845  *boxB = new SubBox(this, topBinY, bottomBinY, boxBLeft, boxBRight, cutLineIdX + 1, cellIds.size() - 1);
846  std::vector<PlacementInfo::Location> &cellLoc = placementInfo->getCellId2location();
847 
848  float overallOverflowRatio = totalUtilization / totalCapacity;
849  if (overallOverflowRatio < 1)
850  overallOverflowRatio = 1;
851 
852  std::vector<int> &boxACellIds = (*boxA)->cellIds;
853  if (boxACellIds.size() > 0)
854  {
855  int cellInBinHead = boxACellIds.size() - 1;
856  int cellInBinTail = boxACellIds.size() - 1;
857 
858  // spread cells' location in boxA
859 
860  for (int binX = boxARight; binX >= boxALeft; binX--)
861  {
862  if (cellInBinTail < 0)
863  break;
864 
865  float cArea = 0;
866  int num = 0;
867  float oldLoX = cellLoc[boxACellIds[cellInBinTail]].X;
868  float oldHiX = oldLoX;
869  for (cellInBinHead = cellInBinTail;
870  cellInBinHead >= 0 &&
871  (binX == boxALeft || (cArea / overallOverflowRatio <= colCapacity[binX - leftBinX] + eps));
872  --cellInBinHead)
873  {
874  cArea += placementInfo->getActualOccupationByCellId(boxACellIds[cellInBinHead]);
875  oldLoX = cellLoc[boxACellIds[cellInBinHead]].X;
876  num++;
877  }
878  cellInBinHead++;
879  if (num > 0)
880  {
881  assert(binX >= 0);
882  assert((unsigned int)binX < binGrid[bottomBinY].size());
883  float newLoX = binGrid[bottomBinY][binX]->left() + placementInfo->getBinGridW() / (num + 1.0);
884  float newHiX = binGrid[bottomBinY][binX]->right() - placementInfo->getBinGridW() / (num + 1.0);
885  float rangeold = oldHiX - oldLoX;
886  float rangenew = newHiX - newLoX;
887  assert(rangeold > -1e-5);
888  assert(rangenew > -1e-5);
889  if (fabs(rangeold) < 1e-5)
890  {
891  float newLoc = (newLoX + newHiX) / 2;
892  for (int ci = cellInBinHead; ci <= cellInBinTail; ++ci)
893  {
894  cellLoc[boxACellIds[ci]].X = newLoc;
895  }
896  }
897  else
898  {
899  float scale = rangenew / rangeold;
900  assert(scale > -1e-5);
901  for (int ci = cellInBinHead; ci <= cellInBinTail; ++ci)
902  {
903  cellLoc[boxACellIds[ci]].X = newLoX + (cellLoc[boxACellIds[ci]].X - oldLoX) * scale;
904  }
905  }
906  }
907  cellInBinTail = cellInBinHead - 1;
908  }
909  }
910  else
911  {
912  delete *boxA;
913  *boxA = nullptr;
914  }
915 
916  std::vector<int> &boxBCellIds = (*boxB)->cellIds;
917 
918  if (boxBCellIds.size() > 0)
919  {
920  int cellInBinHead = 0;
921  int cellInBinTail = 0;
922 
923  // spread cells' location in boxB
924  for (int binX = boxBLeft; binX <= boxBRight; binX++)
925  {
926  if ((unsigned int)cellInBinHead >= boxBCellIds.size())
927  break;
928 
929  float cArea = 0;
930  int num = 0;
931  float oldLoX = cellLoc[boxBCellIds[cellInBinHead]].X;
932  float oldHiX = oldLoX;
933 
934  for (cellInBinTail = cellInBinHead;
935  (unsigned int)cellInBinTail < boxBCellIds.size() &&
936  (binX == boxBRight || (cArea / overallOverflowRatio <= colCapacity[binX - leftBinX] + eps));
937  cellInBinTail++)
938  {
939  cArea += placementInfo->getActualOccupationByCellId(boxBCellIds[cellInBinTail]);
940  oldHiX = cellLoc[boxBCellIds[cellInBinTail]].X;
941  num++;
942  }
943  cellInBinTail--;
944 
945  assert(cellLoc[boxBCellIds[cellInBinTail]].X <= oldHiX + 1e-5);
946  if (num > 0)
947  {
948  assert(binX >= 0);
949  assert((unsigned int)binX < binGrid[bottomBinY].size());
950  float newLoX = binGrid[bottomBinY][binX]->left() + placementInfo->getBinGridW() / (num + 1.0);
951  float newHiX = binGrid[bottomBinY][binX]->right() - placementInfo->getBinGridW() / (num + 1.0);
952  float rangeold = oldHiX - oldLoX;
953  float rangenew = newHiX - newLoX;
954  assert(rangeold > -1e-5);
955  assert(rangenew > -1e-5);
956  if (fabs(rangeold) < 1e-5)
957  {
958  float newLoc = (newLoX + newHiX) / 2;
959  for (int ci = cellInBinHead; ci <= cellInBinTail; ++ci)
960  {
961  cellLoc[boxBCellIds[ci]].X = newLoc;
962  }
963  }
964  else
965  {
966  float scale = rangenew / rangeold;
967  assert(scale > -1e-5);
968  for (int ci = cellInBinHead; ci <= cellInBinTail; ++ci)
969  {
970  cellLoc[boxBCellIds[ci]].X = newLoX + (cellLoc[boxBCellIds[ci]].X - oldLoX) * scale;
971  }
972  }
973  }
974  cellInBinHead = cellInBinTail + 1;
975  }
976  }
977  else
978  {
979  delete *boxB;
980  *boxB = nullptr;
981  }
982 
983  return;
984 }
985 
987 {
988  // refer to paper of POLAR and RippleFPGA
989  if (cellIds.size() == 0)
990  return;
991 
992  if (cellIds.size() > 1)
993  quick_sort(cellIds, 0, cellIds.size() - 1, false);
994 
995  std::vector<float> colCapacity(topBinY - bottomBinY + 1, 0.0);
996  float totalCapacity = 0;
997 
998  assert(leftBinX >= 0);
999  assert(bottomBinY >= 0);
1000  assert((unsigned int)topBinY < binGrid.size());
1001  assert((unsigned int)rightBinX < binGrid[topBinY].size());
1002  // calculate capacity
1003  for (int binY = bottomBinY; binY <= topBinY; binY++)
1004  {
1005  for (int binX = leftBinX; binX <= rightBinX; binX++)
1006  {
1007  float binCapacity = capacityShrinkRatio * binGrid[binY][binX]->getCapacity();
1008  colCapacity[binY - bottomBinY] += binCapacity;
1009  totalCapacity += binCapacity;
1010  }
1011  }
1012 
1013  // get the boundary of the sub boxes
1014  // @ @ @ @ @ @
1015  //
1016  // boxB
1017  //
1018  // ----------
1019  // ----------
1020  //
1021  // boxA
1022  //
1023  // @ @ @ @ @ @
1024  int boxABottom = bottomBinY;
1025  int boxBTop = topBinY;
1026  for (int binY = bottomBinY; binY <= topBinY; binY++, boxABottom++)
1027  {
1028  if (colCapacity[binY - bottomBinY] > 0)
1029  break;
1030  }
1031  for (int binY = topBinY; binY >= bottomBinY; binY--, boxBTop--)
1032  {
1033  if (colCapacity[binY - bottomBinY] > 0)
1034  break;
1035  }
1036  if (boxBTop <= boxABottom)
1037  {
1038  return;
1039  assert(false && "should not happen");
1040  }
1041 
1042  // ----------
1043  //
1044  // boxB
1045  //
1046  // @ @ @ @ @ @
1047  // @ @ @ @ @ @
1048  //
1049  //
1050  // boxA
1051  //
1052  // ----------
1053  int boxATop = boxABottom;
1054  int boxBBottom = boxBTop;
1055  float bottomCapacity = colCapacity[boxATop - bottomBinY];
1056  float topCapacity = colCapacity[boxBBottom - bottomBinY];
1057  while (boxATop < boxBBottom - 1)
1058  {
1059  if (bottomCapacity <= topCapacity)
1060  {
1061  boxATop++;
1062  bottomCapacity += colCapacity[boxATop - bottomBinY];
1063  }
1064  else
1065  {
1066  boxBBottom--;
1067  topCapacity += colCapacity[boxBBottom - bottomBinY];
1068  }
1069  }
1070  // if (leftBinX == 26 && rightBinX == 26 && topBinY == 180 && bottomBinY == 179)
1071  // {
1072  // std::cout << "boxATop=" << boxATop << "\n";
1073  // std::cout << "boxABottom=" << boxABottom << "\n";
1074  // std::cout << "boxBTop=" << boxBTop << "\n";
1075  // std::cout << "boxBBottom=" << boxBBottom << "\n";
1076  // std::vector<PlacementInfo::Location> &cellLoc = placementInfo->getCellId2location();
1077  // for (auto cellId : cellIds)
1078  // {
1079  // std::cout << "cell#" << cellId << " locX:" << cellLoc[cellId].X << " locY:" << cellLoc[cellId].Y << "\n";
1080  // }
1081  // }
1082  // splits the cells into two part
1083  float bottomUtilRatio = bottomCapacity / totalCapacity;
1084  float totalUtilization = 0;
1085  for (auto cellId : cellIds)
1086  {
1087  totalUtilization += placementInfo->getActualOccupationByCellId(cellId);
1088  }
1089  float bottomUtil = totalUtilization * bottomUtilRatio;
1090 
1091  int cutLineIdX = -1;
1092  if (bottomUtil > eps)
1093  {
1094  for (auto cellId : cellIds)
1095  {
1096  bottomUtil -= placementInfo->getActualOccupationByCellId(cellId);
1097  cutLineIdX++;
1098  if (bottomUtil <= eps)
1099  break;
1100  }
1101  }
1102 
1103  // assign cells into two subbox A and B
1104  *boxA = new SubBox(this, boxATop, boxABottom, leftBinX, rightBinX, 0, cutLineIdX);
1105  *boxB = new SubBox(this, boxBTop, boxBBottom, leftBinX, rightBinX, cutLineIdX + 1, cellIds.size() - 1);
1106  std::vector<PlacementInfo::Location> &cellLoc = placementInfo->getCellId2location();
1107 
1108  float overallOverflowRatio = totalUtilization / totalCapacity;
1109  if (overallOverflowRatio < 1)
1110  overallOverflowRatio = 1;
1111  std::vector<int> &boxACellIds = (*boxA)->cellIds;
1112 
1113  if (boxACellIds.size() > 0)
1114  {
1115  int cellInBinHead = boxACellIds.size() - 1;
1116  int cellInBinTail = boxACellIds.size() - 1;
1117  // spread cells' location in boxA
1118 
1119  for (int binY = boxATop; binY >= boxABottom; binY--)
1120  {
1121  if (cellInBinTail < 0)
1122  break;
1123  float cArea = 0;
1124  int num = 0;
1125  float oriBottomY = cellLoc[boxACellIds[cellInBinTail]].Y;
1126  float oriTopY = oriBottomY;
1127  for (cellInBinHead = cellInBinTail;
1128  cellInBinHead >= 0 &&
1129  (binY == boxABottom || (cArea / overallOverflowRatio <= colCapacity[binY - bottomBinY] + eps));
1130  --cellInBinHead)
1131  {
1132  cArea += placementInfo->getActualOccupationByCellId(boxACellIds[cellInBinHead]);
1133  oriBottomY = cellLoc[boxACellIds[cellInBinHead]].Y;
1134  num++;
1135  }
1136  cellInBinHead++;
1137  if (num > 0)
1138  {
1139  assert(binY >= 0);
1140  assert((unsigned int)binY < binGrid.size());
1141  float newBottomY = binGrid[binY][leftBinX]->bottom() + placementInfo->getBinGridH() / (num + 1.0);
1142  float newTopY = binGrid[binY][leftBinX]->top() - placementInfo->getBinGridH() / (num + 1.0);
1143  assert(newTopY >= newBottomY);
1144  float rangeold = oriTopY - oriBottomY;
1145  float rangenew = newTopY - newBottomY;
1146  assert(rangeold > -1e-5);
1147  assert(rangenew > -1e-5);
1148  if (fabs(rangeold) < 1e-5)
1149  {
1150  float newBottomc = (newBottomY + newTopY) / 2;
1151  for (int ci = cellInBinHead; ci <= cellInBinTail; ++ci)
1152  {
1153  cellLoc[boxACellIds[ci]].Y = newBottomc;
1154  }
1155  }
1156  else
1157  {
1158  float scale = rangenew / rangeold;
1159  assert(scale > -1e-5);
1160  for (int ci = cellInBinHead; ci <= cellInBinTail; ++ci)
1161  {
1162  cellLoc[boxACellIds[ci]].Y = newBottomY + (cellLoc[boxACellIds[ci]].Y - oriBottomY) * scale;
1163  }
1164  }
1165  }
1166  cellInBinTail = cellInBinHead - 1;
1167  }
1168  }
1169  else
1170  {
1171  delete *boxA;
1172  *boxA = nullptr;
1173  }
1174 
1175  std::vector<int> &boxBCellIds = (*boxB)->cellIds;
1176 
1177  if (boxBCellIds.size() > 0)
1178  {
1179  int cellInBinHead = 0;
1180  int cellInBinTail = 0;
1181 
1182  // spread cells' location in boxB
1183  for (int binY = boxBBottom; binY <= boxBTop; binY++)
1184  {
1185  if ((unsigned int)cellInBinHead >= boxBCellIds.size())
1186  break;
1187 
1188  float cArea = 0;
1189  int num = 0;
1190  float oriBottomY = cellLoc[boxBCellIds[cellInBinHead]].Y;
1191  float oriTopY = oriBottomY;
1192 
1193  for (cellInBinTail = cellInBinHead;
1194  (unsigned int)cellInBinTail < boxBCellIds.size() &&
1195  (binY == boxBTop || (cArea / overallOverflowRatio <= colCapacity[binY - bottomBinY] + eps));
1196  cellInBinTail++)
1197  {
1198  cArea += placementInfo->getActualOccupationByCellId(boxBCellIds[cellInBinTail]);
1199  oriTopY = cellLoc[boxBCellIds[cellInBinTail]].Y;
1200  num++;
1201  }
1202  cellInBinTail--;
1203  if (num > 0)
1204  {
1205  assert(binY >= 0);
1206  assert((unsigned int)binY < binGrid.size());
1207  float newBottomY = binGrid[binY][leftBinX]->bottom() + placementInfo->getBinGridH() / (num + 1.0);
1208  float newTopY = binGrid[binY][leftBinX]->top() - placementInfo->getBinGridH() / (num + 1.0);
1209  float rangeold = oriTopY - oriBottomY;
1210  float rangenew = newTopY - newBottomY;
1211  assert(rangeold > -1e-5);
1212  assert(rangenew > -1e-5);
1213  if (fabs(rangeold) < 1e-5)
1214  {
1215  float newBottomc = (newBottomY + newTopY) / 2;
1216  for (int ci = cellInBinHead; ci <= cellInBinTail; ++ci)
1217  {
1218  cellLoc[boxBCellIds[ci]].Y = newBottomc;
1219  }
1220  }
1221  else
1222  {
1223  float scale = rangenew / rangeold;
1224  assert(scale > -1e-5);
1225  for (int ci = cellInBinHead; ci <= cellInBinTail; ++ci)
1226  {
1227  cellLoc[boxBCellIds[ci]].Y = newBottomY + (cellLoc[boxBCellIds[ci]].Y - oriBottomY) * scale;
1228  }
1229  }
1230  }
1231  cellInBinHead = cellInBinTail + 1;
1232  }
1233  }
1234  else
1235  {
1236  delete *boxB;
1237  *boxB = nullptr;
1238  }
1239 
1240  return;
1241 }
1242 
1243 const std::string currentDateTime()
1244 {
1245  time_t now = time(0);
1246  struct tm tstruct;
1247  char buf[80];
1248  tstruct = *localtime(&now);
1249  // Visit http://en.cppreference.com/w/cpp/chrono/c/strftime
1250  // for more information about date/time format
1251  strftime(buf, sizeof(buf), "%Y-%m-%d.%X", &tstruct);
1252 
1253  return buf;
1254 }
1255 
1256 void GeneralSpreader::dumpSiteGridDensity(std::string dumpFileName)
1257 {
1258  dumpFileName =
1259  dumpFileName + "-" + sharedCellType + "-" + currentDateTime() + "-" + std::to_string(dumpSiteGridDensityCnt);
1260  print_status("GeneralSpreader: dumping density to: " + dumpFileName);
1261  std::vector<std::vector<PlacementInfo::PlacementBinInfo *>> &curBinGrid =
1263 
1264  std::ofstream outfile0(dumpFileName.c_str());
1265  assert(outfile0.is_open() && outfile0.good() &&
1266  "The path for site density dumping does not exist and please check your path settings");
1267  for (auto &row : curBinGrid)
1268  {
1269  for (auto curBin : row)
1270  {
1271  outfile0 << curBin->getRealUtilizationRate() << " ";
1272  }
1273  outfile0 << "\n";
1274  }
1275  outfile0.close();
1277 }
1278 
1280 {
1281  if (JSONCfg.find("DumpLUTFFCoordTrace-GeneralSpreader") != JSONCfg.end())
1282  {
1283  std::string dumpFile = JSONCfg["DumpLUTFFCoordTrace-GeneralSpreader"] + "-" + sharedCellType + "-" +
1284  std::to_string(LUTFFCoordinateDumpCnt) + ".gz";
1285  print_status("GeneralSpreader: dumping coordinate archieve to: " + dumpFile);
1287  if (dumpFile != "")
1288  {
1289  std::stringstream outfile0;
1290  for (auto curPU : placementInfo->getPlacementUnits())
1291  {
1292  if (auto curUnpackedCell = dynamic_cast<PlacementInfo::PlacementUnpackedCell *>(curPU))
1293  {
1294  float cellX = curUnpackedCell->X();
1295  float cellY = curUnpackedCell->Y();
1296  DesignInfo::DesignCell *curCell = curUnpackedCell->getCell();
1297  if (curCell->isFF() || curCell->isLUT())
1298  {
1299  outfile0 << cellX << " " << cellY << " " << curCell->getName() << "\n";
1300  }
1301  }
1302  else if (auto curMacro = dynamic_cast<PlacementInfo::PlacementMacro *>(curPU))
1303  {
1304  for (int vId = 0; vId < curMacro->getNumOfCells(); vId++)
1305  {
1306  float offsetX_InMacro, offsetY_InMacro;
1307  DesignInfo::DesignCellType cellType;
1308  curMacro->getVirtualCellInfo(vId, offsetX_InMacro, offsetY_InMacro, cellType);
1309  float cellX = curMacro->X() + offsetX_InMacro;
1310  float cellY = curMacro->Y() + offsetY_InMacro;
1311 
1312  if (DesignInfo::isFF(cellType) || DesignInfo::isLUT(cellType))
1313  {
1314  if (curMacro->getCell(vId))
1315  outfile0 << cellX << " " << cellY << " " << curMacro->getCell(vId)->getName() << "\n";
1316  else
1317  outfile0 << cellX << " " << cellY << "\n";
1318  }
1319  }
1320  }
1321  }
1322  writeStrToGZip(dumpFile, outfile0);
1323  print_status("GeneralSpreader: dumped coordinate archieve to: " + dumpFile);
1324  }
1325  }
1326 }
1327 
1328 std::ostream &operator<<(std::ostream &os, GeneralSpreader::SpreadRegion::SubBox *curBox)
1329 {
1330  os << "Box: Top:" << curBox->top() << " Bottom:" << curBox->bottom() << " Left:" << curBox->left()
1331  << " Right:" << curBox->right();
1332  return os;
1333 }
1334 
1336 {
1337  if (dumpFileName != "")
1338  {
1339  dumpCnt++;
1340  dumpFileName = dumpFileName + "-" + std::to_string(dumpCnt) + ".gz";
1341  // print_status("GeneralSpreader: dumping coordinate archieve to: " + dumpFileName);
1342  std::stringstream outfile0;
1343  std::vector<PlacementInfo::Location> &cellLoc = placementInfo->getCellId2location();
1344  for (auto tmpCell : curRegion->getCells())
1345  {
1346  outfile0 << cellLoc[tmpCell->getCellId()].X << " " << cellLoc[tmpCell->getCellId()].Y << tmpCell << "\n";
1347  }
1348  writeStrToGZip(dumpFileName, outfile0);
1349  // print_status("GeneralSpreader: dumped coordinate archieve to: " + dumpFileName);
1350  }
1351 }
1352 
1353 void GeneralSpreader::DumpPUCoordinate(std::string dumpFileName,
1354  std::vector<PlacementInfo::PlacementUnit *> &involvedPUVec)
1355 {
1356  if (dumpFileName != "")
1357  {
1358  dumpCnt++;
1359  dumpFileName = dumpFileName + "-" + std::to_string(dumpCnt) + ".gz";
1360  // print_status("GeneralSpreader: dumping coordinate archieve to: " + dumpFileName);
1361  std::stringstream outfile0;
1362  for (auto curPU : involvedPUVec)
1363  {
1364  outfile0 << curPU->X() << " " << curPU->Y() << " " << curPU << "\n";
1365  }
1366  writeStrToGZip(dumpFileName, outfile0);
1367  // print_status("GeneralSpreader: dumped coordinate archieve to: " + dumpFileName);
1368  }
1369 }
GeneralSpreader::SpreadRegion::bottom
int bottom()
get the bottom bin coordinate Y of the SpreadRegion in bin grid
Definition: GeneralSpreader.h:779
PlacementInfo::getBinGrid
std::vector< std::vector< PlacementBinInfo * > > & getBinGrid(unsigned int BELTypeId)
Get the Bin Grid object.
Definition: PlacementInfo.h:3099
GeneralSpreader::SpreadRegion::cellsInRegion
std::set< DesignInfo::DesignCell * > cellsInRegion
a set of cells in the SpreadRegion
Definition: GeneralSpreader.h:1126
PlacementInfo::PlacementBinInfo::getUtilizationRate
float getUtilizationRate()
Get the Utilization Rate: utilization / (capacity * binShrinkRatio)
Definition: PlacementInfo.h:578
GeneralSpreader::SpreadRegion::cellsInRegionVec
std::vector< DesignInfo::DesignCell * > cellsInRegionVec
a vector of cells in the SpreadRegion
Definition: GeneralSpreader.h:1133
GeneralSpreader::dumpSiteGridDensityCnt
int dumpSiteGridDensityCnt
Definition: GeneralSpreader.h:1236
GeneralSpreader::DumpPUCoordinate
void DumpPUCoordinate(std::string dumpFileName, std::vector< PlacementInfo::PlacementUnit * > &involvedPUVec)
Definition: GeneralSpreader.cc:1353
PlacementInfo::getPlacementUnits
std::vector< PlacementUnit * > & getPlacementUnits()
Definition: PlacementInfo.h:2810
PlacementInfo::PlacementBinInfo::right
float right()
return the right boundary of the bin
Definition: PlacementInfo.h:703
PlacementInfo::PlacementBinInfo::bottom
float bottom()
return the bottom boundary of the bin
Definition: PlacementInfo.h:723
GeneralSpreader::expandedRegions
std::vector< GeneralSpreader::SpreadRegion * > expandedRegions
the obtained SpreadRegion s which can be processed in parallel.
Definition: GeneralSpreader.h:1292
PlacementInfo::PlacementBinInfo
BEL bin for global placement for a specific shared BEL type.
Definition: PlacementInfo.h:372
GeneralSpreader::SpreadRegion::getOverflowRatio
float getOverflowRatio()
Get the resource overflow ratio.
Definition: GeneralSpreader.h:809
PlacementInfo::getSharedBELTypeId
int getSharedBELTypeId(std::string tmpStr)
Definition: PlacementInfo.h:2942
GeneralSpreader::SpreadRegion::SubBox::top
int top()
get the top bin coordinate Y of the SubBox in bin grid
Definition: GeneralSpreader.h:1018
PlacementInfo::PlacementMacro
a fixed group of multiple standard cells with constraints of their relative locations
Definition: PlacementInfo.h:1525
DesignInfo::DesignCell
a DesignCell in design netlist, DesignPin objects of which might connect to DesignNet objects
Definition: DesignInfo.h:782
GeneralSpreader::SpreadRegion::smartFindExpandDirection
bool smartFindExpandDirection(std::set< PlacementInfo::PlacementBinInfo * > &coveredBinSet)
find the legal expansion direction
Definition: GeneralSpreader.h:375
paintPlacement.y
list y
Definition: paintPlacement.py:153
GeneralSpreader::dumpLUTFFCoordinate
void dumpLUTFFCoordinate()
Definition: GeneralSpreader.cc:1279
GeneralSpreader::GeneralSpreader
GeneralSpreader(PlacementInfo *placementInfo, std::map< std::string, std::string > &JSONCfg, std::string &sharedCellType, int currentIteration, float capacityShrinkRatio, bool verbose=true)
Construct a new General Spreader object.
Definition: GeneralSpreader.cc:34
GeneralSpreader::binGrid
std::vector< std::vector< PlacementInfo::PlacementBinInfo * > > & binGrid
a reference of the global bin grid for data accessing and updating of cell density
Definition: GeneralSpreader.h:1234
GeneralSpreader::updatePlacementUnitsWithSpreadedCellLocationsWorker
static void updatePlacementUnitsWithSpreadedCellLocationsWorker(PlacementInfo *placementInfo, std::set< PlacementInfo::PlacementUnit * > &involvedPUs, std::set< DesignInfo::DesignCell * > &involvedCells, std::vector< PlacementInfo::PlacementUnit * > &involvedPUVec, float forgetRatio, float displacementLimit, int startId, int endId)
multi-threading workers for updating the information of the involved PlacementUnit(s)
Definition: GeneralSpreader.cc:307
GeneralSpreader::nJobs
int nJobs
Definition: GeneralSpreader.h:1238
PlacementInfo::getCellId2location
std::vector< Location > & getCellId2location()
Definition: PlacementInfo.h:3600
DesignInfo::DesignCellType
DesignCellType
design cell types
Definition: DesignInfo.h:73
GeneralSpreader::SpreadRegion::top
int top()
get the top bin coordinate Y of the SpreadRegion in bin grid
Definition: GeneralSpreader.h:769
GeneralSpreader::verbose
bool verbose
Definition: GeneralSpreader.h:1228
GeneralSpreader::SpreadRegion::left
int left()
get the left bin coordinate X of the SpreadRegion in bin grid
Definition: GeneralSpreader.h:789
GeneralSpreader::SpreadRegion::SubBox
SubBox is the exact container which is the object for bi-partitioning-based cell spreading.
Definition: GeneralSpreader.h:822
GeneralSpreader::SpreadRegion::SubBox::bottom
int bottom()
get the bottom bin coordinate Y of the SubBox in bin grid
Definition: GeneralSpreader.h:1028
GeneralSpreader::SpreadRegion::SubBox::spreadAndPartition
void spreadAndPartition()
spread cells and partition the SubBox into smaller SubBoxes
Definition: GeneralSpreader.cc:706
GeneralSpreader::SpreadRegion::topBinY
int topBinY
Definition: GeneralSpreader.h:1080
GeneralSpreader::overflowBins
std::vector< PlacementInfo::PlacementBinInfo * > overflowBins
a vector of the found overflow bins in the current placement
Definition: GeneralSpreader.h:1254
PlacementInfo::PlacementUnit::X
float X()
Definition: PlacementInfo.h:1024
PlacementInfo::getDeviceInfo
DeviceInfo * getDeviceInfo()
Definition: PlacementInfo.h:3308
GeneralSpreader::capacityShrinkRatio
float capacityShrinkRatio
Definition: GeneralSpreader.h:1227
GeneralSpreader::dumpSiteGridDensity
void dumpSiteGridDensity(std::string dumpFileName)
Definition: GeneralSpreader.cc:1256
GeneralSpreader::DumpCellsCoordinate
void DumpCellsCoordinate(std::string dumpFileName, GeneralSpreader::SpreadRegion *curRegion)
Definition: GeneralSpreader.cc:1335
GeneralSpreader::SpreadRegion::binGrid
std::vector< std::vector< PlacementInfo::PlacementBinInfo * > > & binGrid
a reference of the global bin grid for data accessing and updating of cell density
Definition: GeneralSpreader.h:1099
GeneralSpreader::SpreadRegion::rightBinX
int rightBinX
Definition: GeneralSpreader.h:1081
operator<<
std::ostream & operator<<(std::ostream &os, GeneralSpreader::SpreadRegion::SubBox *curBox)
Definition: GeneralSpreader.cc:1328
GeneralSpreader::SpreadRegion::totalUtilization
float totalUtilization
Definition: GeneralSpreader.h:1078
delayVisualization.X
X
Definition: delayVisualization.py:80
GeneralSpreader::recordSpreadedCellLocations
void recordSpreadedCellLocations()
record the spreaded location in PlacementInfo for later forget-ratio-based location updating
Definition: GeneralSpreader.cc:698
GeneralSpreader::SpreadRegion::totalCapacity
float totalCapacity
Definition: GeneralSpreader.h:1077
PlacementInfo::getActualOccupationByCellId
float getActualOccupationByCellId(int id)
Get the Actual Occupation By Cell Id.
Definition: PlacementInfo.h:2995
GeneralSpreader::SpreadRegion::simpleFindExpandDirection
bool simpleFindExpandDirection(std::set< PlacementInfo::PlacementBinInfo * > &coveredBinSet)
find the expansion direction iteratively in pre-defined order
Definition: GeneralSpreader.h:689
GeneralSpreader::SpreadRegion
SpreadRegion is an object that record cell spreading region information, including boundaries,...
Definition: GeneralSpreader.h:86
DesignInfo::isFF
static bool isFF(DesignCellType cellType)
Definition: DesignInfo.h:1360
DesignInfo::DesignCell::isFF
bool isFF()
Definition: DesignInfo.h:933
print_status
void print_status(std::string tmp_string)
Definition: strPrint.cc:44
GeneralSpreader::useSimpleExpland
bool useSimpleExpland
simple expansion will iteratively try 4 directions to expand the SpreadRegion
Definition: GeneralSpreader.h:1246
GeneralSpreader::SpreadRegion::overflowRatio
float overflowRatio
Definition: GeneralSpreader.h:1079
DesignInfo::DesignElement::getName
const std::string & getName() const
Definition: DesignInfo.h:243
GeneralSpreader::SpreadRegion::SubBox::spreadCellsH
void spreadCellsH(SubBox **boxA, SubBox **boxB)
split horizontally the SubBox into smaller ones and assign cells to them
Definition: GeneralSpreader.cc:752
currentDateTime
const std::string currentDateTime()
Definition: GeneralSpreader.cc:1243
GeneralSpreader::expandFromABin
GeneralSpreader::SpreadRegion * expandFromABin(PlacementInfo::PlacementBinInfo *curBin, float capacityShrinkRatio, unsigned int numBinThr=1000000)
obtain a SpreadRegion by expanding a cell spreading window from an overflow bin
Definition: GeneralSpreader.cc:613
PlacementInfo::getPlacementUnitByCellId
PlacementUnit * getPlacementUnitByCellId(int cellId)
Definition: PlacementInfo.h:3127
GeneralSpreader::SpreadRegion::simpleExpand
void simpleExpand(std::set< PlacementInfo::PlacementBinInfo * > &coveredBinSet)
select the the expansion direction which is found in a pre-defined order
Definition: GeneralSpreader.h:724
GeneralSpreader::placementInfo
PlacementInfo * placementInfo
Definition: GeneralSpreader.h:1223
GeneralSpreader::coveredBinSet
std::set< PlacementInfo::PlacementBinInfo * > coveredBinSet
a set of the bins covered by existing SpreadRegion(s)
Definition: GeneralSpreader.h:1266
DesignInfo::DesignCell::getCellId
int getCellId()
Get the Cell Id in the cell list.
Definition: DesignInfo.h:1037
DesignInfo::DesignCell::isLUT
bool isLUT()
Definition: DesignInfo.h:927
writeStrToGZip
void writeStrToGZip(std::string fileName, std::stringstream &data)
Definition: dumpZip.cc:29
GeneralSpreader::SpreadRegion::getCells
std::vector< DesignInfo::DesignCell * > & getCells()
Get the cells in the SpreadRegion.
Definition: GeneralSpreader.h:759
GeneralSpreader::SpreadRegion::SubBox::left
int left()
get the left bin coordinate X of the SubBox in bin grid
Definition: GeneralSpreader.h:1038
PlacementInfo::legalizeXYInArea
void legalizeXYInArea(PlacementUnit *curPU, float &fX, float &fY)
move the PlacementUnit to ensure the cells in it are within the device area.
Definition: PlacementInfo.h:3364
GeneralSpreader::SpreadRegion::leftBinX
int leftBinX
Definition: GeneralSpreader.h:1081
PlacementInfo::transferCellBinInfo
void transferCellBinInfo(int cellId, float fX, int fY)
update the bin information of a design cell when it is moved to a new location
Definition: PlacementInfo.h:3751
GeneralSpreader::SpreadRegion::binSetInRegion
std::set< PlacementInfo::PlacementBinInfo * > binSetInRegion
a set of bins in the SpreadRegion
Definition: GeneralSpreader.h:1146
GeneralSpreader.h
This header file contains the definitions of GeneralSpreader class and its internal modules and APIs ...
GeneralSpreader::SpreadRegion::isRegionOverlap
bool isRegionOverlap(int tmpRegionTopBinY, int tmpRegionBottomBinY, int tmpRegionLeftBinX, int tmpRegionRightBinX)
check whether the SpreadRegion is overlapped with a given boundary
Definition: GeneralSpreader.h:132
PlacementInfo::getBinGridW
float getBinGridW()
Get the width of a bin in grid.
Definition: PlacementInfo.h:3615
PlacementInfo::getPU2ClockRegionColumn
std::map< PlacementUnit *, int > & getPU2ClockRegionColumn()
get the PlacementUnit Mapping to clock region column for timing optimzation
Definition: PlacementInfo.h:4353
PlacementInfo::PlacementBinInfo::top
float top()
return the top boundary of the bin
Definition: PlacementInfo.h:713
GeneralSpreader::makeCellInLegalArea
static void makeCellInLegalArea(PlacementInfo *placementInfo, float &cellX, float &cellY)
ensure the X/Y is in the legal range of the target device
Definition: GeneralSpreader.h:1192
GeneralSpreader::LUTFFCoordinateDumpCnt
int LUTFFCoordinateDumpCnt
Definition: GeneralSpreader.h:1237
GeneralSpreader::updatePlacementUnitsWithSpreadedCellLocations
void updatePlacementUnitsWithSpreadedCellLocations(std::set< PlacementInfo::PlacementUnit * > &involvedPUs, std::set< DesignInfo::DesignCell * > &involvedCells, std::vector< PlacementInfo::PlacementUnit * > &involvedPUVec, float forgetRatio, bool enableClockRegionAware, float displacementLimit)
update the information of the involved PlacementUnit(s)
Definition: GeneralSpreader.cc:414
PlacementInfo::enforceLegalizeXYInArea
void enforceLegalizeXYInArea(PlacementUnit *curPU)
move the PlacementUnit to ensure the cells in it are within the device area.
Definition: PlacementInfo.h:3402
delayVisualization.Y
Y
Definition: delayVisualization.py:80
GeneralSpreader::JSONCfg
std::map< std::string, std::string > & JSONCfg
Definition: GeneralSpreader.h:1224
GeneralSpreader::SpreadRegion::addBinRegion
void addBinRegion(int newRegionTopBinY, int newRegionBottomBinY, int newRegionLeftBinX, int newRegionRightBinX, std::set< PlacementInfo::PlacementBinInfo * > &coveredBinSet)
add cell bins into SpreadRegion with a new boundary and update region information including boundary ...
Definition: GeneralSpreader.cc:656
GeneralSpreader::SpreadRegion::SubBox::right
int right()
get the right bin coordinate X of the SubBox in bin grid
Definition: GeneralSpreader.h:1048
GeneralSpreader::dumpCnt
int dumpCnt
Definition: GeneralSpreader.h:1248
PlacementInfo::PlacementUnpackedCell
the smallest, indivisible, representable component. It will include only one standard cell
Definition: PlacementInfo.h:1447
PlacementInfo::PlacementBinInfo::left
float left()
return the left boundary of the bin
Definition: PlacementInfo.h:693
PlacementInfo::getBinGridH
float getBinGridH()
Get the height of a bin in grid.
Definition: PlacementInfo.h:3625
GeneralSpreader::sharedCellType
std::string sharedCellType
Definition: GeneralSpreader.h:1225
print_info
void print_info(std::string tmp_string)
Definition: strPrint.cc:39
checkHalfColumn.i
int i
Definition: checkHalfColumn.py:5
GeneralSpreader::overflowBinSet
std::set< PlacementInfo::PlacementBinInfo * > overflowBinSet
a set of the found overflow bins in the current placement
Definition: GeneralSpreader.h:1260
PlacementInfo::getPlacementUnitByCell
PlacementUnit * getPlacementUnitByCell(DesignInfo::DesignCell *curCell)
Definition: PlacementInfo.h:3120
DesignInfo::isLUT
static bool isLUT(DesignCellType cellType)
Definition: DesignInfo.h:1324
GeneralSpreader::SpreadRegion::smartExpand
void smartExpand(std::set< PlacementInfo::PlacementBinInfo * > &coveredBinSet)
select the expansion direction greedily
Definition: GeneralSpreader.h:491
siteSortCmp
bool siteSortCmp(PlacementInfo::PlacementBinInfo *a, PlacementInfo::PlacementBinInfo *b)
Definition: GeneralSpreader.cc:262
GeneralSpreader::SpreadRegion::bottomBinY
int bottomBinY
Definition: GeneralSpreader.h:1080
GeneralSpreader::findOverflowBins
void findOverflowBins(float overflowThreshold)
find the overflow bins in the placement accoridng to a given threshold
Definition: GeneralSpreader.cc:267
GeneralSpreader::SpreadRegion::binsInRegion
std::vector< PlacementInfo::PlacementBinInfo * > binsInRegion
a vector of bins in the SpreadRegion
Definition: GeneralSpreader.h:1140
GeneralSpreader::SpreadRegion::getBinsInRegion
std::vector< PlacementInfo::PlacementBinInfo * > & getBinsInRegion()
Get the bins in the SpreadRegion.
Definition: GeneralSpreader.h:176
DeviceInfo::getClockRegions
std::vector< std::vector< ClockRegion * > > & getClockRegions()
Get the Clock Regions in an 2D array clockregion[Y][X].
Definition: DeviceInfo.h:1261
GeneralSpreader::SpreadRegion::right
int right()
get the right bin coordinate X of the SpreadRegion in bin grid
Definition: GeneralSpreader.h:799
GeneralSpreader::SpreadRegion::SubBox::spreadCellsV
void spreadCellsV(SubBox **boxA, SubBox **boxB)
split vertically the SubBox into smaller ones and assign cells to them
Definition: GeneralSpreader.cc:986
GeneralSpreader::SpreadRegion::SubBox::cellIds
std::vector< int > cellIds
the cells in this SubBox
Definition: GeneralSpreader.h:1060
PlacementInfo
Information related to FPGA placement (wirelength optimization, cell spreading, legalization,...
Definition: PlacementInfo.h:59
GeneralSpreader::spreadPlacementUnits
void spreadPlacementUnits(float forgetRatio, bool enableClockRegionAware=false, float displacementLimit=-10, unsigned int spreadRegionBinSizeLimit=1000000)
spread cells with a given forgetting ratio
Definition: GeneralSpreader.cc:52