31 template <
class NodeList,
class NetList>
35 std::vector<int> inputCluster;
37 for (
unsigned int i = 0;
i < nodeList.size();
i++)
39 inputCluster.push_back(
i);
41 recursiveMinCutPartition(inputCluster,
this, eachClusterDSPNum, eachClusterBRAMNum);
48 int numClusters = clusters.size();
49 for (
int i = 0;
i < numClusters;
i++)
52 for (
int j =
i + 1; j < numClusters; j++)
54 if (clusters[
i].size() > clusters[j].size())
56 std::vector<int> tmpNodes = clusters[
i];
57 clusters[
i] = clusters[j];
58 clusters[j] = tmpNodes;
64 template <
class NodeList,
class NetList>
67 int eachClusterBRAMNum)
70 std::array<std::vector<int>, 2> outputClusters;
73 int cut = graphPartitioner->
minCutBipartition(inputCluster, outputClusters, graphPartitioner, eachClusterDSPNum,
80 graphPartitioner->
clusters.push_back(inputCluster);
84 if (outputClusters[0].size() == 0 && outputClusters[1].size() == 0)
87 graphPartitioner->
clusters.push_back(inputCluster);
91 assert(outputClusters[0].size() > 0 && outputClusters[1].size() > 0);
93 std::thread t1(recursiveMinCutPartition, std::ref(outputClusters[0]), std::ref(graphPartitioner),
94 std::ref(eachClusterDSPNum), std::ref(eachClusterBRAMNum));
95 std::thread t2(recursiveMinCutPartition, std::ref(outputClusters[1]), std::ref(graphPartitioner),
96 std::ref(eachClusterDSPNum), std::ref(eachClusterBRAMNum));
104 return (stat(name.c_str(), &buffer) == 0);
107 template <
class NodeList,
class NetList>
109 std::array<std::vector<int>, 2> &outputClusters,
111 int eachClusterDSPNum,
int eachClusterBRAMNum)
116 outputClusters[0].clear();
117 outputClusters[1].clear();
118 unsigned int totalWeight = 0;
121 int totalBRAMNum = 0;
122 for (
auto PUId : inputCluster)
124 totalWeight += graphPartitioner->
nodeList[PUId]->getWeight();
125 totalBRAMNum += graphPartitioner->
nodeList[PUId]->getBRAMNum();
126 totalDSPNum += graphPartitioner->
nodeList[PUId]->getDSPNum();
132 if (inputCluster.size() < minCellClusterSize / 5)
135 if (totalDSPNum <= eachClusterDSPNum && totalBRAMNum <= eachClusterBRAMNum)
137 if (
double(minCellClusterSize) > 0.8 * totalWeight)
142 print_info(
"partitioning iter#" + std::to_string(
cnt) +
" #curNode: " +
143 std::to_string(inputCluster.size()) +
" totalWeight=" + std::to_string(totalWeight) +
144 " minCellClusterSize > 0.8 * totalWeight => SHOULD CONTINUE PARTITIONING");
149 graphPartitioner->
cntLock.lock();
151 print_info(
"partitioning iter#" + std::to_string(
cnt) +
" #curNode: " +
152 std::to_string(inputCluster.size()) +
" #totalDSPNum: " + std::to_string(totalDSPNum) +
153 " #totalBRAMNum: " + std::to_string(totalBRAMNum) +
" SHOULD CONTINUE PARTITIONING");
154 graphPartitioner->
cntLock.unlock();
157 if (0.4 *
double(minCellClusterSize) > totalWeight)
161 int numHyperNodes = 0;
162 std::vector<int> placementUnit2hyperNode(graphPartitioner->
nodeList.size(), -1);
164 for (
auto instId : inputCluster)
165 placementUnit2hyperNode[instId] = numHyperNodes++;
167 int numPlacementNets = 0;
168 std::vector<bool> isCsdNet(graphPartitioner->
netList.size(),
false);
169 int numPlacementPins = 0;
170 for (
auto net : graphPartitioner->
netList)
173 for (
auto tmpPU : net->getUnits())
175 if (placementUnit2hyperNode[tmpPU->getId()] != -1)
184 isCsdNet[net->getId()] =
true;
188 unsigned int shareMemorySize = 6 + numHyperNodes + numPlacementNets + 1 + numPlacementPins + numHyperNodes + 2;
199 std::cout <<
"try to find [" <<
targetPath <<
"] but not found.\n";
200 assert(
false &&
"target partitioning process executable should be found!");
206 shareMemory[0] = numHyperNodes;
207 shareMemory[1] = numPlacementNets;
208 shareMemory[2] = numPlacementPins;
209 double final_imbal = std::max(0.5 -
double(minCellClusterSize) / totalWeight, 0.4);
210 *(
double *)(shareMemory + 3) = final_imbal;
211 int *cut = shareMemory + 5;
212 int *cwghts = shareMemory + 6;
213 int *xpins = cwghts + numHyperNodes;
214 int *pins = xpins + numPlacementNets + 1;
215 int *partvec = pins + numPlacementPins;
216 int *partweights = partvec + numHyperNodes;
218 int *hyperNode2placementUnit =
new int[numHyperNodes];
219 for (
auto instId : inputCluster)
220 hyperNode2placementUnit[placementUnit2hyperNode[instId]] = instId;
222 for (
int i = 0;
i < numHyperNodes; ++
i)
224 assert((
unsigned int)hyperNode2placementUnit[
i] < graphPartitioner->
nodeList.size());
225 cwghts[
i] = graphPartitioner->
nodeList[hyperNode2placementUnit[
i]]->getWeight();
231 int maxCut = maxCutRate * numPlacementNets;
235 int indexNet = 0, indexPin = 0;
236 for (
auto net : graphPartitioner->
netList)
238 if (isCsdNet[net->getId()])
240 for (
auto tmpPU : net->getUnits())
241 if (placementUnit2hyperNode[tmpPU->getId()] != -1)
242 pins[indexPin++] = placementUnit2hyperNode[tmpPU->getId()];
243 xpins[++indexNet] = indexPin;
246 assert(indexPin == numPlacementPins && indexNet == numPlacementNets);
252 for (
int i = 0;
i < numHyperNodes; ++
i)
253 outputClusters[partvec[
i]].push_back(inputCluster[
i]);
255 int totalWeight0 = 0;
256 for (
auto PUId : outputClusters[0])
257 totalWeight0 += graphPartitioner->
nodeList[PUId]->getWeight();
258 int totalWeight1 = 0;
259 for (
auto PUId : outputClusters[1])
260 totalWeight1 += graphPartitioner->
nodeList[PUId]->getWeight();
262 unsigned minClusterTotalWeight = std::min(totalWeight0, totalWeight1);
263 double imbal = 0.5 - double(minClusterTotalWeight) / totalWeight;
265 graphPartitioner->
cntLock.lock();
266 if ((*cut > maxCut || ((
float)outputClusters[0].size() / (
float)outputClusters[1].size() < 0.666) ||
267 ((
float)outputClusters[1].size() / (
float)outputClusters[0].size() < 0.666)) &&
268 (minCellClusterSize * 1.25 > totalWeight && totalDSPNum <= 3 * eachClusterDSPNum &&
269 totalBRAMNum <= 3 * eachClusterBRAMNum))
272 print_warning(
"partitioned iter#" + std::to_string(
cnt) +
" #node: " + std::to_string(numHyperNodes) +
273 " #net: " + std::to_string(numPlacementNets) +
" max_cut: " + std::to_string(maxCut) +
274 " max_imbal: " + std::to_string(final_imbal) +
" get too large cut: " + std::to_string(*cut) +
275 " failed to find cut meeting requirements of min-cut or size balance. cluster[0].size=" +
276 std::to_string(outputClusters[0].size()) +
277 " cluster[1].size=" + std::to_string(outputClusters[1].size()));
278 outputClusters[0].clear();
279 outputClusters[1].clear();
284 print_info(
"partitioned iter#" + std::to_string(
cnt) +
" #node: " + std::to_string(numHyperNodes) +
285 " #net: " + std::to_string(numPlacementNets) +
" max_cut: " + std::to_string(maxCut) +
286 " max_imbal: " + std::to_string(final_imbal) +
" succeed with " +
287 std::to_string(partweights[0]) +
" and " + std::to_string(partweights[1]) +
288 " (cut: " + std::to_string(*cut) +
", imbal: " + std::to_string(imbal) +
")" +
289 "cluster[0].size=" + std::to_string(outputClusters[0].size()) +
290 " cluster[1].size=" + std::to_string(outputClusters[1].size()));
294 graphPartitioner->
cntLock.unlock();
297 delete[] hyperNode2placementUnit;
305 std::vector<PlacementInfo::PlacementNet *>>;