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"
89 const Cell &
at(
size_t i,
size_t j)
const {
119 if (!llvm::is_contained(flows, flow))
120 flows.push_back(flow);
129 int other = leader == j ? k : j;
143 static int indexIn(llvm::ArrayRef<Port> ports,
Port p) {
144 const Port *it = llvm::find(ports, p);
145 return it == ports.end() ? -1 : it - ports.begin();
175 std::vector<PathEndPoint>
dsts;
210 os <<
"\tSwitchSettings: ";
211 for (
const auto &[coords, setting] : ss)
212 os << coords <<
": " << setting <<
" | ";
231 std::function<bool(
const PathEndPoint &,
const std::set<int> &,
243 llvm::function_ref<
bool(
TileID)> low,
bool up,
size_t limit)>;
269 std::vector<std::pair<PathEndPoint, PathEndPoint>>
apart;
273 std::vector<std::pair<PathEndPoint, PathEndPoint>>
together;
301 std::optional<mlir::Location>
loc = std::nullopt)
304 void log(llvm::raw_ostream &os)
const override;
306 return llvm::inconvertibleErrorCode();
311 std::optional<mlir::Location>
loc;
317 :
public llvm::ErrorInfo<DeadlockProneRouting, RoutingFailure> {
320 using ErrorInfo::ErrorInfo;
326 :
public llvm::ErrorInfo<PinnedRoutingFailure, RoutingFailure> {
329 using ErrorInfo::ErrorInfo;
365 std::optional<int> packetId,
bool isPriorityFlow,
366 std::optional<mlir::Location> loc = std::nullopt);
374 llvm::Expected<Routing>
findPaths(
int maxIterations);
409 enum PortSide :
int { In = 0, Out = 1 };
410 static int stateId(
int nodeId, PortSide side) {
return 2 * nodeId + side; }
411 static int stateNode(
int state) {
return state >> 1; }
418 void buildRoutingGraph();
421 double edgeWeight(
const Edge &e, std::optional<int> packetId,
422 const llvm::BitVector *avoid,
423 const llvm::BitVector *avoidBranch)
const;
433 void dijkstraShortestPaths(
434 llvm::ArrayRef<int> seeds, llvm::ArrayRef<double> seedCosts,
435 std::optional<int> packetId,
const llvm::BitVector *avoid =
nullptr,
436 const llvm::DenseMap<int, llvm::BitVector> *branchAvoid =
nullptr,
437 const llvm::DenseSet<int> *stops =
nullptr,
438 llvm::ArrayRef<int> targets = {},
439 llvm::function_ref<bool(
int,
int)> mayCross =
nullptr);
445 llvm::Error routePart(
RouteState &st,
int flow);
448 int applyRoutingFaults(
RouteState &st,
const RoutingFaults &faults);
450 llvm::Error explainNoRouting(
const RouteState &st)
const;
453 llvm::Error cutOverflow()
const;
454 bool hasRoom(
const SwitchboxConnect &sb)
const;
456 bool shareAllChannels();
457 bool capCrowdedFanOut();
458 bool routeIdsApart();
459 bool splitSharedIds();
463 std::vector<Flow> flows;
465 std::map<std::pair<PathEndPoint, PathEndPoint>, llvm::SmallVector<int, 2>>
468 std::map<PathEndPoint, std::set<int>> idsBySource()
const;
470 std::map<PathEndPoint, std::set<int>> priorityIds;
472 std::map<PathEndPoint, std::map<PathEndPoint, mlir::Location>> flowLocs;
473 std::optional<mlir::Location> flowLoc(
const PathEndPoint &src,
474 const PathEndPoint *dst)
const;
477 std::map<std::pair<TileID, TileID>, SwitchboxConnect> graph;
480 bool graphBuilt =
false;
481 std::map<PathEndPoint, int> nodeIds;
482 std::vector<PathEndPoint> nodes;
483 std::vector<std::vector<Edge>> adjacency;
484 std::vector<size_t> wireEdgesBegin;
488 std::vector<double> distance;
489 std::vector<uint64_t> indexInHeap;
490 std::vector<int8_t> colors;
491 std::vector<int> preds;
492 std::vector<Edge> predEdge;
494 int getOrAddNodeId(
const PathEndPoint &pep);
496 PacketConstraints constraints;
498 std::string checkReason;
501 bool packetsFailed =
true;
502 bool shareChannels =
false, idsApart =
false, splitShared =
false;
505 bool meetApart =
false;
508 bool treesMet =
false;
510 int columns = 0, rows = 0;
511 size_t relaxStep = 0;
512 llvm::DenseSet<TileID> crowdedTiles, cappedTiles;
525 TileOp
getTile(mlir::OpBuilder &builder,
int col,
int row);
527 SwitchboxOp
getSwitchbox(mlir::OpBuilder &builder,
int col,
int row);
528 ShimMuxOp
getShimMux(mlir::OpBuilder &builder,
int col);
533 return coordToSwitchbox.lookup(tile);
536 return coordToShimMux.lookup({col, 0});
547 static constexpr int maxIterations = 1000;
549 int maxCol = 0, maxRow = 0;
550 llvm::DenseMap<TileID, TileOp> coordToTile;
551 llvm::DenseMap<TileID, SwitchboxOp> coordToSwitchbox;
552 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
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
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