26 LLVM_DEBUG(llvm::dbgs() <<
"\t---Begin DynamicTileAnalysis Constructor---\n");
28 maxCol = device.getTargetModel().columns();
29 maxRow = device.getTargetModel().rows();
37 for (PacketFlowOp pktFlowOp : device.getOps<PacketFlowOp>()) {
38 Region &r = pktFlowOp.getPorts();
40 Port srcPort, dstPort;
41 TileOp srcTile, dstTile;
43 for (Operation &Op : b.getOperations()) {
44 if (
auto pktSource = dyn_cast<PacketSourceOp>(Op)) {
45 srcTile = dyn_cast<TileOp>(pktSource.getTile().getDefiningOp());
46 srcPort = pktSource.port();
47 srcCoords = {srcTile.colIndex(), srcTile.rowIndex()};
48 }
else if (
auto pktDest = dyn_cast<PacketDestOp>(Op)) {
49 dstTile = dyn_cast<TileOp>(pktDest.getTile().getDefiningOp());
50 dstPort = pktDest.port();
51 dstCoords = {dstTile.colIndex(), dstTile.rowIndex()};
52 LLVM_DEBUG(llvm::dbgs()
53 <<
"\tAdding Packet Flow: (" <<
srcCoords.col <<
", "
55 << stringifyWireBundle(srcPort.bundle) << srcPort.channel
57 << stringifyWireBundle(dstPort.bundle) << dstPort.channel
61 pktFlowOp.getPriorityRoute()
62 ? *pktFlowOp.getPriorityRoute()
72 pathfinder->sortFlows(device.getTargetModel().columns(),
73 device.getTargetModel().rows());
76 for (FlowOp flowOp : device.getOps<FlowOp>()) {
77 TileOp srcTile = cast<TileOp>(flowOp.getSource().getDefiningOp());
78 TileOp dstTile = cast<TileOp>(flowOp.getDest().getDefiningOp());
81 Port srcPort = {flowOp.getSourceBundle(), flowOp.getSourceChannel()};
82 Port dstPort = {flowOp.getDestBundle(), flowOp.getDestChannel()};
83 LLVM_DEBUG(llvm::dbgs()
85 <<
")" << stringifyWireBundle(srcPort.bundle) << srcPort.channel
87 << stringifyWireBundle(dstPort.bundle) << dstPort.channel
95 for (SwitchboxOp switchboxOp : device.getOps<SwitchboxOp>()) {
96 if (!
pathfinder->addFixedConnection(switchboxOp))
97 return switchboxOp.emitOpError() <<
"Unable to add fixed connections";
106 return device.emitError(
"Unable to find a legal routing");
114 for (
auto tileOp : device.getOps<TileOp>()) {
116 col = tileOp.colIndex();
117 row = tileOp.rowIndex();
121 for (
auto switchboxOp : device.getOps<SwitchboxOp>()) {
122 int col = switchboxOp.colIndex();
123 int row = switchboxOp.rowIndex();
127 for (
auto shimmuxOp : device.getOps<ShimMuxOp>()) {
128 int col = shimmuxOp.colIndex();
129 int row = shimmuxOp.rowIndex();
134 LLVM_DEBUG(llvm::dbgs() <<
"\t---End DynamicTileAnalysis Constructor---\n");
180 std::map<WireBundle, int> maxChannels;
181 auto intraconnect = [&](
int col,
int row) {
185 for (
int i = 0, e = getMaxEnumValForWireBundle() + 1; i < e; ++i) {
186 WireBundle bundle = symbolizeWireBundle(i).value();
206 maxChannels[bundle] = channels;
210 for (
size_t i = 0; i < sb.srcPorts.size(); i++) {
211 for (
size_t j = 0; j < sb.dstPorts.size(); j++) {
212 auto &pIn = sb.srcPorts[i];
213 auto &pOut = sb.dstPorts[j];
215 pOut.bundle, pOut.channel))
221 auto isBundleInList = [](WireBundle bundle,
222 std::vector<WireBundle> bundles) {
223 return std::find(bundles.begin(), bundles.end(), bundle) !=
226 const std::vector<WireBundle> bundles = {
227 WireBundle::DMA, WireBundle::NOC, WireBundle::PLIO};
228 if (isBundleInList(pIn.bundle, bundles) ||
229 isBundleInList(pOut.bundle, bundles))
238 auto interconnect = [&](
int col,
int row,
int targetCol,
int targetRow,
239 WireBundle srcBundle, WireBundle dstBundle) {
246 for (
size_t i = 0; i < sb.srcPorts.size(); i++) {
252 for (
int row = 0;
row <= maxRow;
row++) {
253 for (
int col = 0;
col <= maxCol;
col++) {
334 std::vector<Flow> priorityFlows;
335 std::vector<Flow> normalFlows;
336 for (
auto f : flows) {
337 if (f.isPriorityFlow)
338 priorityFlows.push_back(f);
340 normalFlows.push_back(f);
344 auto getUniqueIdFromVecOfProperties =
345 [](std::vector<std::pair<int, int>> propertiesAndLimits) {
348 for (
auto pair : propertiesAndLimits) {
349 uniqueId += pair.first * multiplier;
350 multiplier *= pair.second;
354 std::sort(priorityFlows.begin(), priorityFlows.end(),
355 [maxCol, maxRow, getUniqueIdFromVecOfProperties](
const auto &lhs,
359 std::vector<std::pair<int, int>> lhsProperties = {
360 {lhs.src.coords.col, maxCol},
361 {lhs.src.coords.row, maxRow},
362 {getWireBundleAsInt(lhs.src.port.bundle),
363 AIE::getMaxEnumValForWireBundle()},
364 {lhs.src.port.channel, 0}};
365 int lhsUniqueID = getUniqueIdFromVecOfProperties(lhsProperties);
366 std::vector<std::pair<int, int>> rhsProperties = {
367 {rhs.src.coords.col, maxCol},
368 {rhs.src.coords.row, maxRow},
370 AIE::getMaxEnumValForWireBundle()},
371 {rhs.src.port.channel, 0}};
372 int rhsUniqueID = getUniqueIdFromVecOfProperties(rhsProperties);
373 return lhsUniqueID < rhsUniqueID;
375 flows = priorityFlows;
376 flows.insert(flows.end(), normalFlows.begin(), normalFlows.end());
412 std::map<PathEndPoint, double> distance;
413 std::map<PathEndPoint, PathEndPoint> preds;
414 std::map<PathEndPoint, uint64_t> indexInHeap;
415 enum Color { WHITE, GRAY, BLACK };
416 std::map<PathEndPoint, Color> colors;
419 std::map<PathEndPoint, uint64_t>,
420 std::map<PathEndPoint, double> &,
423 MutableQueue Q(distance, indexInHeap);
432 if (channels.count(
src) == 0) {
433 auto &sb = graph[std::make_pair(
src.coords,
src.coords)];
434 for (
size_t i = 0; i < sb.srcPorts.size(); i++) {
435 for (
size_t j = 0; j < sb.dstPorts.size(); j++) {
436 if (sb.srcPorts[i] ==
src.port &&
444 std::vector<std::pair<TileID, Port>> neighbors = {
445 {{
src.coords.col,
src.coords.row - 1},
446 {WireBundle::North,
src.port.channel}},
447 {{
src.coords.col - 1,
src.coords.row},
448 {WireBundle::East,
src.port.channel}},
449 {{
src.coords.col,
src.coords.row + 1},
450 {WireBundle::South,
src.port.channel}},
451 {{
src.coords.col + 1,
src.coords.row},
452 {WireBundle::West,
src.port.channel}}};
454 for (
const auto &[neighborCoords, neighborPort] : neighbors) {
455 if (graph.count(std::make_pair(
src.coords, neighborCoords)) > 0 &&
457 auto &sb = graph[std::make_pair(
src.coords, neighborCoords)];
458 if (std::find(sb.dstPorts.begin(), sb.dstPorts.end(), neighborPort) !=
460 channels[
src].push_back({neighborCoords, neighborPort});
463 std::sort(channels[
src].begin(), channels[
src].end());
466 for (
auto &dest : channels[
src]) {
467 if (distance.count(dest) == 0)
468 distance[dest] = INF;
469 auto &sb = graph[std::make_pair(
src.coords, dest.coords)];
470 size_t i = std::distance(
472 std::find(sb.srcPorts.begin(), sb.srcPorts.end(),
src.port));
473 size_t j = std::distance(
475 std::find(sb.dstPorts.begin(), sb.dstPorts.end(), dest.port));
476 assert(i < sb.srcPorts.size());
477 assert(j < sb.dstPorts.size());
478 bool relax = distance[
src] + sb.demand[i][j] < distance[dest];
479 if (colors.count(dest) == 0) {
482 distance[dest] = distance[
src] + sb.demand[i][j];
487 }
else if (colors[dest] == GRAY && relax) {
488 distance[dest] = distance[
src] + sb.demand[i][j];
506 LLVM_DEBUG(llvm::dbgs() <<
"\t---Begin Pathfinder::findPaths---\n");
507 std::map<PathEndPoint, SwitchSettings> routingSolution;
509 for (
auto &[_, sb] : graph) {
510 for (
size_t i = 0; i < sb.srcPorts.size(); i++) {
511 for (
size_t j = 0; j < sb.dstPorts.size(); j++) {
512 sb.usedCapacity[i][j] = 0;
513 sb.overCapacity[i][j] = 0;
514 sb.isPriority[i][j] =
false;
520 llvm::MapVector<int, std::vector<Flow>> groupedFlows;
521 for (
auto &f : flows) {
522 if (groupedFlows.count(f.packetGroupId) == 0) {
523 groupedFlows[f.packetGroupId] = std::vector<Flow>();
525 groupedFlows[f.packetGroupId].push_back(f);
528 int iterationCount = -1;
529 int illegalEdges = 0;
531 int totalPathLength = 0;
535 if (++iterationCount >= maxIterations) {
536 LLVM_DEBUG(llvm::dbgs()
537 <<
"\t\tPathfinder: maxIterations has been exceeded ("
539 <<
" iterations)...unable to find routing for flows.\n");
543 LLVM_DEBUG(llvm::dbgs() <<
"\t\t---Begin findPaths iteration #"
544 << iterationCount <<
"---\n");
546 for (
auto &[_, sb] : graph) {
555 routingSolution.clear();
556 for (
auto &[_, sb] : graph) {
557 for (
size_t i = 0; i < sb.srcPorts.size(); i++) {
558 for (
size_t j = 0; j < sb.dstPorts.size(); j++) {
559 sb.usedCapacity[i][j] = 0;
560 sb.packetFlowCount[i][j] = 0;
561 sb.packetGroupId[i][j] = -1;
569 for (
const auto &[_, flows] : groupedFlows) {
575 std::set<PathEndPoint> processed;
581 processed.insert(
src);
582 for (
auto endPoint :
dsts) {
583 if (endPoint ==
src) {
585 switchSettings[
src.coords].srcs.push_back(
src.port);
586 switchSettings[
src.coords].dsts.push_back(
src.port);
588 auto curr = endPoint;
590 while (!processed.count(curr)) {
591 auto &sb = graph[std::make_pair(preds[curr].
coords, curr.coords)];
593 std::distance(sb.srcPorts.begin(),
594 std::find(sb.srcPorts.begin(), sb.srcPorts.end(),
596 size_t j = std::distance(
598 std::find(sb.dstPorts.begin(), sb.dstPorts.end(), curr.port));
599 assert(i < sb.srcPorts.size());
600 assert(j < sb.dstPorts.size());
603 (sb.packetGroupId[i][j] == -1 ||
605 for (
size_t k = 0; k < sb.srcPorts.size(); k++) {
606 for (
size_t l = 0; l < sb.dstPorts.size(); l++) {
607 if (k == i || l == j) {
612 sb.packetFlowCount[i][j]++;
615 sb.packetFlowCount[i][j] = 0;
616 sb.usedCapacity[i][j]++;
619 sb.usedCapacity[i][j]++;
624 if (preds[curr].
coords == curr.coords) {
625 switchSettings[preds[curr].coords].srcs.push_back(
627 switchSettings[curr.coords].dsts.push_back(curr.port);
629 processed.insert(curr);
634 routingSolution[
src] = switchSettings;
636 for (
auto &[_, sb] : graph) {
637 for (
size_t i = 0; i < sb.srcPorts.size(); i++) {
638 for (
size_t j = 0; j < sb.dstPorts.size(); j++) {
640 if (sb.packetFlowCount[i][j] > 0) {
641 sb.packetFlowCount[i][j] = 0;
642 sb.usedCapacity[i][j]++;
650 for (
auto &[_, sb] : graph) {
651 for (
size_t i = 0; i < sb.srcPorts.size(); i++) {
652 for (
size_t j = 0; j < sb.dstPorts.size(); j++) {
655 sb.overCapacity[i][j]++;
659 <<
"\t\t\tToo much capacity on (" << sb.srcCoords.col <<
","
660 << sb.srcCoords.row <<
") " << sb.srcPorts[i].bundle
661 << sb.srcPorts[i].channel <<
" -> (" << sb.dstCoords.col <<
","
662 << sb.dstCoords.row <<
") " << sb.dstPorts[j].bundle
663 << sb.dstPorts[j].channel <<
", used_capacity = "
664 << sb.usedCapacity[i][j] <<
", demand = " << sb.demand[i][j]
665 <<
", over_capacity_count = " << sb.overCapacity[i][j] <<
"\n");
669 if (sb.srcCoords != sb.dstCoords) {
670 totalPathLength += sb.usedCapacity[i][j];
678 for (
const auto &[
PathEndPoint, switchSetting] : routingSolution) {
679 LLVM_DEBUG(llvm::dbgs()
680 <<
"\t\t\tFlow starting at (" <<
PathEndPoint.coords.col <<
","
682 LLVM_DEBUG(llvm::dbgs() << switchSetting);
684 LLVM_DEBUG(llvm::dbgs()
685 <<
"\t\t---End findPaths iteration #" << iterationCount
686 <<
" , illegal edges count = " << illegalEdges
687 <<
", total path length = " << totalPathLength <<
"---\n");
689 }
while (illegalEdges >
692 LLVM_DEBUG(llvm::dbgs() <<
"\t---End Pathfinder::findPaths---\n");
693 return routingSolution;