9#ifndef AIE_PATHFINDER_H
10#define AIE_PATHFINDER_H
16#include "llvm/ADT/ArrayRef.h"
17#include "llvm/ADT/BitVector.h"
18#include "llvm/ADT/DenseMap.h"
19#include "llvm/ADT/DenseSet.h"
20#include "llvm/ADT/IntEqClasses.h"
21#include "llvm/ADT/STLExtras.h"
22#include "llvm/ADT/SmallVector.h"
23#include "llvm/Support/Error.h"
24#include "llvm/Support/raw_ostream.h"
91 const Cell &
at(
size_t i,
size_t j)
const {
121 if (!llvm::is_contained(flows, flow))
122 flows.push_back(flow);
131 int other = leader == j ? k : j;
145 static int indexIn(llvm::ArrayRef<Port> ports,
Port p) {
146 const Port *it = llvm::find(ports, p);
147 return it == ports.end() ? -1 : it - ports.begin();
177 std::vector<PathEndPoint>
dsts;
212 os <<
"\tSwitchSettings: ";
213 for (
const auto &[coords, setting] : ss)
214 os << coords <<
": " << setting <<
" | ";
233 std::function<bool(
const PathEndPoint &,
const std::set<int> &,
245 llvm::function_ref<
bool(
TileID)> low,
bool up,
size_t limit)>;
271 std::vector<std::pair<PathEndPoint, PathEndPoint>>
apart;
275 std::vector<std::pair<PathEndPoint, PathEndPoint>>
together;
302 std::optional<mlir::Location>
loc = std::nullopt)
305 void log(llvm::raw_ostream &os)
const override;
307 return llvm::inconvertibleErrorCode();
312 std::optional<mlir::Location>
loc;
318 :
public llvm::ErrorInfo<DeadlockProneRouting, RoutingFailure> {
321 using ErrorInfo::ErrorInfo;
327 :
public llvm::ErrorInfo<PinnedRoutingFailure, RoutingFailure> {
330 using ErrorInfo::ErrorInfo;
369 std::optional<int> packetId,
bool isPriorityFlow,
370 std::optional<mlir::Location> loc = std::nullopt);
380 llvm::Expected<Routing>
findPaths(
int maxIterations);
415 enum PortSide :
int { In = 0, Out = 1 };
416 static int stateId(
int nodeId, PortSide side) {
return 2 * nodeId + side; }
417 static int stateNode(
int state) {
return state >> 1; }
424 void buildRoutingGraph();
427 double edgeWeight(
const Edge &e, std::optional<int> packetId,
428 const llvm::BitVector *avoid,
429 const llvm::BitVector *avoidBranch)
const;
439 void dijkstraShortestPaths(
440 llvm::ArrayRef<int> seeds, llvm::ArrayRef<double> seedCosts,
441 std::optional<int> packetId,
const llvm::BitVector *avoid =
nullptr,
442 const llvm::DenseMap<int, llvm::BitVector> *branchAvoid =
nullptr,
443 const llvm::DenseSet<int> *stops =
nullptr,
444 llvm::ArrayRef<int> targets = {},
445 llvm::function_ref<bool(
int,
int)> mayCross =
nullptr);
451 llvm::Error routePart(
RouteState &st,
int flow);
454 int applyRoutingFaults(
RouteState &st,
const RoutingFaults &faults);
456 llvm::Error explainNoRouting(
const RouteState &st)
const;
459 llvm::Error cutOverflow()
const;
460 bool hasRoom(
const SwitchboxConnect &sb)
const;
462 bool shareAllChannels();
463 bool capCrowdedFanOut();
464 bool routeIdsApart();
465 bool splitSharedIds();
469 std::vector<Flow> flows;
471 std::map<std::pair<PathEndPoint, PathEndPoint>, llvm::SmallVector<int, 2>>
474 std::map<PathEndPoint, std::set<int>> idsBySource()
const;
476 std::map<PathEndPoint, std::set<int>> priorityIds;
478 std::map<PathEndPoint, std::map<PathEndPoint, mlir::Location>> flowLocs;
479 std::optional<mlir::Location> flowLoc(
const PathEndPoint &src,
480 const PathEndPoint *dst)
const;
483 std::map<std::pair<TileID, TileID>, SwitchboxConnect> graph;
486 bool graphBuilt =
false;
487 std::map<PathEndPoint, int> nodeIds;
488 std::vector<PathEndPoint> nodes;
489 std::vector<std::vector<Edge>> adjacency;
490 std::vector<size_t> wireEdgesBegin;
494 std::vector<double> distance;
495 std::vector<uint64_t> indexInHeap;
496 std::vector<int8_t> colors;
497 std::vector<int> preds;
498 std::vector<Edge> predEdge;
500 int getOrAddNodeId(
const PathEndPoint &pep);
502 PacketConstraints constraints;
504 std::string checkReason;
507 bool packetsFailed =
true;
508 bool shareChannels =
false, idsApart =
false, splitShared =
false;
511 bool meetApart =
false;
514 bool treesMet =
false;
516 int columns = 0, rows = 0;
517 size_t relaxStep = 0;
518 llvm::DenseSet<TileID> crowdedTiles, cappedTiles;
531 TileOp
getTile(mlir::OpBuilder &builder,
int col,
int row);
533 SwitchboxOp
getSwitchbox(mlir::OpBuilder &builder,
int col,
int row);
534 ShimMuxOp
getShimMux(mlir::OpBuilder &builder,
int col);
539 return coordToSwitchbox.lookup(tile);
542 return coordToShimMux.lookup({col, 0});
555 static constexpr int maxIterations = 1000;
557 int maxCol = 0, maxRow = 0;
558 llvm::DenseMap<TileID, TileOp> coordToTile;
559 llvm::DenseMap<TileID, SwitchboxOp> coordToSwitchbox;
560 llvm::DenseMap<TileID, ShimMuxOp> coordToShimMux;
ShimMuxOp getShimMux(mlir::OpBuilder &builder, int col)
SwitchboxOp getSwitchbox(mlir::OpBuilder &builder, int col, int row)
SwitchboxOp lookupSwitchbox(TileID tile) const
TileOp getTile(mlir::OpBuilder &builder, const TileID &tileId)
TileOp lookupTile(TileID tile) const
TileOp getTile(mlir::OpBuilder &builder, int col, int row)
llvm::Error runAnalysis(DeviceOp &device)
std::set< PathEndPoint > processedFlows
ShimMuxOp lookupShimMux(int col) const
std::vector< std::pair< TileID, Port > > avoidedPorts
void avoidPort(TileID coords, Port port)
llvm::Expected< Routing > findPaths(int maxIterations)
void setPacketConstraints(PacketConstraints c)
void excludeTile(TileID coords)
void addFlow(TileID srcCoords, Port srcPort, TileID dstCoords, Port dstPort, std::optional< int > packetId, bool isPriorityFlow, std::optional< mlir::Location > loc=std::nullopt)
void initialize(int maxCol, int maxRow, const AIETargetModel &targetModel)
mlir::LogicalResult addFixedConnection(SwitchboxOp switchboxOp)
void log(llvm::raw_ostream &os) const override
RoutingFailure(std::string reason, RoutingFaults faults={}, std::optional< mlir::Location > loc=std::nullopt)
std::optional< mlir::Location > loc
std::error_code convertToErrorCode() const override
std::function< llvm::Error(const Routing &)> RoutingCheck
int shimMuxChannelTo(Port dst)
struct TileID { friend std::ostream &operator<<(std::ostream &os, const TileID &s) { os<< "TileID("<< s.col<< ", "<< s.row<< ")"; return os; } friend std::string to_string(const TileID &s) { std::ostringstream ss; ss<< s; return ss.str(); } friend llvm::raw_ostream &operator<<(llvm::raw_ostream &os, const TileID &s) { os<< to_string(s); return os; } inline bool operator<(const TileID &rhs) const { return std::tie(col, row)< std::tie(rhs.col, rhs.row); } bool operator==(const TileID &rhs) const { return std::tie(col, row)==std::tie(rhs.col, rhs.row); } bool operator!=(const TileID &rhs) const { return !(*this==rhs);} int col, row;} TileID
std::function< bool(const PathEndPoint &, const std::set< int > &, const PathEndPoint &, const std::set< int > &)> PacketConflict
llvm::raw_ostream & operator<<(llvm::raw_ostream &os, const SwitchSettings &ss)
std::function< PacketsApart( llvm::function_ref< bool(TileID)> low, bool up, size_t limit)> PacketsApartAcross
int shimMuxChannelFrom(Port src)
std::string describeTilePort(TileID tile, Port port)
Names a tile port the way diagnostics do, e.g. "(0, 2) DMA:1".
struct Port { WireBundle bundle; int channel; bool operator==(const Port &rhs) const { return std::tie(bundle, channel)==std::tie(rhs.bundle, rhs.channel); } bool operator!=(const Port &rhs) const { return !(*this==rhs);} bool operator<(const Port &rhs) const { return std::tie(bundle, channel)< std::tie(rhs.bundle, rhs.channel); } friend std::ostream &operator<<(std::ostream &os, const Port &port) { os<< "("; os<< stringifyWireBundle(port.bundle).str(); os<< ": "<< std::to_string(port.channel)<< ")"; return os; } friend llvm::raw_ostream &operator<<(llvm::raw_ostream &os, const Port &port) { os<< to_string(port); return os; } } Port
std::map< TileID, SwitchSetting > SwitchSettings
std::string describePort(Port port)
Names a port the way diagnostics do, e.g. "DMA:1".
std::map< PathEndPoint, std::vector< TreeHop > > PacketTrees
std::vector< PathEndPoint > dsts
std::optional< int > packetId
std::map< PathEndPoint, std::set< int > > pinnedIds
PacketsApartAcross apartAcross
std::vector< std::string > flows
PathEndPoint(TileID coords, Port port)
bool operator==(const PathEndPoint &rhs) const
friend llvm::raw_ostream & operator<<(llvm::raw_ostream &os, const PathEndPoint &s)
bool operator<(const PathEndPoint &rhs) const
std::vector< std::pair< TileID, Connect > > connections
std::vector< PathEndPoint > untrunk
std::vector< std::pair< PathEndPoint, PathEndPoint > > together
std::vector< TreeSplit > splits
std::vector< TileID > crowded
std::vector< std::pair< PathEndPoint, PathEndPoint > > apart
std::map< PathEndPoint, SwitchSettings > settings
std::map< std::pair< PathEndPoint, int >, SwitchSettings > idSettings
bool operator<(const SwitchSetting &rhs) const
friend llvm::raw_ostream & operator<<(llvm::raw_ostream &os, const SwitchSetting &s)
SwitchSetting(std::vector< Port > srcs)
SwitchSetting(std::vector< Port > srcs, std::vector< Port > dsts)
llvm::SmallDenseMap< int, int, 2 > packetIds
llvm::IntEqClasses dstUnits
llvm::ArrayRef< int > unitFlows(int j) const
std::vector< Port > dstPorts
llvm::BitVector packetOnlySrc
std::vector< Port > srcPorts
std::vector< llvm::SmallVector< int, 2 > > unitPacketFlows
SwitchboxConnect(TileID srcCoords, TileID dstCoords)
int srcIndex(Port p) const
SwitchboxConnect()=default
static void bumpDemand(Cell &c)
void addToUnit(int j, int flow)
llvm::BitVector circuitOnlyDst
SwitchboxConnect(TileID coords)
Cell & at(size_t i, size_t j)
std::vector< Cell > cells
int dstIndex(Port p) const
void joinUnits(int j, int k)
const Cell & at(size_t i, size_t j) const
bool operator==(const TreeHop &rhs) const
std::optional< PathEndPoint > apart
bool operator<(const TreeSplit &rhs) const