10#include "mlir/IR/IRMapping.h"
11#include "mlir/IR/OperationSupport.h"
17#define GEN_PASS_DEF_AIEIMPORTOVERLAY
18#include "aie/Dialect/AIE/Transforms/AIEPasses.h.inc"
22struct AIEImportOverlayPass
23 : xilinx::AIE::impl::AIEImportOverlayBase<AIEImportOverlayPass> {
24 LogicalResult importDevice(DeviceOp device, DeviceOp overlay) {
25 if (overlay == device || overlay.getOverlayAttr())
26 return device.emitOpError(
27 "requires an overlay without an overlay reference");
28 if (device.getDevice() != overlay.getDevice())
29 return device.emitOpError(
"and its overlay must use the same target");
31 OpBuilder builder(device.getContext());
32 auto equivalent = [&](Operation *source, Operation *dest) {
33 IRMapping values(mapping);
35 OwningOpRef<Operation *> normalized;
36 if (
auto flow = dyn_cast<PacketFlowOp>(source)) {
37 if (isa<PacketFlowOp>(dest)) {
38 normalized = dest->clone();
39 auto other = cast<PacketFlowOp>(*normalized);
40 other.setKeepPktHeaderAttr(flow.getKeepPktHeaderAttr());
41 other.setPriorityRouteAttr(flow.getPriorityRouteAttr());
45 return OperationEquivalence::isEquivalentTo(
47 [&](Value a, Value b) {
48 return success(values.lookupOrDefault(a) == b);
50 [&](Value a, Value b) { values.map(a, b); },
51 OperationEquivalence::IgnoreLocations |
52 OperationEquivalence::IgnoreDiscardableAttrs);
54 auto inherit = [&](Operation *source, Operation *dest) {
55 mapping.map(source->getResults(), dest->getResults());
56 if (
auto flow = dyn_cast<PacketFlowOp>(source)) {
57 auto other = cast<PacketFlowOp>(dest);
58 other.setKeepPktHeaderAttr(flow.getKeepPktHeaderAttr());
59 other.setPriorityRouteAttr(flow.getPriorityRouteAttr());
61 for (NamedAttribute attr : source->getDiscardableAttrs())
62 if (!dest->hasAttr(attr.getName()))
63 dest->setAttr(attr.getName(), attr.getValue());
65 for (TileOp tile : overlay.getOps<TileOp>()) {
66 builder.setInsertionPointToStart(device.getBody());
67 TileOp dest = TileOp::getOrCreate(builder, device, tile.colIndex(),
69 mapping.map(tile.getResult(), dest.getResult());
70 if (
auto id = tile->getAttr(
"controller_id")) {
71 if (
auto own = dest->getAttr(
"controller_id"); own && own !=
id)
72 return dest.emitOpError(
73 "has a different controller ID from its overlay");
74 dest->setAttr(
"controller_id",
id);
77 std::function<LogicalResult(Block &, Block &)> importBlock =
78 [&](Block &source, Block &dest) -> LogicalResult {
79 auto slot = dest.begin();
80 for (Operation &op : source.without_terminator()) {
84 if (isa<PacketRuleOp>(op) && slot != dest.end() && !isa<EndOp>(*slot)) {
85 if (!equivalent(&op, &*slot))
86 return slot->emitOpError(
87 "occupies a packet-rule slot required by its overlay");
88 inherit(&op, &*slot++);
91 bool container = isa<SwitchboxOp, ShimMuxOp, PacketRulesOp>(op);
92 Operation *match =
nullptr;
94 Operation *shape = op.cloneWithoutRegions();
95 for (Operation &candidate : dest.without_terminator()) {
96 if (candidate.getName() != op.getName())
98 Operation *other = candidate.cloneWithoutRegions();
99 bool same = equivalent(shape, other);
108 for (Operation &candidate : dest.without_terminator()) {
109 if (equivalent(&op, &candidate)) {
114 op.getAttrOfType<StringAttr>(SymbolTable::getSymbolAttrName());
115 if (name && name == candidate.getAttrOfType<StringAttr>(
116 SymbolTable::getSymbolAttrName()))
117 return candidate.emitOpError(
"conflicts with an overlay symbol ")
123 mapping.map(op.getResults(), match->getResults());
124 if (failed(importBlock(op.getRegion(0).front(),
125 match->getRegion(0).front())))
131 builder.setInsertionPoint(dest.getTerminator());
132 builder.clone(op, mapping);
137 if (failed(importBlock(*overlay.getBody(), *device.getBody())))
142 void runOnOperation()
override {
143 ModuleOp module = getOperation();
144 for (DeviceOp device : module.getOps<DeviceOp>()) {
145 auto ref = device.getOverlayAttr();
148 auto overlay =
module.lookupSymbol<DeviceOp>(ref.getValue());
150 device.emitOpError(
"references an unknown overlay device ") << ref;
151 return signalPassFailure();
153 if (failed(importDevice(device, overlay)))
154 return signalPassFailure();
160std::unique_ptr<OperationPass<ModuleOp>>
162 return std::make_unique<AIEImportOverlayPass>();
std::unique_ptr< mlir::OperationPass< mlir::ModuleOp > > createAIEImportOverlayPass()