AMF-Placer  2.0
An Open-Source Timing-driven Analytical Mixed-size FPGA Placer
ClusterPlacer.cc
Go to the documentation of this file.
1 
26 #include "ClusterPlacer.h"
27 #include <algorithm>
28 #include <cmath>
29 #include <cstdlib>
30 #include <ctime>
31 #include <iostream>
32 
33 ClusterPlacer::ClusterPlacer(PlacementInfo *placementInfo, std::map<std::string, std::string> &JSONCfg,
34  float connectionToFixedFactor)
35  : placementInfo(placementInfo), JSONCfg(JSONCfg), connectionToFixedFactor(connectionToFixedFactor)
36 {
37  if (JSONCfg.find("ClusterPlacerVerbose") != JSONCfg.end())
38  verbose = JSONCfg["ClusterPlacerVerbose"] == "true";
39  if (JSONCfg.find("y2xRatio") != JSONCfg.end())
40  y2xRatio = std::stof(JSONCfg["y2xRatio"]);
41 
42  if (JSONCfg.find("jobs") != JSONCfg.end())
43  {
44  jobs = std::stoul(JSONCfg["jobs"]);
45  }
46  else
47  {
48  jobs = 1;
49  }
50 
51  clockRegionXNum = std::stoi(JSONCfg["clockRegionXNum"]);
52  clockRegionYNum = std::stoi(JSONCfg["clockRegionYNum"]);
53 
54  if (JSONCfg.find("RandomInitialPlacement") != JSONCfg.end())
55  {
56  randomInitialPlacement = JSONCfg["RandomInitialPlacement"] == "true";
57  }
58 }
59 
61 {
62  print_status("Cluster Placement Start.");
63 
65  {
67  placeClusters();
68 
69  if (JSONCfg.find("drawClusters") != JSONCfg.end())
70  {
71  if (JSONCfg["drawClusters"] == "true")
72  drawClusters();
73  }
74  if (JSONCfg.find("Dump Cluster file") != JSONCfg.end())
75  {
76  dumpClusters();
77  }
78  }
79  else
80  {
81  srandom(20213654);
82  for (auto curPU : placementInfo->getPlacementUnits())
83  {
84  if (!curPU->isFixed())
85  {
88  placementInfo->legalizeXYInArea(curPU, fX, fY);
89  curPU->setAnchorLocation(fX, fY);
90  }
91  }
92  }
93 
96 
97  print_status("Cluster Placement Done.");
98 }
99 
101 {
102  print_status("Clustering Start.");
103 
106  // refineClustersWithPredefinedClusters();
107 
109 
110  print_status("Placement Unit Clustering Done.");
111 }
112 
114 {
115  int minClusterCellNum =
116  std::min(unsigned(placementInfo->getNumCells() * 0.25),
117  unsigned(avgClusterSizeRequirement)); // 22000 is the rough number of cells in a clock region, Please
118  // note that minCellClusterSize is not the number of
119  // placementunits but the number of cells
120 
121  int eachClusterDSPNum = 96;
122  int eachClusterBRAMNum = 24;
123  int gridH = std::stoi(JSONCfg["clockRegionYNum"]);
124  int gridW = std::stoi(JSONCfg["clockRegionXNum"]);
125 
126  if (JSONCfg.find("clockRegionDSPNum") != JSONCfg.end())
127  {
128  eachClusterDSPNum = std::stoi(JSONCfg["clockRegionDSPNum"]);
129  }
130  if (JSONCfg.find("clockRegionBRAMNum") != JSONCfg.end())
131  {
132  eachClusterBRAMNum = std::stoi(JSONCfg["clockRegionBRAMNum"]);
133  }
134 
135  clockBasedPartitioning(minClusterCellNum, eachClusterDSPNum, eachClusterBRAMNum);
136  if (isClustersToLarges() && clusters.size() < 0.6 * gridW * gridH)
137  {
138  maxMinCutRate = 0.1;
139  clockBasedPartitioning(minClusterCellNum, eachClusterDSPNum, eachClusterBRAMNum);
141  }
142 }
143 
145 {
146  // handle the long paths
148  // auto simpleTimingGraph = placementInfo->getTimingInfo()->getSimplePlacementTimingGraph();
149  int pathLengthThr = placementInfo->getLongPathThresholdLevel();
150  std::set<int> extractedCellIds;
151  extractedCellIds.clear();
152 
153  print_status("ClusterPlacer:: create long path cluster units (pathLengthThr=" + std::to_string(pathLengthThr) +
154  ")");
155  unsigned int maxSize = 0;
156  for (auto timingNode : timingNodes)
157  {
158  if (timingNode->getLongestPathLength() > pathLengthThr && timingNode->getForwardLevel() > pathLengthThr * 0.333)
159  {
160  auto curCell = timingNode->getDesignNode();
161  auto tmpPU = placementInfo->getPlacementUnitByCell(curCell);
162  if (placementUnitId2ClusterUnitId[tmpPU->getId()] < 0)
163  {
164  std::vector<int> candidateCellIds; //= simpleTimingGraph->BFSFromNode(timingNode->getId(),
165  // pathLengthThr, 1000000, extractedCellIds);
166  candidateCellIds.clear();
167 
168  if (timingNode->getOutEdges().size() >= 16)
169  {
170 
171  for (auto outEdge : timingNode->getOutEdges())
172  {
173  if (extractedCellIds.find(outEdge->getSink()->getId()) == extractedCellIds.end())
174  candidateCellIds.push_back(outEdge->getSink()->getId());
175  }
176 
177  // if (candidateCellIds.size() < 16)
178  // continue;
179  }
180  else
181  {
182  continue;
183  }
184 
185  std::set<PlacementInfo::PlacementUnit *> PUsInLongPaths;
186  PUsInLongPaths.clear();
187  for (auto &candidateCellId : candidateCellIds)
188  {
189  extractedCellIds.insert(candidateCellId);
190  auto PUInPath = placementInfo->getPlacementUnitByCellId(candidateCellId);
191  // the clusters should not be overlapped with each other
192  if (placementUnitId2ClusterUnitId[PUInPath->getId()] < 0)
193  PUsInLongPaths.insert(PUInPath);
194  }
195 
196  if (PUsInLongPaths.size() == 0)
197  continue;
198 
200  for (auto PUInPath : PUsInLongPaths)
201  {
202  assert(placementUnitId2ClusterUnitId[PUInPath->getId()] < 0);
203  placementUnitId2ClusterUnitId[PUInPath->getId()] = curClusterUnit->getId();
204  curClusterUnit->addPlacementUnit(PUInPath);
205 
206  if (!PUInPath->isFixed())
207  {
208  if (auto unpackedCell = dynamic_cast<PlacementInfo::PlacementUnpackedCell *>(PUInPath))
209  {
210  int cellId = unpackedCell->getCell()->getCellId();
211  extractedCellIds.insert(cellId);
212  }
213  else if (auto curMacro = dynamic_cast<PlacementInfo::PlacementMacro *>(PUInPath))
214  {
215  for (auto tmpCell : curMacro->getCells())
216  {
217  int cellId = tmpCell->getCellId();
218  extractedCellIds.insert(cellId);
219  }
220  }
221  }
222  }
223 
224  if (PUsInLongPaths.size() > maxSize)
225  maxSize = PUsInLongPaths.size();
226 
227  clusterUnits.push_back(curClusterUnit);
228  }
229  }
230  assert(clusterUnits.size() <= placementInfo->getPlacementUnits().size());
231  }
232  print_info("ClusterPlacer: largest long-path cluster size=" + std::to_string(maxSize));
233 }
234 
236 {
237  if (placementInfo->getDesignInfo()->getClocksInDesign().size() > 20)
238  return;
239  // add the predefined clusters
240  for (auto curClock : placementInfo->getDesignInfo()->getClocksInDesign())
241  {
242  auto &cellSet = placementInfo->getDesignInfo()->getCellsUnderClock(curClock);
243  if (cellSet.size() > 5000 || cellSet.size() < 20)
244  continue;
245 
246  std::set<PlacementInfo::PlacementUnit *> PUsInuserDefinedClusterCluster;
247  PUsInuserDefinedClusterCluster.clear();
248  for (auto &curCell : cellSet)
249  {
250  auto tmpPU = placementInfo->getPlacementUnitByCell(curCell);
251  // the clusters should not be overlapped with each other
252  if (placementUnitId2ClusterUnitId[tmpPU->getId()] < 0)
253  PUsInuserDefinedClusterCluster.insert(tmpPU);
254  }
255 
257  for (auto tmpPU : PUsInuserDefinedClusterCluster)
258  {
259  assert(placementUnitId2ClusterUnitId[tmpPU->getId()] < 0);
260  placementUnitId2ClusterUnitId[tmpPU->getId()] = curClusterUnit->getId();
261  curClusterUnit->addPlacementUnit(tmpPU);
262  }
263  print_info("build a cluster (size=" + std::to_string(curClusterUnit->getUnits().size()) + ") for clock [" +
264  curClock->getName() + "].");
265  clusterUnits.push_back(curClusterUnit);
266  }
267 }
268 
270 {
271  std::vector<std::vector<DesignInfo::DesignCell *>> &predefinedCellClusters =
273  placementUnitId2ClusterUnitId = std::vector<int>(placementInfo->getPlacementUnits().size(), -1);
274  clusterUnits.clear();
275  clusterNets.clear();
276 
277  // add the predefined clusters
278  int overlapCnt = 0;
279  for (auto &clusterCellSet : predefinedCellClusters)
280  {
281 
282  bool noOverlap = true;
283  std::set<PlacementInfo::PlacementUnit *> PUsInuserDefinedClusterCluster;
284  PUsInuserDefinedClusterCluster.clear();
285  for (auto tmpCell : clusterCellSet)
286  {
287  auto tmpPU = placementInfo->getPlacementUnitByCell(tmpCell);
288  // the clusters should not be overlapped with each other
289  if (placementUnitId2ClusterUnitId[tmpPU->getId()] >= 0)
290  {
291  noOverlap = false;
292  break;
293  }
294  PUsInuserDefinedClusterCluster.insert(tmpPU);
295  }
296  if (noOverlap)
297  {
299  for (auto tmpPU : PUsInuserDefinedClusterCluster)
300  {
301  assert(placementUnitId2ClusterUnitId[tmpPU->getId()] < 0);
302  placementUnitId2ClusterUnitId[tmpPU->getId()] = curClusterUnit->getId();
303  curClusterUnit->addPlacementUnit(tmpPU);
304  }
305  clusterUnits.push_back(curClusterUnit);
306  }
307  else
308  {
309  overlapCnt++;
310  }
311  }
312 
313  print_info("There are " + std::to_string(predefinedCellClusters.size()) + " predefined userDefinedClusters and " +
314  std::to_string(overlapCnt) + " overlapped clusters and totally " + std::to_string(clusterUnits.size()) +
315  " userDefinedCluster clusters are identified.");
316 
317  // handle the other placement units
319 
320  // create the nets between the cluster units
322 }
323 
325 {
326  for (auto tmpPU : placementInfo->getPlacementUnits())
327  {
328  if (placementUnitId2ClusterUnitId[tmpPU->getId()] < 0)
329  {
331  clusterUnits.push_back(curClusterUnit);
332  curClusterUnit->addPlacementUnit(tmpPU);
333  placementUnitId2ClusterUnitId[tmpPU->getId()] = curClusterUnit->getId();
334  }
335  }
336 }
337 
338 void ClusterPlacer::basicPartitioning(int minClusterCellNum, int eachClusterDSPNum, int eachClusterBRAMNum)
339 {
341  new GraphPartitioner<std::vector<PlacementInfo::PlacementUnit *>, std::vector<PlacementInfo::PlacementNet *>>(
344  basicGraphPartitioner->solve(eachClusterDSPNum, eachClusterBRAMNum);
346  delete basicGraphPartitioner;
347 
348  placementUnit2ClusterId.clear();
350  int clusterId = 0;
351  for (auto cluster : clusters)
352  {
353  for (int placementUnitId : cluster)
354  {
355  placementUnit2ClusterId[placementUnitId] = clusterId;
356  }
357  clusterId++;
358  }
359 }
360 
361 void ClusterPlacer::userDefinedClusterBasedPartitioning(int minClusterCellNum, int eachClusterDSPNum,
362  int eachClusterBRAMNum)
363 {
366  new GraphPartitioner<std::vector<PlacementInfo::ClusterUnit *>, std::vector<PlacementInfo::ClusterNet *>>(
367  clusterUnits, clusterNets, minClusterCellNum, jobs, verbose);
369  userDefinedClusterBasedGraphPartitioner->solve(eachClusterDSPNum, eachClusterBRAMNum);
372 
373  placementUnit2ClusterId.clear();
375  int clusterId = 0;
376 
377  std::vector<std::set<int>> newClusters(0);
378  for (auto cluster : clusters)
379  {
380  std::set<int> curCluster;
381  int tmpWeight = 0;
382  for (int clusterUnitId : cluster)
383  {
384  for (auto tmpPU : clusterUnits[clusterUnitId]->getUnits())
385  {
386  assert(placementUnit2ClusterId[tmpPU->getId()] < 0);
387  placementUnit2ClusterId[tmpPU->getId()] = clusterId;
388  curCluster.insert(tmpPU->getId());
389  tmpWeight += tmpPU->getWeight();
390  }
391  }
392  newClusters.push_back(curCluster);
393  clusterId++;
394  }
395 
396  clusters = newClusters;
397 }
398 
399 void ClusterPlacer::clockBasedPartitioning(int minClusterCellNum, int eachClusterDSPNum, int eachClusterBRAMNum)
400 {
402 
404  print_info("ClusterPlacer: There are " +
405  std::to_string(placementInfo->getDesignInfo()->getClocksInDesign().size()) +
406  " global clocks and totally " + std::to_string(clusterUnits.size()) + " clock clusters are identified.");
407 
408  int clusterNumRecord = clusterUnits.size();
410  print_info("ClusterPlacer: There are totally " + std::to_string(clusterUnits.size() - clusterNumRecord) +
411  " long-path clusters are identified.");
412 
413  clusterNumRecord = clusterUnits.size();
415  print_info("ClusterPlacer: There are totally " + std::to_string(clusterUnits.size() - clusterNumRecord) +
416  " Single-PU clusters are identified.");
417 
418  // handle the other placement units
420 
422  new GraphPartitioner<std::vector<PlacementInfo::ClusterUnit *>, std::vector<PlacementInfo::ClusterNet *>>(
423  clusterUnits, clusterNets, minClusterCellNum, jobs, verbose);
425  clockBasedGraphPartitioner->solve(eachClusterDSPNum, eachClusterBRAMNum);
428 
429  placementUnit2ClusterId.clear();
431  int clusterId = 0;
432 
433  std::vector<std::set<int>> newClusters(0);
434  unsigned int PUCnt = 0;
435  for (auto cluster : clusters)
436  {
437  std::set<int> curCluster;
438  int tmpWeight = 0;
439  for (int clusterUnitId : cluster)
440  {
441  for (auto tmpPU : clusterUnits[clusterUnitId]->getUnits())
442  {
443  assert(placementUnit2ClusterId[tmpPU->getId()] < 0);
444  placementUnit2ClusterId[tmpPU->getId()] = clusterId;
445  curCluster.insert(tmpPU->getId());
446  tmpWeight += tmpPU->getWeight();
447  PUCnt++;
448  }
449  }
450  newClusters.push_back(curCluster);
451  clusterId++;
452  }
453  assert(PUCnt == placementUnit2ClusterId.size());
454  clusters = newClusters;
455 }
456 
458 {
459  std::vector<std::vector<DesignInfo::DesignCell *>> &predefinedCellClusters =
461 
462  std::set<PlacementInfo::PlacementUnit *> reallocatedPUs;
463 
464  int reallocateCnt = 0;
465  for (auto &clusterCellSet : predefinedCellClusters)
466  {
467  std::vector<int> cluster2overlappedCellNum(clusters.size(), 0);
468  int maxOverlappedClusterId = 0;
469  int maxOverlapCnt = 0;
470 
471  int DSPCnt = 0;
472  int BRAMCnt = 0;
473  for (auto tmpCell : clusterCellSet)
474  {
475  DSPCnt += tmpCell->isDSP();
476  BRAMCnt += tmpCell->isBRAM();
477  }
478 
479  if (DSPCnt >= 8 || BRAMCnt >= 8)
480  continue;
481 
482  // find the most overlapped partitioned cluster for the predefined cluster
483  for (auto tmpCell : clusterCellSet)
484  {
485  auto tmpPU = placementInfo->getPlacementUnitByCell(tmpCell);
486  auto tmpPUId = tmpPU->getId();
487 
488  for (unsigned int i = 0; i < clusters.size(); i++)
489  {
490  if (clusters[i].find(tmpPUId) != clusters[i].end())
491  {
492  cluster2overlappedCellNum[i]++;
493  if (cluster2overlappedCellNum[i] > maxOverlapCnt)
494  {
495  cluster2overlappedCellNum[i] = cluster2overlappedCellNum[i];
496  maxOverlappedClusterId = i;
497  }
498  break;
499  }
500  }
501  }
502 
503  // move cells in predefined Cluster togather
504  for (auto tmpCell : clusterCellSet)
505  {
506  auto tmpPU = placementInfo->getPlacementUnitByCell(tmpCell);
507  auto tmpPUId = tmpPU->getId();
508 
509  // don't reallocate PU twice
510  if (reallocatedPUs.find(tmpPU) != reallocatedPUs.end())
511  continue;
512  reallocatedPUs.insert(tmpPU);
513 
514  if (placementUnit2ClusterId[tmpPUId] != maxOverlappedClusterId)
515  {
516  clusters[placementUnit2ClusterId[tmpPUId]].erase(tmpPUId);
517  clusters[maxOverlappedClusterId].insert(tmpPUId);
518  placementUnit2ClusterId[tmpPUId] = maxOverlappedClusterId;
519  reallocateCnt++;
520  }
521  }
522  }
523 
524  print_info("reallocate " + std::to_string(reallocateCnt) + " PU(s)");
525 }
526 
528 {
529  std::string infoStr = "Recursive partitioning generates " + std::to_string(clusters.size()) +
530  " clusters and the numbers of the placement units for them are: ";
531 
532  auto &PUs = placementInfo->getPlacementUnits();
533 
534  int totalCellsinCluster = 0;
535  for (auto cluster : clusters)
536  {
537  int DSPNum = 0;
538  int BRAMNum = 0;
539  int cellsinCluster = 0;
540  for (int PUId : cluster)
541  {
542  if (auto curMacro = dynamic_cast<PlacementInfo::PlacementMacro *>(PUs[PUId]))
543  {
544  for (auto tmpCell : curMacro->getCells())
545  {
546  DSPNum += tmpCell->isDSP();
547  BRAMNum += tmpCell->isBRAM();
548  }
549  }
550  else if (auto curUnpackedCell = dynamic_cast<PlacementInfo::PlacementUnpackedCell *>(PUs[PUId]))
551  {
552  DSPNum += curUnpackedCell->getCell()->isDSP();
553  BRAMNum += curUnpackedCell->getCell()->isBRAM();
554  }
555 
556  cellsinCluster += PUs[PUId]->getWeight();
557  totalCellsinCluster += PUs[PUId]->getWeight();
558  }
559  infoStr += std::to_string(cluster.size()) + "-" + std::to_string(cellsinCluster) +
560  "(DSP:" + std::to_string(DSPNum) + ",BRAM:" + std::to_string(BRAMNum) + "), ";
561  }
562 
563  print_info(infoStr);
564 
565  if ((totalCellsinCluster / clusters.size()) > 0.75 * avgClusterSizeRequirement)
566  {
567  print_warning("Average cluster size is too large = " + std::to_string((totalCellsinCluster / clusters.size())));
568  return true;
569  }
570  return false;
571 }
572 
574 {
575  if (auto unpackedCell = dynamic_cast<PlacementInfo::PlacementUnpackedCell *>(curPU))
576  {
577  return unpackedCell->getCell()->isIO();
578  }
579  else if (auto curMacro = dynamic_cast<PlacementInfo::PlacementMacro *>(curPU))
580  {
581  for (auto tmpCell : curMacro->getCells())
582  {
583  if (tmpCell->isIO())
584  {
585  return true;
586  }
587  }
588  return false;
589  }
590  return false;
591 }
592 
594 {
595  clusterAdjMat = std::vector<std::vector<float>>(clusters.size(), std::vector<float>(clusters.size(), 0));
596  clusterCLBCellWeights = std::vector<float>(clusters.size(), 0);
597  clusterDSPCellWeights = std::vector<float>(clusters.size(), 0);
598  clusterBRAMCellWeights = std::vector<float>(clusters.size(), 0);
599  cluster2FixedUnitMat = std::vector<std::vector<float>>(
600  clusters.size(), std::vector<float>(placementInfo->getFixedPlacementUnits().size(), 0));
601 
602  fixedX.clear();
603  fixedY.clear();
604 
605  float clockRegionW = (placementInfo->getGlobalMaxX() - placementInfo->getGlobalMinX()) / clockRegionXNum;
606 
607  std::map<PlacementInfo::PlacementUnit *, int> fixedPlacementUnit2LocId;
608  fixedPlacementUnit2LocId.clear();
609 
610  float pathThr = placementInfo->getMediumPathThresholdLevel();
611 
612  int ignoredConnectCnt = 0;
613  bool cutShortPathNets = !isDensePlacement();
614  for (auto net : placementInfo->getPlacementNets())
615  {
616  for (auto driveU : net->getDriverUnits())
617  {
618  if (driveU->isFixed())
619  {
620  if (fixedPlacementUnit2LocId.find(driveU) == fixedPlacementUnit2LocId.end())
621  {
622  int amo = fixedPlacementUnit2LocId.size();
623  fixedPlacementUnit2LocId[driveU] = amo;
624  if (containIOCells(driveU))
625  {
626  fixedX.push_back(driveU->X() + clockRegionW / 2.0);
627  fixedY.push_back(driveU->Y());
628  }
629  else
630  {
631  fixedX.push_back(driveU->X());
632  fixedY.push_back(driveU->Y());
633  }
634  }
635  }
636 
637  for (auto UBeDriven : net->getUnitsBeDriven())
638  {
639  int A = driveU->getId();
640  int B = UBeDriven->getId();
641  int maxLength = getPlacementUnitMaxPathLen(UBeDriven);
642 
643  if (maxLength > 0 && maxLength < 3 && net->getUnitsBeDriven().size() < 8 && cutShortPathNets)
644  continue;
645 
646  int clusterA = placementUnit2ClusterId[A];
647  int clusterB = placementUnit2ClusterId[B];
648  assert(clusterA >= 0 && clusterB >= 0);
649  assert((unsigned int)clusterA < cluster2FixedUnitMat.size() &&
650  (unsigned int)clusterB < cluster2FixedUnitMat.size());
651  if (UBeDriven->isFixed())
652  {
653  if (fixedPlacementUnit2LocId.find(UBeDriven) == fixedPlacementUnit2LocId.end())
654  {
655  int amo = fixedPlacementUnit2LocId.size();
656  fixedPlacementUnit2LocId[UBeDriven] = amo;
657  if (containIOCells(UBeDriven))
658  {
659  fixedX.push_back(UBeDriven->X() + clockRegionW / 2.0);
660  fixedY.push_back(UBeDriven->Y());
661  }
662  else
663  {
664  fixedX.push_back(UBeDriven->X());
665  fixedY.push_back(UBeDriven->Y());
666  }
667  }
668  }
669 
670  if (net->getPinOffsetsInUnit().size() > 1)
671  {
672  if (UBeDriven->isFixed() && !driveU->isFixed())
673  {
674  assert(fixedPlacementUnit2LocId.find(UBeDriven) != fixedPlacementUnit2LocId.end());
675  assert((unsigned int)fixedPlacementUnit2LocId[UBeDriven] <
676  cluster2FixedUnitMat[clusterA].size());
677  cluster2FixedUnitMat[clusterA][fixedPlacementUnit2LocId[UBeDriven]] +=
678  net->getDesignNet()->getOverallEnhanceRatio() / (net->getPinOffsetsInUnit().size() - 1);
679  }
680  else if (!UBeDriven->isFixed() && driveU->isFixed())
681  {
682  assert(fixedPlacementUnit2LocId.find(driveU) != fixedPlacementUnit2LocId.end());
683  assert((unsigned int)fixedPlacementUnit2LocId[driveU] < cluster2FixedUnitMat[clusterB].size());
684  cluster2FixedUnitMat[clusterB][fixedPlacementUnit2LocId[driveU]] +=
685  net->getDesignNet()->getOverallEnhanceRatio() / (net->getPinOffsetsInUnit().size() - 1);
686  }
687  else if (!UBeDriven->isFixed() && !driveU->isFixed())
688  {
689  clusterAdjMat[clusterA][clusterB] +=
690  net->getDesignNet()->getOverallEnhanceRatio() / (net->getPinOffsetsInUnit().size() - 1);
691  clusterAdjMat[clusterB][clusterA] +=
692  net->getDesignNet()->getOverallEnhanceRatio() / (net->getPinOffsetsInUnit().size() - 1);
693  }
694  }
695  }
696  }
697  }
698 
699  for (auto curPU : placementInfo->getPlacementUnits())
700  {
701  int PUId = curPU->getId();
702  int clusterId = placementUnit2ClusterId[PUId];
703  clusterCLBCellWeights[clusterId] += curPU->getWeight();
704  clusterDSPCellWeights[clusterId] += curPU->getDSPNum();
705  clusterBRAMCellWeights[clusterId] += curPU->getBRAMNum();
706  }
707 }
708 
710 {
711  print_status("SA-based Cluster Placement Start.");
712  assert(JSONCfg.find("clockRegionXNum") != JSONCfg.end());
713  assert(JSONCfg.find("clockRegionYNum") != JSONCfg.end());
714 
715  int gridH = std::stoi(JSONCfg["clockRegionYNum"]);
716  int gridW = std::stoi(JSONCfg["clockRegionXNum"]);
717  int SAIterNum = 100000;
718  int restartNum = 10;
719 
720  if (JSONCfg.find("Simulated Annealing IterNum") != JSONCfg.end())
721  SAIterNum = std::stoi(JSONCfg["Simulated Annealing IterNum"]);
722  if (JSONCfg.find("Simulated Annealing restartNum") != JSONCfg.end())
723  restartNum = std::stoi(JSONCfg["Simulated Annealing restartNum"]);
724  float deviceW = (placementInfo->getGlobalMaxX() - placementInfo->getGlobalMinX());
725  float deviceH = (placementInfo->getGlobalMaxY() - placementInfo->getGlobalMinY());
726 
727  // SA-based cluster placement
729  gridH, gridW, deviceH, deviceW, connectionToFixedFactor, y2xRatio * 0.8, SAIterNum, jobs,
730  restartNum, verbose);
731  saPlacer->solve();
733 
735 
737  print_status("SA-based Cluster Placement Done.");
738 }
739 
740 void ClusterPlacer::placeUnitBaseOnClusterPlacement(const std::vector<std::pair<int, int>> &cluster2XY)
741 {
742  int gridH = std::stoi(JSONCfg["clockRegionYNum"]);
743  int gridW = std::stoi(JSONCfg["clockRegionXNum"]);
744 
745  float deviceW = (placementInfo->getGlobalMaxX() - placementInfo->getGlobalMinX());
746  float deviceH = (placementInfo->getGlobalMaxY() - placementInfo->getGlobalMinY());
747 
748  float regionW = deviceW / gridW;
749  float regionH = deviceH / gridH;
750 
751  cluster2FP_XY.clear();
752  for (auto intXY : cluster2XY)
753  {
754  float fX = intXY.first * regionW + regionW / 2;
755  float fY = intXY.second * regionH + regionH / 2;
756  cluster2FP_XY.push_back(std::pair<float, float>(fX, fY));
757  }
758 
759  assert(!randomInitialPlacement);
760 
761  for (auto curPU : placementInfo->getPlacementUnits())
762  {
763  if (!curPU->isFixed())
764  {
765  // float fX = random_float(cluster2FP_XY[placementUnit2ClusterId[curPU->getId()]].first - regionW / 2,
766  // cluster2FP_XY[placementUnit2ClusterId[curPU->getId()]].first + regionW / 2);
767  // float fY = random_float(cluster2FP_XY[placementUnit2ClusterId[curPU->getId()]].second - regionH / 2,
768  // cluster2FP_XY[placementUnit2ClusterId[curPU->getId()]].second + regionH / 2);
769  float fX = cluster2FP_XY[placementUnit2ClusterId[curPU->getId()]].first;
770  float fY = cluster2FP_XY[placementUnit2ClusterId[curPU->getId()]].second;
771  placementInfo->legalizeXYInArea(curPU, fX, fY);
772  curPU->setAnchorLocation(fX, fY);
773  }
774  }
775 }
776 
778 {
779  std::string dumpClustersFile = JSONCfg["Dump Cluster file"];
780  if (dumpClustersFile != "")
781  {
782  print_status("dumping cluster information to " + dumpClustersFile);
783  std::ofstream outfile0((dumpClustersFile + ".tcl").c_str());
784  assert(outfile0.is_open() && outfile0.good() &&
785  "The path for cluster result dumping does not exist and please check your path settings");
786  for (unsigned int cluster_id = 0; cluster_id < clusters.size(); cluster_id++)
787  {
788  outfile0 << "# placed at region coordinate: X " << cluster2XY[cluster_id].first << " Y "
789  << cluster2XY[cluster_id].second << "\n";
790  outfile0 << "highlight -color_index " << (cluster_id) % 20 + 1 << " [get_cells {";
791  for (int id : clusters[cluster_id])
792  {
793  if (auto tmpMacro =
795  {
796  for (auto cell : tmpMacro->getCells())
797  {
798  outfile0 << cell->getName() << " ";
799  }
800  }
801  else if (auto tmpUnpacked = dynamic_cast<PlacementInfo::PlacementUnpackedCell *>(
803  {
804  outfile0 << tmpUnpacked->getName() << " ";
805  }
806  else
807  {
808  assert(false);
809  }
810  }
811  outfile0 << "}]\n";
812  }
813  outfile0.close();
814  outfile0 = std::ofstream(dumpClustersFile.c_str());
815  for (unsigned int cluster_id = 0; cluster_id < clusters.size(); cluster_id++)
816  {
817  for (int id : clusters[cluster_id])
818  {
819  if (auto tmpMacro =
821  {
822  for (auto cell : tmpMacro->getCells())
823  {
824  outfile0 << cell->getName() << " ";
825  }
826  }
827  else if (auto tmpUnpacked = dynamic_cast<PlacementInfo::PlacementUnpackedCell *>(
829  {
830  outfile0 << tmpUnpacked->getName() << " ";
831  }
832  else
833  {
834  assert(false);
835  }
836  }
837  outfile0 << "\n";
838  }
839  outfile0.close();
840  }
841 }
842 
844 {
845  std::vector<std::pair<int, int>> lines;
846  lines.clear();
847  for (unsigned int clusterA = 1; clusterA < clusterAdjMat.size(); clusterA++)
848  for (unsigned int clusterB = 0; clusterB < clusterA; clusterB++)
849  {
850  if (clusterAdjMat[clusterA][clusterB] > 0)
851  {
852  lines.push_back(std::pair<int, int>(clusterA, clusterB));
853  }
854  }
855  // paintClusterNodeLine(cluster2FP_XY, lines, cluster2FixedUnitMat, fixedX, fixedY);
856 }
PlacementInfo::getNumCells
int getNumCells()
Definition: PlacementInfo.h:2842
ClusterPlacer::placementUnitId2ClusterUnitId
std::vector< int > placementUnitId2ClusterUnitId
Definition: ClusterPlacer.h:158
ClusterPlacer::connectionToFixedFactor
float connectionToFixedFactor
the enhancement ratio of the net between elements and I/Os
Definition: ClusterPlacer.h:110
PlacementInfo::ClusterUnit::addPlacementUnit
void addPlacementUnit(PlacementInfo::PlacementUnit *curPU)
Definition: PlacementInfo.h:2512
PlacementInfo::getPlacementUnits
std::vector< PlacementUnit * > & getPlacementUnits()
Definition: PlacementInfo.h:2810
PlacementTimingInfo::getSimplePlacementTimingInfo_PathLenSorted
std::vector< TimingGraph< DesignInfo::DesignCell >::TimingNode * > & getSimplePlacementTimingInfo_PathLenSorted()
Definition: PlacementTimingInfo.h:840
ClusterPlacer::creaeClusterNets
void creaeClusterNets()
construct the netlist of the generated clusters based on the PlacementNet in PlacementInfo
Definition: ClusterPlacer.h:225
ClusterPlacer::createUserDefinedClusterBasedClusterUnits
void createUserDefinedClusterBasedClusterUnits()
initially cluster cells based on user-defined clusters
Definition: ClusterPlacer.cc:269
PlacementInfo::PlacementMacro
a fixed group of multiple standard cells with constraints of their relative locations
Definition: PlacementInfo.h:1525
ClusterPlacer::resetClusterInfo
void resetClusterInfo()
clean all information of the clusters (including PlacementUnit-Cluster mapping and the cluster-level ...
Definition: ClusterPlacer.h:214
DesignInfo::getCellsUnderClock
std::set< DesignCell * > & getCellsUnderClock(DesignNet *clock)
Get the cells driven by a given clock net.
Definition: DesignInfo.h:1734
containIOCells
bool containIOCells(PlacementInfo::PlacementUnit *curPU)
Definition: ClusterPlacer.cc:573
ClusterPlacer::userDefinedClusterBasedGraphPartitioner
GraphPartitioner< std::vector< PlacementInfo::ClusterUnit * >, std::vector< PlacementInfo::ClusterNet * > > * userDefinedClusterBasedGraphPartitioner
userDefinedClusterBasedGraphPartitioner will conduct partitioning at the Cluster level considering co...
Definition: ClusterPlacer.h:193
ClusterPlacer::clusterBRAMCellWeights
std::vector< float > clusterBRAMCellWeights
Definition: ClusterPlacer.h:150
ClusterPlacer::basicGraphPartitioner
GraphPartitioner< std::vector< PlacementInfo::PlacementUnit * >, std::vector< PlacementInfo::PlacementNet * > > * basicGraphPartitioner
basicGraphPartitioner will conduct partitioning at the PlacementUnit level considering connectivity a...
Definition: ClusterPlacer.h:185
ClusterPlacer::placementInfo
PlacementInfo * placementInfo
the PlacementInfo for this placer to handle
Definition: ClusterPlacer.h:95
ClusterPlacer::clusterDSPCellWeights
std::vector< float > clusterDSPCellWeights
Definition: ClusterPlacer.h:149
PlacementInfo::getGlobalMinY
float getGlobalMinY()
Get the Global Min Y (bottom boundary of the device)
Definition: PlacementInfo.h:2882
PlacementInfo::getLongPathThresholdLevel
int getLongPathThresholdLevel()
Definition: PlacementInfo.h:4358
ClusterPlacer::dumpClusters
void dumpClusters()
Definition: ClusterPlacer.cc:777
GraphPartitioner::getClustersPUIdSets
const std::vector< std::set< int > > & getClustersPUIdSets()
Get the clusters after partitioning (each is a set containing ids for nodes inside the clusters)
Definition: GraphPartitioner.h:98
ClusterPlacer::basicPartitioning
void basicPartitioning(int minClusterCellNum, int eachClusterDSPNum, int eachClusterBRAMNum)
pure connectivity-based partitioning based on PaToH
Definition: ClusterPlacer.cc:338
ClusterPlacer::clusterNets
std::vector< PlacementInfo::ClusterNet * > clusterNets
Definition: ClusterPlacer.h:160
ClusterPlacer::userDefinedClusterBasedPartitioning
void userDefinedClusterBasedPartitioning(int minClusterCellNum, int eachClusterDSPNum, int eachClusterBRAMNum)
initially cluster cells based on user-defined clusters and conduct connectivity-based partitioning ba...
Definition: ClusterPlacer.cc:361
ClusterPlacer::y2xRatio
float y2xRatio
the Y/X coordinate calibration factor
Definition: ClusterPlacer.h:116
ClusterPlacer::cluster2XY
std::vector< std::pair< int, int > > cluster2XY
mapping cluster id to X/Y location in the cluster bin
Definition: ClusterPlacer.h:137
ClusterPlacer::createLongPathClusterUnits
void createLongPathClusterUnits()
initially cluster cells based on user-defined clusters
Definition: ClusterPlacer.cc:144
PlacementInfo::updateB2BAndGetTotalHPWL
double updateB2BAndGetTotalHPWL()
update the B2B net model for the placement and get the total HPWL of all the nets in the design
Definition: PlacementInfo.h:3913
ClusterPlacer::jobs
int jobs
the parallel (multi-threading) worker number
Definition: ClusterPlacer.h:168
DesignInfo::getClocksInDesign
std::vector< DesignNet * > & getClocksInDesign()
Get the all the clock nets in the design.
Definition: DesignInfo.h:1723
ClusterPlacer::clusterCLBCellWeights
std::vector< float > clusterCLBCellWeights
Definition: ClusterPlacer.h:148
PlacementInfo::getGlobalMaxX
float getGlobalMaxX()
Get the Global Max X (right boundary of the device)
Definition: PlacementInfo.h:2852
ClusterPlacer::clockRegionXNum
int clockRegionXNum
Definition: ClusterPlacer.h:162
ClusterPlacer::refineClustersWithPredefinedClusters
void refineClustersWithPredefinedClusters()
refine the elements in obtained clusters to ensure the cells in user-defined clusters in the same clu...
Definition: ClusterPlacer.cc:457
ClusterPlacer::createSinglePUClusterUnits
void createSinglePUClusterUnits()
wrap single PlacementUnits into ClusterUnit for later uniform processing
Definition: ClusterPlacer.cc:324
ClusterPlacer::isClustersToLarges
bool isClustersToLarges()
check whether the average size of clusters is greater than the given threshold
Definition: ClusterPlacer.cc:527
ClusterPlacer::getPlacementUnitMaxPathLen
int getPlacementUnitMaxPathLen(PlacementInfo::PlacementUnit *curPU)
Definition: ClusterPlacer.h:340
PlacementInfo::getFixedPlacementUnits
std::vector< PlacementUnit * > & getFixedPlacementUnits()
Definition: PlacementInfo.h:2818
DSE.end
end
Definition: DSE.py:18
ClusterPlacer::clockBasedPartitioning
void clockBasedPartitioning(int minClusterCellNum, int eachClusterDSPNum, int eachClusterBRAMNum)
initially cluster cells based on clock domains and conduct connectivity-based partitioning based on P...
Definition: ClusterPlacer.cc:399
ClusterPlacer::avgClusterSizeRequirement
int avgClusterSizeRequirement
the requirement of the average size of clusters (the number of cells)
Definition: ClusterPlacer.h:125
PlacementInfo::updateElementBinGrid
void updateElementBinGrid()
map design cells to the bins in the bin grid.
Definition: PlacementInfo.cc:906
DesignInfo::getPredefinedClusters
std::vector< std::vector< DesignCell * > > & getPredefinedClusters()
Get the predefined clusters which are defined in design configuration files.
Definition: DesignInfo.h:1659
GraphPartitioner
GraphPartitioner will recursively bi-partition the netlist (which could be netlist of clusters) based...
Definition: GraphPartitioner.h:52
delayVisualization.A
A
Definition: delayVisualization.py:85
PlacementInfo::ClusterUnit::getId
int getId()
Definition: PlacementInfo.h:2525
print_status
void print_status(std::string tmp_string)
Definition: strPrint.cc:44
ClusterPlacer::randomInitialPlacement
bool randomInitialPlacement
Definition: ClusterPlacer.h:119
ClusterPlacer::clockRegionYNum
int clockRegionYNum
Definition: ClusterPlacer.h:162
ClusterPlacer::placeClusters
void placeClusters()
conduct the ClusterUnit level SA placement and then map PlacementUnit to cluster location
Definition: ClusterPlacer.cc:709
ClusterPlacer::setClusterNetsAdjMat
void setClusterNetsAdjMat()
construct the cluster nets adjacent matrix for simulated-annealing cluster placement
Definition: ClusterPlacer.cc:593
PlacementInfo::getGlobalMinX
float getGlobalMinX()
Get the Global Min X (left boundary of the device)
Definition: PlacementInfo.h:2872
SAPlacer::getCluster2XY
std::vector< std::pair< int, int > > & getCluster2XY()
Definition: SAPlacer.h:60
print_warning
void print_warning(std::string tmp_string)
Definition: strPrint.cc:57
PlacementInfo::getPlacementUnitByCellId
PlacementUnit * getPlacementUnitByCellId(int cellId)
Definition: PlacementInfo.h:3127
ClusterPlacer::placementUnit2ClusterId
std::vector< int > placementUnit2ClusterId
Definition: ClusterPlacer.h:156
ClusterPlacer::hypergraphPartitioning
void hypergraphPartitioning()
call specific partitioners to partition the design netlist into clusters for initial placement
Definition: ClusterPlacer.cc:113
PlacementInfo::setClusterNum
void setClusterNum(int _clusterNum)
Definition: PlacementInfo.h:4378
ClusterPlacer::random_float
float random_float(float min, float max)
Definition: ClusterPlacer.h:366
SAPlacer::solve
void solve()
Definition: SAPlacer.cc:678
PlacementInfo::PlacementUnit
a movement unit in placement with information of location and resource demand
Definition: PlacementInfo.h:1010
SAPlacer
Definition: SAPlacer.h:41
ClusterPlacer.h
This header file contains the definitions of ClusterPlacer class and its internal modules and APIs wh...
PlacementInfo::PlacementUnit::getId
unsigned int getId()
Definition: PlacementInfo.h:1206
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
PlacementInfo::getTimingInfo
PlacementTimingInfo * getTimingInfo()
Definition: PlacementInfo.h:3313
ClusterPlacer::clusterUnits
std::vector< PlacementInfo::ClusterUnit * > clusterUnits
Definition: ClusterPlacer.h:159
ClusterPlacer::JSONCfg
std::map< std::string, std::string > & JSONCfg
Definition: ClusterPlacer.h:104
PlacementInfo::ClusterUnit
a group of PlacementUnits
Definition: PlacementInfo.h:2489
ClusterPlacer::maxMinCutRate
double maxMinCutRate
the maximum cut rate for netlist min-cut partitioning
Definition: ClusterPlacer.h:131
ClusterPlacer::cluster2FP_XY
std::vector< std::pair< float, float > > cluster2FP_XY
mapping cluster id to floating-point X/Y location on device
Definition: ClusterPlacer.h:143
PlacementInfo::checkClockUtilization
bool checkClockUtilization(bool dump)
check the utlization of the clock regions on the device
Definition: PlacementInfo.cc:2087
ClusterPlacer::clusters
std::vector< std::set< int > > clusters
the resultant clusters of PlacementUnit (id)
Definition: ClusterPlacer.h:103
PlacementInfo::getPlacementNets
std::vector< PlacementNet * > & getPlacementNets()
Definition: PlacementInfo.h:2822
ClusterPlacer::saPlacer
SAPlacer * saPlacer
simulated-annealing placer for the cluster placement.
Definition: ClusterPlacer.h:177
ClusterPlacer::ClusterPlacement
void ClusterPlacement()
conduct cluster placement, cluster nodes in the given netlist and place the clusters on the device as...
Definition: ClusterPlacer.cc:60
PlacementInfo::PlacementUnpackedCell
the smallest, indivisible, representable component. It will include only one standard cell
Definition: PlacementInfo.h:1447
ClusterPlacer::clusterAdjMat
std::vector< std::vector< float > > clusterAdjMat
Definition: ClusterPlacer.h:147
ClusterPlacer::clockBasedGraphPartitioner
GraphPartitioner< std::vector< PlacementInfo::ClusterUnit * >, std::vector< PlacementInfo::ClusterNet * > > * clockBasedGraphPartitioner
clockBasedGraphPartitioner will conduct partitioning at the Cluster level considering connectivity an...
Definition: ClusterPlacer.h:201
GraphPartitioner::solve
void solve(int eachClusterDSPNum, int eachClusterBRAMNum)
a caller which will start the partitioning procedure
Definition: GraphPartitioner.cc:32
print_info
void print_info(std::string tmp_string)
Definition: strPrint.cc:39
ClusterPlacer::cluster2FixedUnitMat
std::vector< std::vector< float > > cluster2FixedUnitMat
Definition: ClusterPlacer.h:152
checkHalfColumn.i
int i
Definition: checkHalfColumn.py:5
PlacementInfo::getDesignInfo
DesignInfo * getDesignInfo()
Definition: PlacementInfo.h:3303
PlacementInfo::getPlacementUnitByCell
PlacementUnit * getPlacementUnitByCell(DesignInfo::DesignCell *curCell)
Definition: PlacementInfo.h:3120
ClusterPlacer::ClusterPlacer
ClusterPlacer(PlacementInfo *placementInfo, std::map< std::string, std::string > &JSONCfg, float connectionToFixedFactor=5.0)
Construct a new Cluster Placer object.
Definition: ClusterPlacer.cc:33
PlacementInfo::getMediumPathThresholdLevel
int getMediumPathThresholdLevel()
Definition: PlacementInfo.h:4363
ClusterPlacer::drawClusters
void drawClusters()
Definition: ClusterPlacer.cc:843
ClusterPlacer::isDensePlacement
bool isDensePlacement()
Definition: ClusterPlacer.h:203
ClusterPlacer::fixedX
std::vector< float > fixedX
Definition: ClusterPlacer.h:153
delayVisualization.lines
lines
Definition: delayVisualization.py:26
ClusterPlacer::createClockBasedClusterUnits
void createClockBasedClusterUnits()
initially cluster cells based on clock domains
Definition: ClusterPlacer.cc:235
GraphPartitioner::setMaxCutRate
void setMaxCutRate(double _maxCutRate)
Set the max mincut rate.
Definition: GraphPartitioner.h:148
PlacementInfo::getGlobalMaxY
float getGlobalMaxY()
Get the Global Max Y (top boundary of the device)
Definition: PlacementInfo.h:2862
ClusterPlacer::verbose
bool verbose
Definition: ClusterPlacer.h:117
PlacementInfo
Information related to FPGA placement (wirelength optimization, cell spreading, legalization,...
Definition: PlacementInfo.h:59
PlacementInfo::ClusterUnit::getUnits
std::vector< PlacementInfo::PlacementUnit * > & getUnits()
Definition: PlacementInfo.h:2520
ClusterPlacer::placeUnitBaseOnClusterPlacement
void placeUnitBaseOnClusterPlacement(const std::vector< std::pair< int, int >> &cluster2XY)
map PlacementUnit to cluster location
Definition: ClusterPlacer.cc:740
ClusterPlacer::fixedY
std::vector< float > fixedY
Definition: ClusterPlacer.h:154
ClusterPlacer::clusterPlacementUnits
void clusterPlacementUnits()
cluster the netlist and create ClusterUnit level netlist for SA placement
Definition: ClusterPlacer.cc:100