-
Notifications
You must be signed in to change notification settings - Fork 183
Expand file tree
/
Copy pathAIEAssignLockIDs.cpp
More file actions
109 lines (95 loc) · 3.96 KB
/
AIEAssignLockIDs.cpp
File metadata and controls
109 lines (95 loc) · 3.96 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
//===- AIEAssignLockIDs.cpp -------------------------------------*- C++ -*-===//
//
// This file is licensed under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
// (c) Copyright 2022 Xilinx Inc.
//
//===----------------------------------------------------------------------===//
// This pass aims to assign lockIDs to AIE.lock operations. The lockID is
// numbered from the most recent AIE.lock within the same tile. If the lockID
// exceeds the number of locks on the tile, the pass generates an error and
// terminates. AIE.lock operations for different tiles are numbered
// independently. If there are existing lock IDs, this pass is idempotent
// and only assigns lock IDs to locks without an ID.
#include "aie/Dialect/AIE/IR/AIEDialect.h"
#include "aie/Dialect/AIE/Transforms/AIEPasses.h"
#include "mlir/Pass/Pass.h"
#include "llvm/ADT/DenseMap.h"
namespace xilinx::AIE {
#define GEN_PASS_DEF_AIEASSIGNLOCKIDS
#include "aie/Dialect/AIE/Transforms/AIEPasses.h.inc"
} // namespace xilinx::AIE
#define DEBUG_TYPE "aie-assign-lock-ids"
using namespace mlir;
using namespace xilinx;
using namespace xilinx::AIE;
struct AIEAssignLockIDsPass : xilinx::AIE::impl::AIEAssignLockIDsBase<AIEAssignLockIDsPass> {
void getDependentDialects(DialectRegistry ®istry) const override {
registry.insert<func::FuncDialect>();
registry.insert<AIEDialect>();
}
void runOnOperation() override {
DeviceOp device = getOperation();
OpBuilder rewriter = OpBuilder::atBlockTerminator(device.getBody());
// All of the lock ops on a tile, separated into ops which have been
// assigned to a lock, and ops which have not.
struct TileLockOps {
DenseSet<int> assigned;
SmallVector<LockOp> unassigned;
};
DenseMap<TileOp, TileLockOps> tileToLocks;
// Construct data structure storing locks by tile.
device.walk<WalkOrder::PreOrder>([&](LockOp lockOp) {
TileOp tileOp = lockOp.getTileOp();
if (lockOp.getLockID().has_value()) {
auto lockID = lockOp.getLockID().value();
auto iter = tileToLocks.find(tileOp);
if (iter == tileToLocks.end())
tileToLocks.insert({tileOp, {{lockID}, /* unassigned = */ {}}});
else {
if (iter->second.assigned.find(lockID) !=
iter->second.assigned.end()) {
auto diag = lockOp->emitOpError("is assigned to the same lock (")
<< lockID << ") as another op.";
diag.attachNote(tileOp.getLoc())
<< "tile has lock ops assigned to same lock.";
return signalPassFailure();
}
iter->second.assigned.insert(lockID);
}
} else {
auto iter = tileToLocks.find(tileOp);
if (iter == tileToLocks.end())
tileToLocks.insert({tileOp, {/* assigned = */ {}, {lockOp}}});
else
iter->second.unassigned.push_back(lockOp);
}
});
// IR mutation: assign locks to all unassigned lock ops.
for (auto [tileOp, locks] : tileToLocks) {
const auto locksPerTile =
getTargetModel(tileOp).getNumLocks(tileOp.getCol(), tileOp.getRow());
uint32_t nextID = 0;
for (auto lockOp : locks.unassigned) {
while (nextID < locksPerTile &&
(locks.assigned.find(nextID) != locks.assigned.end())) {
++nextID;
}
if (nextID == locksPerTile) {
mlir::InFlightDiagnostic diag =
lockOp->emitOpError("not allocated a lock.");
diag.attachNote(tileOp.getLoc()) << "because only " << locksPerTile
<< " locks available in this tile.";
return signalPassFailure();
}
lockOp.setLockIDAttr(rewriter.getI32IntegerAttr(nextID));
++nextID;
}
}
}
};
std::unique_ptr<OperationPass<DeviceOp>> AIE::createAIEAssignLockIDsPass() {
return std::make_unique<AIEAssignLockIDsPass>();
}