MLIR-AIE
AIELowerCascadeFlows.cpp
Go to the documentation of this file.
1//===- AIELowerCascadeFlows.cpp ---------------------------------*- C++ -*-===//
2//
3// This file is licensed under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7// (c) Copyright 2024 Xilinx Inc.
8//
9//===----------------------------------------------------------------------===//
10
13
14#include "mlir/IR/Attributes.h"
15#include "mlir/Pass/Pass.h"
16
17#include "llvm/ADT/Twine.h"
18
19#define DEBUG_TYPE "aie-lower-cascade-flows"
20
21using namespace mlir;
22using namespace xilinx;
23using namespace xilinx::AIE;
24
26 : AIELowerCascadeFlowsBase<AIELowerCascadeFlowsPass> {
27 void getDependentDialects(DialectRegistry &registry) const override {
28 registry.insert<AIEDialect>();
29 }
30 void runOnOperation() override {
31 DeviceOp device = getOperation();
32 const auto &targetModel = device.getTargetModel();
33 OpBuilder builder = OpBuilder::atBlockTerminator(device.getBody());
34
35 std::set<TileOp> tilesWithCascadeFlow;
36 DenseMap<TileOp, WireBundle> cascadeInputsPerTile;
37 DenseMap<TileOp, WireBundle> cascadeOutputsPerTile;
38
39 // identify cascade_flows and what ports they use on each tile
40 for (auto cascadeFlow : device.getOps<CascadeFlowOp>()) {
41 // for each cascade flow
42 TileOp src = cascadeFlow.getSourceTileOp();
43 TileOp dst = cascadeFlow.getDestTileOp();
44 tilesWithCascadeFlow.insert(src);
45 tilesWithCascadeFlow.insert(dst);
46
47 if (targetModel.isSouth(src.getCol(), src.getRow(), dst.getCol(),
48 dst.getRow())) {
49 cascadeInputsPerTile[dst] = WireBundle::North;
50 cascadeOutputsPerTile[src] = WireBundle::South;
51 } else if (targetModel.isEast(src.getCol(), src.getRow(), dst.getCol(),
52 dst.getRow())) {
53 cascadeInputsPerTile[dst] = WireBundle::West;
54 cascadeOutputsPerTile[src] = WireBundle::East;
55 } else {
56 // TODO: remove when this pass supports routing
57 cascadeFlow.emitOpError(
58 "source tile must be to the North or West of the destination tile");
59 return;
60 }
61 }
62
63 // generate configure cascade ops
64 for (TileOp tile : tilesWithCascadeFlow) {
65 WireBundle inputDir;
66 if (cascadeInputsPerTile.find(tile) != cascadeInputsPerTile.end()) {
67 inputDir = cascadeInputsPerTile[tile];
68 } else {
69 inputDir = WireBundle::North;
70 }
71 WireBundle outputDir;
72 if (cascadeOutputsPerTile.find(tile) != cascadeOutputsPerTile.end()) {
73 outputDir = cascadeOutputsPerTile[tile];
74 } else {
75 outputDir = WireBundle::South;
76 }
77 builder.create<ConfigureCascadeOp>(builder.getUnknownLoc(), tile,
78 static_cast<CascadeDir>(inputDir),
79 static_cast<CascadeDir>(outputDir));
80 }
81
82 // erase CascadeFlowOps
83 SetVector<Operation *> opsToErase;
84 device.walk([&](Operation *op) {
85 if (isa<CascadeFlowOp>(op))
86 opsToErase.insert(op);
87 });
88 IRRewriter rewriter(&getContext());
89 for (auto it = opsToErase.rbegin(); it != opsToErase.rend(); ++it)
90 (*it)->erase();
91 }
92};
93
94std::unique_ptr<OperationPass<DeviceOp>> AIE::createAIELowerCascadeFlowsPass() {
95 return std::make_unique<AIELowerCascadeFlowsPass>();
96}
Include the generated interface declarations.
std::unique_ptr< mlir::OperationPass< DeviceOp > > createAIELowerCascadeFlowsPass()
PathEndPoint src
void getDependentDialects(DialectRegistry &registry) const override