33 : placementInfo(placementInfo), JSONCfg(JSONCfg), verbose(verbose)
64 print_warning(
"Direct Macro Legalization is enbaled. It might undermine the HPWL.");
87 auto designNet = pNet->getDesignNet();
88 if (!designNet->checkIsPowerNet() && !designNet->checkIsGlobalClock())
90 netPinEnhanceRate[designNet] = std::vector<float>(designNet->getPins().size(), -1);
101 bool forwardSolutionToNextIteration,
bool enableMacroPseudoNet2Site,
102 bool considerNetNum,
bool enableUserDefinedClusterOpt,
118 updateB2BNetWeight(pesudoNetWeight, enableMacroPseudoNet2Site, considerNetNum, enableUserDefinedClusterOpt,
160 if (tmpPU->isFixed())
172 if (tmpPU->isFixed())
183 bool displacementLimitEnable = displacementLimit > 0;
186 if (displacementLimitEnable)
190 #pragma omp parallel for
191 for (
unsigned int tmpPUId = 0; tmpPUId < numPUs; tmpPUId++)
194 if (tmpPU->isFixed())
198 float disX = std::fabs(fX - tmpPU->X());
199 float disY = std::fabs(fY - tmpPU->Y());
201 float disRatio = displacementLimit / dis;
204 fX = tmpPU->X() + (fX - tmpPU->X()) * disRatio;
205 fY = tmpPU->Y() + (fY - tmpPU->Y()) * disRatio;
208 tmpPU->setAnchorLocation(fX, fY);
213 #pragma omp parallel for
214 for (
unsigned int tmpPUId = 0; tmpPUId < numPUs; tmpPUId++)
217 if (tmpPU->isFixed())
221 float disX = std::fabs(fX - tmpPU->X());
222 float disY = std::fabs(fY - tmpPU->Y());
224 float disRatio = displacementLimit / dis;
227 fX = tmpPU->X() + (fX - tmpPU->X()) * disRatio;
228 fY = tmpPU->Y() + (fY - tmpPU->Y()) * disRatio;
231 tmpPU->setAnchorLocation(fX, fY);
239 #pragma omp parallel for
240 for (
unsigned int tmpPUId = 0; tmpPUId < numPUs; tmpPUId++)
243 if (tmpPU->isFixed())
248 tmpPU->setAnchorLocation(fX, fY);
253 #pragma omp parallel for
254 for (
unsigned int tmpPUId = 0; tmpPUId < numPUs; tmpPUId++)
257 if (tmpPU->isFixed())
262 tmpPU->setAnchorLocation(fX, fY);
269 bool enableUserDefinedClusterOpt,
275 bool updateTrue =
true, updateFalse =
false;
293 print_warning(
"addPseudoNetForMacros is disabled according to placer configuration.");
305 if (enableUserDefinedClusterOpt)
318 if (
JSONCfg[
"DrawNetAfterEachIteration"] ==
"true")
321 std::cout <<
"please input the ID of net you want to show (-1 for stopping):\n";
327 std::cout <<
"please input the ID of net you want to show (-1 for stopping):\n";
335 std::vector<Eigen::Triplet<float>> &objectiveMatrixTripletList,
336 std::vector<float> &objectiveMatrixDiag,
337 Eigen::VectorXd &objectiveVector,
float generalNetWeight,
338 float y2xRatio,
bool updateX,
bool updateY)
340 objectiveMatrixTripletList.clear();
341 objectiveMatrixDiag.clear();
346 if (net->getDesignNet()->checkIsPowerNet())
349 if (net->updateNetBounds(updateX, updateY))
351 net->updateBound2BoundNetWeight(objectiveMatrixTripletList, objectiveMatrixDiag, objectiveVector,
369 print_info(
"WLOptimizer macroLegalizePseudoNet=" + std::to_string(macroPseudoNetFactor * pesudoNetWeight));
372 for (
auto pairPUX : PUX)
374 if (!pairPUX.first->checkHasBRAM() && !pairPUX.first->checkHasDSP() && !pairPUX.first->checkHasCARRY())
378 macroPseudoNetFactor * pesudoNetWeight * pairPUX.first->getNetsSetPtr()->size() / 3,
y2xRatio,
true,
380 else if (pairPUX.first->checkHasCARRY())
384 macroPseudoNetFactor * pesudoNetWeight * pairPUX.first->getNetsSetPtr()->size() / 5,
y2xRatio,
true,
390 macroPseudoNetFactor * pesudoNetWeight * pairPUX.first->getNetsSetPtr()->size(),
y2xRatio,
true,
393 for (
auto pairPUY : PUY)
395 if (!pairPUY.first->checkHasBRAM() && !pairPUY.first->checkHasDSP() && !pairPUY.first->checkHasCARRY())
399 macroPseudoNetFactor * pesudoNetWeight * pairPUY.first->getNetsSetPtr()->size() / 3,
y2xRatio,
401 else if (pairPUY.first->checkHasCARRY())
405 macroPseudoNetFactor * pesudoNetWeight * pairPUY.first->getNetsSetPtr()->size() / 5,
y2xRatio,
411 macroPseudoNetFactor * pesudoNetWeight * pairPUY.first->getNetsSetPtr()->size(),
y2xRatio,
false,
417 for (
auto pairPUX : PUX)
422 macroPseudoNetFactor * pesudoNetWeight,
y2xRatio,
true,
false);
424 for (
auto pairPUY : PUY)
429 macroPseudoNetFactor * pesudoNetWeight,
y2xRatio,
false,
true);
448 if (slackPowFactor < 0 || timingWeight < 0)
455 assert(cellLoc.size() == timingNodes.size());
458 int enhanceNetCnt = 0;
459 unsigned int highFanoutThr = 10000;
463 highFanoutThr = 1000;
471 #pragma omp parallel for
472 for (
int PNetId = 0; PNetId < netNum; PNetId++)
477 auto designNet = curNet->getDesignNet();
480 assert(curNet->getId() == PNetId);
481 if (designNet->checkIsPowerNet() || designNet->checkIsGlobalClock())
484 if (curNet->getDriverUnits().size() != 1 || curNet->getUnits().size() <= 1 ||
485 curNet->getUnits().size() >= highFanoutThr)
487 auto &PUs = curNet->getUnits();
488 auto &pins = designNet->getPins();
489 int pinNum = pins.size();
491 assert(curNet->getUnits().size() == (
unsigned int)pinNum);
493 int driverPinInNet = -1;
495 for (
int i = 0;
i < pinNum;
i++)
497 if (pins[
i]->isOutputPort())
504 assert(driverPinInNet >= 0);
507 auto srcCell = pins[driverPinInNet]->getCell();
508 unsigned int srcCellId = srcCell->getCellId();
509 auto srcNode = timingNodes[srcCellId];
510 auto srcLoc = cellLoc[srcCellId];
511 int driverPathLen = timingNodes[srcCellId]->getLongestPathLength();
513 if (netActualSlackPinNum[curNet] == 0)
516 float w = 2 * timingWeight / std::pow((
float)(netActualSlackPinNum[curNet]), 0.5);
520 std::cout <<
"driver: " <<
targetCellName <<
" x: " << srcLoc.X <<
" y: " << srcLoc.Y <<
"\n";
525 for (
int pinBeDriven = 0; pinBeDriven < pinNum; pinBeDriven++)
527 if (pinBeDriven == driverPinInNet)
531 auto sinkCell = pins[pinBeDriven]->getCell();
532 unsigned int sinkCellId = sinkCell->getCellId();
533 auto sinkNode = timingNodes[sinkCellId];
534 auto sinkLoc = cellLoc[sinkCellId];
535 int succPathLen = sinkNode->getLongestPathLength();
537 timingOptimizer->
getDelayByModel(sinkNode, srcNode, sinkLoc.X, sinkLoc.Y, srcLoc.X, srcLoc.Y);
538 float slack = sinkNode->getRequiredArrivalTime() - srcNode->getLatestOutputArrival() - netDelay;
539 float clockPeriod = sinkNode->getClockPeriod();
543 std::cout << sinkCell <<
" has no clock setting!!\n";
549 float enhanceRatio = std::pow(1 - slack / clockPeriod, slackPowFactor);
552 enhanceRatio = std::pow(enhanceRatio, slack /
slackThr * 3);
558 if (srcNode->checkIsRegister())
562 float expectedAvgDelay_succ = clockPeriod / succPathLen;
563 if (netDelay > expectedAvgDelay_succ)
565 std::max(enhanceRatio, (
float)std::pow((netDelay / expectedAvgDelay_succ), 0.66));
570 if (driverPathLen > 0)
572 float expectedAvgDelay_driver = clockPeriod / driverPathLen;
573 if (netDelay > expectedAvgDelay_driver)
575 std::max(enhanceRatio, (
float)std::pow((netDelay / expectedAvgDelay_driver), 0.66));
580 if (pinEnhanceRate[pinBeDriven] < 0)
582 pinEnhanceRate[pinBeDriven] = enhanceRatio;
586 if (enhanceRatio > 0)
588 float shrinkRatio = pinEnhanceRate[pinBeDriven] / enhanceRatio;
591 if (shrinkRatio > 300)
593 enhanceRatio = std::pow(enhanceRatio, 0.1) * std::pow(pinEnhanceRate[pinBeDriven], 0.9);
595 else if (shrinkRatio > 200)
597 enhanceRatio = std::pow(enhanceRatio, 0.2) * std::pow(pinEnhanceRate[pinBeDriven], 0.8);
599 else if (shrinkRatio > 100)
602 std::pow(enhanceRatio, 0.33) * std::pow(pinEnhanceRate[pinBeDriven], 0.67);
604 else if (shrinkRatio > 64)
606 enhanceRatio = std::pow(enhanceRatio, 0.4) * std::pow(pinEnhanceRate[pinBeDriven], 0.6);
609 pinEnhanceRate[pinBeDriven] = enhanceRatio;
614 std::cout <<
"sink: " << sinkCell->getName() <<
" x: " << sinkLoc.X <<
" y: " << sinkLoc.Y
615 <<
" netDelay: " << netDelay <<
" slack: " << slack <<
" w: " << w
616 <<
" enhanceRatio: " << enhanceRatio <<
"\n";
620 std::cout <<
"src: " << srcCell->getName() <<
" x: " << srcLoc.X <<
" y: " << srcLoc.Y
621 <<
" netDelay: " << netDelay <<
" slack: " << slack <<
" w: " << w
622 <<
" enhanceRatio: " << enhanceRatio <<
"\n";
626 PUs[pinBeDriven]->getId(), driverPinInNet,
644 for (
int PNetId = 0; PNetId < netNum; PNetId++)
649 curNet->addPseudoNet_enhancePin2Pin(
652 enhanceTuple.PUBId, enhanceTuple.PinAId, enhanceTuple.PinBId);
654 curNet->addPseudoNet_enhancePin2Pin(
657 enhanceTuple.PUBId, enhanceTuple.PinAId, enhanceTuple.PinBId);
662 print_status(
"WirelengthOptimizer: addPseudoNet_SlackBased done");
669 float w = 2 * timingWeight / std::pow(2, 0.5);
670 if (disThreshold < 0)
672 print_status(
"WirelengthOptimizer: Timing Driven Pairing LUTs.");
680 assert(cellLoc.size() == timingNodes.size());
682 int LUTLUTPairCnt = 0;
692 if ((curCell->isLUT() || curCell->isMux() || curCell->isCarry()) && !curCell->isVirtualCell())
694 assert(curCell->getOutputPins().size() > 0);
695 if (curCell->getOutputPins().size() >= 1 && curCell->getOutputPins().size() <= 8)
697 auto srcCell = curCell;
698 unsigned int srcCellId = srcCell->getCellId();
699 auto srcNode = timingNodes[srcCellId];
700 auto srcLoc = cellLoc[srcCellId];
701 int driverPathLen = timingNodes[srcCellId]->getLongestPathLength();
703 if (driverPathLen < longLenThr)
705 for (
auto curOutputPin : curCell->getOutputPins())
710 assert(curOutputPin->getNet());
712 auto curNet = curOutputPin->getNet();
718 float worstSlack = 0.0;
720 int pinBeDriven = -1;
721 int pinOffsetId = -1;
722 if (curNet->getPins().size() > 16)
725 for (
auto curPin : curNet->getPins())
728 auto sinkCell = curPin->getCell();
729 if (sinkCell == curCell)
732 if (sinkCell->isLUT())
734 unsigned int sinkCellId = sinkCell->
getCellId();
735 auto sinkNode = timingNodes[sinkCellId];
736 auto sinkLoc = cellLoc[sinkCellId];
737 int succPathLen = sinkNode->getLongestPathLength();
738 if (succPathLen < longLenThr)
740 float netDelay = timingOptimizer->
getDelayByModel(sinkNode, srcNode, sinkLoc.X, sinkLoc.Y,
743 sinkNode->getRequiredArrivalTime() - srcNode->getLatestOutputArrival() - netDelay;
747 if (curDis < disThreshold && slack < worstSlack)
753 targetSinkCell = sinkCell;
754 pinBeDriven = pinOffsetId;
761 unsigned int sinkCellId = targetSinkCell->
getCellId();
762 auto sinkNode = timingNodes[sinkCellId];
763 auto sinkLoc = cellLoc[sinkCellId];
764 float clockPeriod = sinkNode->getClockPeriod();
772 float enhanceRatio = std::pow(1 - worstSlack / clockPeriod,
slackPowerFactor);
774 int driverPinInNet = -1;
775 auto &pins = curNet->getPins();
776 for (
int i = 0;
i < pins.size();
i++)
778 if (pins[
i]->isOutputPort())
785 float netDelay = timingOptimizer->
getDelayByModel(sinkNode, srcNode, sinkLoc.X, sinkLoc.Y,
787 float slack = sinkNode->getRequiredArrivalTime() - srcNode->getLatestOutputArrival() - netDelay;
791 std::cout <<
"LUTParing sink: " << targetSinkCell->
getName() <<
" x: " << sinkLoc.X
792 <<
" y: " << sinkLoc.Y <<
" netDelay: " << netDelay <<
" slack: " << slack
793 <<
" w: " << w <<
" enhanceRatio: " << enhanceRatio <<
"\n";
797 std::cout <<
"LUTParing src: " << srcCell->getName() <<
" x: " << srcLoc.X
798 <<
" y: " << srcLoc.Y <<
" netDelay: " << netDelay <<
" slack: " << slack
799 <<
" w: " << w <<
" enhanceRatio: " << enhanceRatio <<
"\n";
801 curPNet->addPseudoNet_enhancePin2Pin(
804 predLUTPU->getId(), succLUTPU->
getId(), driverPinInNet, pinBeDriven);
806 curPNet->addPseudoNet_enhancePin2Pin(
809 predLUTPU->getId(), succLUTPU->
getId(), driverPinInNet, pinBeDriven);
827 std::vector<int> netCnt(101, 0);
830 for (
int PUId = 0; PUId < numPUs; PUId++)
834 float curX = curPU->X();
835 int size = curPU->getNetsSetPtr()->size() / 5;
841 int highInterconnectPUCnt = 0;
842 for (
int i = 100;
i >= 2;
i--)
844 highInterconnectPUCnt += netCnt[
i];
845 if (highInterconnectPUCnt > 300)
850 print_info(
"WirelengthOptimizer: PU net pin cnt distribution (netSizeThr=" + std::to_string(netSizeThr) +
"):");
852 for (
int i = 0;
i <= 100;
i++)
853 std::cout << netCnt[
i] <<
" ";
856 if (netSizeThr > 100)
863 #pragma omp parallel sections
867 #pragma omp parallel for // schedule(dynamic, 16)
868 for (
int PUId = 0; PUId < numPUs; PUId++)
871 bool movable = !curPU->isFixed();
874 float curX = curPU->X();
875 float lastX = curPU->lastX();
876 float size = curPU->getNetsSetPtr()->size();
877 if (size > netSizeThr)
882 std::pow(size, powFactor) * pesudoNetWeight / std::max(minDist, std::fabs(lastX - curX)),
889 #pragma omp parallel for // schedule(dynamic, 16)
890 for (
int PUId = 0; PUId < numPUs; PUId++)
893 bool movable = !curPU->isFixed();
896 float curY = curPU->Y();
897 float lastY = curPU->lastY();
898 float size = curPU->getNetsSetPtr()->size();
899 if (size > netSizeThr)
904 std::pow(size, powFactor) * pesudoNetWeight / std::max(minDist, std::fabs(lastY - curY)),
913 #pragma omp parallel sections
917 #pragma omp parallel for // schedule(dynamic, 16)
918 for (
int PUId = 0; PUId < numPUs; PUId++)
921 bool movable = !curPU->isFixed();
924 float curX = curPU->X();
925 float lastX = curPU->lastX();
929 pesudoNetWeight / std::max(minDist, std::fabs(lastX - curX)),
y2xRatio,
true,
false);
935 #pragma omp parallel for // schedule(dynamic, 16)
936 for (
int PUId = 0; PUId < numPUs; PUId++)
939 bool movable = !curPU->isFixed();
942 float curY = curPU->Y();
943 float lastY = curPU->lastY();
947 pesudoNetWeight / std::max(minDist, std::fabs(lastY - curY)),
y2xRatio,
false,
true);
960 std::vector<std::vector<DesignInfo::DesignCell *>> &predefinedCellClusters =
963 std::set<PlacementInfo::PlacementUnit *> reallocatedPUs;
965 int reallocateCells = 0;
966 for (
auto &clusterCellSet : predefinedCellClusters)
968 std::set<PlacementInfo::PlacementUnit *> PUsInCurCluster;
969 PUsInCurCluster.clear();
973 int totalCellNum = clusterCellSet.size();
974 if (totalCellNum < 24)
976 float clusterFactor = (200.0 / totalCellNum);
977 if (clusterFactor > 1)
983 float x0 = 10000, y0 = 10000, x1 = -10000, y1 = -10000;
984 for (
auto tmpCell : clusterCellSet)
987 if (PUsInCurCluster.find(tmpPU) == PUsInCurCluster.end())
989 PUsInCurCluster.insert(tmpPU);
990 avgX += tmpPU->
X() * tmpPU->getNetsSetPtr()->size();
991 avgY += tmpPU->Y() * tmpPU->getNetsSetPtr()->size();
992 totalNetNum += tmpPU->getNetsSetPtr()->size();
1000 if (tmpPU->Y() > y1)
1005 if (PUsInCurCluster.size() > 1)
1007 if ((x1 - x0) * (y1 - y0) / PUsInCurCluster.size() < 1 && (x1 - x0) * (y1 - y0) > 1)
1009 avgX /= totalNetNum;
1010 avgY /= totalNetNum;
1012 for (
auto tmpPU : PUsInCurCluster)
1029 if (reallocatedPUs.find(tmpPU) == reallocatedPUs.end())
1031 reallocatedPUs.insert(tmpPU);
1032 reallocateCells += tmpPU->getWeight();
1039 print_warning(
"set user-defined cluster pseudo net for " + std::to_string(reallocatedPUs.size()) +
" PU(s) and " +
1040 std::to_string(reallocateCells) +
" cell(s).");
1045 if (pesudoNetWeight <= 0)
1051 if (PU2ClockRegionCenter.size() <= 0)
1054 for (
auto PUXY : PU2ClockRegionCenter)
1056 auto curPU = PUXY.first;
1057 float cX = PUXY.second.first;
1058 if (PU2ClockRegionColumn.find(curPU) != PU2ClockRegionColumn.end())
1060 int clockRegionX = PU2ClockRegionColumn[curPU];
1062 if (clockRegionX == 2)
1064 if (std::fabs(curPU->X() - cX) > 6)
1068 pesudoNetWeight * std::pow(curPU->getNetsSetPtr()->size(), 1.1),
y2xRatio,
true,
false);
1069 else if (std::fabs(curPU->X() - cX) > 3 && !
DSPCritical)
1073 pesudoNetWeight * curPU->getNetsSetPtr()->size(),
y2xRatio,
true,
false);
1078 std::fabs(curPU->X() - cX) / 3 * pesudoNetWeight * curPU->getNetsSetPtr()->size(),
y2xRatio,
1081 else if (clockRegionX < 2)
1084 float rLeft = clockRegions[0][1]->getLeft();
1085 float rRight = clockRegions[0][1]->getRight();
1086 cX = (rLeft + rRight) / 2;
1087 if ((curPU->X() - cX) > 6)
1091 pesudoNetWeight * std::pow(curPU->getNetsSetPtr()->size(), 1.1),
y2xRatio,
true,
false);
1096 pesudoNetWeight * curPU->getNetsSetPtr()->size(),
y2xRatio,
true,
false);
1101 (curPU->X() - cX) / 3 * pesudoNetWeight * curPU->getNetsSetPtr()->size(),
y2xRatio,
true,
1104 else if (clockRegionX > 2)
1106 float rLeft = clockRegions[0][3]->getLeft();
1107 float rRight = clockRegions[0][3]->getRight();
1108 cX = (rLeft + rRight) / 2;
1109 if ((curPU->X() - cX) < -6)
1113 pesudoNetWeight * std::pow(curPU->getNetsSetPtr()->size(), 1.1),
y2xRatio,
true,
false);
1118 pesudoNetWeight * curPU->getNetsSetPtr()->size(),
y2xRatio,
true,
false);
1123 (cX - curPU->X()) / 3 * pesudoNetWeight * curPU->getNetsSetPtr()->size(),
y2xRatio,
true,
1134 print_warning(
"update pseudo net of clockt region for " + std::to_string(PU2ClockRegionCenter.size()) +
" PUs");