26 LLVM_DEBUG(llvm::dbgs() <<
"\t---Begin DynamicTileAnalysis Constructor---\n");
30 for (TileOp tileOp : device.getOps<TileOp>()) {
41 for (PacketFlowOp pktFlowOp : device.getOps<PacketFlowOp>()) {
42 Region &r = pktFlowOp.getPorts();
44 Port srcPort, dstPort;
45 TileOp srcTile, dstTile;
47 for (Operation &Op : b.getOperations()) {
48 if (
auto pktSource = dyn_cast<PacketSourceOp>(Op)) {
49 srcTile = dyn_cast<TileOp>(pktSource.getTile().getDefiningOp());
50 srcPort = pktSource.port();
51 srcCoords = {srcTile.colIndex(), srcTile.rowIndex()};
52 }
else if (
auto pktDest = dyn_cast<PacketDestOp>(Op)) {
53 dstTile = dyn_cast<TileOp>(pktDest.getTile().getDefiningOp());
54 dstPort = pktDest.port();
55 dstCoords = {dstTile.colIndex(), dstTile.rowIndex()};
56 LLVM_DEBUG(llvm::dbgs()
57 <<
"\tAdding Packet Flow: (" <<
srcCoords.col <<
", "
59 << stringifyWireBundle(srcPort.bundle) << srcPort.channel
61 << stringifyWireBundle(dstPort.bundle) << dstPort.channel
65 pktFlowOp.getPriorityRoute()
66 ? *pktFlowOp.getPriorityRoute()
76 pathfinder->sortFlows(device.getTargetModel().columns(),
77 device.getTargetModel().rows());
80 for (FlowOp flowOp : device.getOps<FlowOp>()) {
81 TileOp srcTile = cast<TileOp>(flowOp.getSource().getDefiningOp());
82 TileOp dstTile = cast<TileOp>(flowOp.getDest().getDefiningOp());
85 Port srcPort = {flowOp.getSourceBundle(), flowOp.getSourceChannel()};
86 Port dstPort = {flowOp.getDestBundle(), flowOp.getDestChannel()};
87 LLVM_DEBUG(llvm::dbgs()
89 <<
")" << stringifyWireBundle(srcPort.bundle) << srcPort.channel
91 << stringifyWireBundle(dstPort.bundle) << dstPort.channel
99 for (SwitchboxOp switchboxOp : device.getOps<SwitchboxOp>()) {
100 if (!
pathfinder->addFixedConnection(switchboxOp))
101 return switchboxOp.emitOpError() <<
"Unable to add fixed connections";
110 return device.emitError(
"Unable to find a legal routing");
118 for (
auto tileOp : device.getOps<TileOp>()) {
120 col = tileOp.colIndex();
121 row = tileOp.rowIndex();
127 for (
auto switchboxOp : device.getOps<SwitchboxOp>()) {
128 int col = switchboxOp.colIndex();
129 int row = switchboxOp.rowIndex();
133 for (
auto shimmuxOp : device.getOps<ShimMuxOp>()) {
134 int col = shimmuxOp.colIndex();
135 int row = shimmuxOp.rowIndex();
140 LLVM_DEBUG(llvm::dbgs() <<
"\t---End DynamicTileAnalysis Constructor---\n");
192 std::map<WireBundle, int> maxChannels;
193 auto intraconnect = [&](
int col,
int row) {
197 const std::vector<WireBundle> bundles = {
198 WireBundle::Core, WireBundle::DMA, WireBundle::FIFO,
199 WireBundle::South, WireBundle::West, WireBundle::North,
200 WireBundle::East, WireBundle::PLIO, WireBundle::NOC,
201 WireBundle::Trace, WireBundle::TileControl};
202 for (WireBundle bundle : bundles) {
222 maxChannels[bundle] = channels;
226 for (
size_t i = 0; i < sb.srcPorts.size(); i++) {
227 for (
size_t j = 0; j < sb.dstPorts.size(); j++) {
228 auto &pIn = sb.srcPorts[i];
229 auto &pOut = sb.dstPorts[j];
231 pOut.bundle, pOut.channel))
237 auto isBundleInList = [](WireBundle bundle,
238 std::vector<WireBundle> bundles) {
239 return std::find(bundles.begin(), bundles.end(), bundle) !=
242 const std::vector<WireBundle> bundles = {
243 WireBundle::DMA, WireBundle::NOC, WireBundle::PLIO};
244 if (isBundleInList(pIn.bundle, bundles) ||
245 isBundleInList(pOut.bundle, bundles))
254 auto interconnect = [&](
int col,
int row,
int targetCol,
int targetRow,
255 WireBundle srcBundle, WireBundle dstBundle) {
262 for (
size_t i = 0; i < sb.srcPorts.size(); i++) {
268 for (
int row = 0;
row <= maxRow;
row++) {
269 for (
int col = 0;
col <= maxCol;
col++) {
350 std::vector<Flow> priorityFlows;
351 std::vector<Flow> normalFlows;
352 for (
auto f : flows) {
353 if (f.isPriorityFlow)
354 priorityFlows.push_back(f);
356 normalFlows.push_back(f);
360 auto getUniqueIdFromVecOfProperties =
361 [](std::vector<std::pair<int, int>> propertiesAndLimits) {
364 for (
auto pair : propertiesAndLimits) {
365 uniqueId += pair.first * multiplier;
366 multiplier *= pair.second;
370 std::sort(priorityFlows.begin(), priorityFlows.end(),
371 [maxCol, maxRow, getUniqueIdFromVecOfProperties](
const auto &lhs,
375 std::vector<std::pair<int, int>> lhsProperties = {
376 {lhs.src.coords.col, maxCol},
377 {lhs.src.coords.row, maxRow},
378 {getWireBundleAsInt(lhs.src.port.bundle),
379 AIE::getMaxEnumValForWireBundle()},
380 {lhs.src.port.channel, 0}};
381 int lhsUniqueID = getUniqueIdFromVecOfProperties(lhsProperties);
382 std::vector<std::pair<int, int>> rhsProperties = {
383 {rhs.src.coords.col, maxCol},
384 {rhs.src.coords.row, maxRow},
386 AIE::getMaxEnumValForWireBundle()},
387 {rhs.src.port.channel, 0}};
388 int rhsUniqueID = getUniqueIdFromVecOfProperties(rhsProperties);
389 return lhsUniqueID < rhsUniqueID;
391 flows = priorityFlows;
392 flows.insert(flows.end(), normalFlows.begin(), normalFlows.end());
428 std::map<PathEndPoint, double> distance;
429 std::map<PathEndPoint, PathEndPoint> preds;
430 std::map<PathEndPoint, uint64_t> indexInHeap;
431 enum Color { WHITE, GRAY, BLACK };
432 std::map<PathEndPoint, Color> colors;
435 std::map<PathEndPoint, uint64_t>,
436 std::map<PathEndPoint, double> &,
439 MutableQueue Q(distance, indexInHeap);
448 if (channels.count(
src) == 0) {
449 auto &sb = graph[std::make_pair(
src.coords,
src.coords)];
450 for (
size_t i = 0; i < sb.srcPorts.size(); i++) {
451 for (
size_t j = 0; j < sb.dstPorts.size(); j++) {
452 if (sb.srcPorts[i] ==
src.port &&
460 std::vector<std::pair<TileID, Port>> neighbors = {
461 {{
src.coords.col,
src.coords.row - 1},
462 {WireBundle::North,
src.port.channel}},
463 {{
src.coords.col - 1,
src.coords.row},
464 {WireBundle::East,
src.port.channel}},
465 {{
src.coords.col,
src.coords.row + 1},
466 {WireBundle::South,
src.port.channel}},
467 {{
src.coords.col + 1,
src.coords.row},
468 {WireBundle::West,
src.port.channel}}};
470 for (
const auto &[neighborCoords, neighborPort] : neighbors) {
471 if (graph.count(std::make_pair(
src.coords, neighborCoords)) > 0 &&
473 auto &sb = graph[std::make_pair(
src.coords, neighborCoords)];
474 if (std::find(sb.dstPorts.begin(), sb.dstPorts.end(), neighborPort) !=
476 channels[
src].push_back({neighborCoords, neighborPort});
479 std::sort(channels[
src].begin(), channels[
src].end());
482 for (
auto &dest : channels[
src]) {
483 if (distance.count(dest) == 0)
484 distance[dest] = INF;
485 auto &sb = graph[std::make_pair(
src.coords, dest.coords)];
486 size_t i = std::distance(
488 std::find(sb.srcPorts.begin(), sb.srcPorts.end(),
src.port));
489 size_t j = std::distance(
491 std::find(sb.dstPorts.begin(), sb.dstPorts.end(), dest.port));
492 assert(i < sb.srcPorts.size());
493 assert(j < sb.dstPorts.size());
494 bool relax = distance[
src] + sb.demand[i][j] < distance[dest];
495 if (colors.count(dest) == 0) {
498 distance[dest] = distance[
src] + sb.demand[i][j];
503 }
else if (colors[dest] == GRAY && relax) {
504 distance[dest] = distance[
src] + sb.demand[i][j];
522 LLVM_DEBUG(llvm::dbgs() <<
"\t---Begin Pathfinder::findPaths---\n");
523 std::map<PathEndPoint, SwitchSettings> routingSolution;
525 for (
auto &[_, sb] : graph) {
526 for (
size_t i = 0; i < sb.srcPorts.size(); i++) {
527 for (
size_t j = 0; j < sb.dstPorts.size(); j++) {
528 sb.usedCapacity[i][j] = 0;
529 sb.overCapacity[i][j] = 0;
530 sb.isPriority[i][j] =
false;
536 llvm::MapVector<int, std::vector<Flow>> groupedFlows;
537 for (
auto &f : flows) {
538 if (groupedFlows.count(f.packetGroupId) == 0) {
539 groupedFlows[f.packetGroupId] = std::vector<Flow>();
541 groupedFlows[f.packetGroupId].push_back(f);
544 int iterationCount = -1;
545 int illegalEdges = 0;
547 int totalPathLength = 0;
551 if (++iterationCount >= maxIterations) {
552 LLVM_DEBUG(llvm::dbgs()
553 <<
"\t\tPathfinder: maxIterations has been exceeded ("
555 <<
" iterations)...unable to find routing for flows.\n");
559 LLVM_DEBUG(llvm::dbgs() <<
"\t\t---Begin findPaths iteration #"
560 << iterationCount <<
"---\n");
562 for (
auto &[_, sb] : graph) {
571 routingSolution.clear();
572 for (
auto &[_, sb] : graph) {
573 for (
size_t i = 0; i < sb.srcPorts.size(); i++) {
574 for (
size_t j = 0; j < sb.dstPorts.size(); j++) {
575 sb.usedCapacity[i][j] = 0;
576 sb.packetFlowCount[i][j] = 0;
577 sb.packetGroupId[i][j] = -1;
585 for (
const auto &[_, flows] : groupedFlows) {
591 std::set<PathEndPoint> processed;
597 processed.insert(
src);
598 for (
auto endPoint :
dsts) {
599 if (endPoint ==
src) {
601 switchSettings[
src.coords].srcs.push_back(
src.port);
602 switchSettings[
src.coords].dsts.push_back(
src.port);
604 auto curr = endPoint;
606 while (!processed.count(curr)) {
607 auto &sb = graph[std::make_pair(preds[curr].
coords, curr.coords)];
609 std::distance(sb.srcPorts.begin(),
610 std::find(sb.srcPorts.begin(), sb.srcPorts.end(),
612 size_t j = std::distance(
614 std::find(sb.dstPorts.begin(), sb.dstPorts.end(), curr.port));
615 assert(i < sb.srcPorts.size());
616 assert(j < sb.dstPorts.size());
619 (sb.packetGroupId[i][j] == -1 ||
621 for (
size_t k = 0; k < sb.srcPorts.size(); k++) {
622 for (
size_t l = 0; l < sb.dstPorts.size(); l++) {
623 if (k == i || l == j) {
628 sb.packetFlowCount[i][j]++;
631 sb.packetFlowCount[i][j] = 0;
632 sb.usedCapacity[i][j]++;
635 sb.usedCapacity[i][j]++;
640 if (preds[curr].
coords == curr.coords) {
641 switchSettings[preds[curr].coords].srcs.push_back(
643 switchSettings[curr.coords].dsts.push_back(curr.port);
645 processed.insert(curr);
650 routingSolution[
src] = switchSettings;
652 for (
auto &[_, sb] : graph) {
653 for (
size_t i = 0; i < sb.srcPorts.size(); i++) {
654 for (
size_t j = 0; j < sb.dstPorts.size(); j++) {
656 if (sb.packetFlowCount[i][j] > 0) {
657 sb.packetFlowCount[i][j] = 0;
658 sb.usedCapacity[i][j]++;
666 for (
auto &[_, sb] : graph) {
667 for (
size_t i = 0; i < sb.srcPorts.size(); i++) {
668 for (
size_t j = 0; j < sb.dstPorts.size(); j++) {
671 sb.overCapacity[i][j]++;
675 <<
"\t\t\tToo much capacity on (" << sb.srcCoords.col <<
","
676 << sb.srcCoords.row <<
") " << sb.srcPorts[i].bundle
677 << sb.srcPorts[i].channel <<
" -> (" << sb.dstCoords.col <<
","
678 << sb.dstCoords.row <<
") " << sb.dstPorts[j].bundle
679 << sb.dstPorts[j].channel <<
", used_capacity = "
680 << sb.usedCapacity[i][j] <<
", demand = " << sb.demand[i][j]
681 <<
", over_capacity_count = " << sb.overCapacity[i][j] <<
"\n");
685 if (sb.srcCoords != sb.dstCoords) {
686 totalPathLength += sb.usedCapacity[i][j];
694 for (
const auto &[
PathEndPoint, switchSetting] : routingSolution) {
695 LLVM_DEBUG(llvm::dbgs()
696 <<
"\t\t\tFlow starting at (" <<
PathEndPoint.coords.col <<
","
698 LLVM_DEBUG(llvm::dbgs() << switchSetting);
700 LLVM_DEBUG(llvm::dbgs()
701 <<
"\t\t---End findPaths iteration #" << iterationCount
702 <<
" , illegal edges count = " << illegalEdges
703 <<
", total path length = " << totalPathLength <<
"---\n");
705 }
while (illegalEdges >
708 LLVM_DEBUG(llvm::dbgs() <<
"\t---End Pathfinder::findPaths---\n");
709 return routingSolution;