77 DeviceOp device = getOperation();
78 OpBuilder builder = OpBuilder::atBlockTerminator(device.getBody());
80 DenseMap<TileID, Operation *> tiles;
81 DenseMap<Operation *, CoreOp> cores;
82 DenseMap<Operation *, MemOp> mems;
83 DenseMap<Value, Value> buffers;
84 DenseMap<func::FuncOp, std::pair<int, int>> funcs;
87 for (
auto tile : device.getOps<TileOp>()) {
88 int colIndex = tile.colIndex();
89 int rowIndex = tile.rowIndex();
90 tiles[{colIndex, rowIndex}] = tile;
96 for (
auto callOp : device.getOps<func::CallOp>()) {
97 if (!callOp->getAttr(
"aie.x") || !callOp->getAttr(
"aie.y"))
100 SmallVector<Value, 4> callOperands(callOp.getArgOperands());
101 SmallVector<std::pair<MemRefType, int>, 4> coreBufTypes;
103 int colIndex = callOp->getAttrOfType<IntegerAttr>(
"aie.x").getInt();
104 int rowIndex = callOp->getAttrOfType<IntegerAttr>(
"aie.y").getInt();
107 if (!tiles[{colIndex, rowIndex}]) {
108 builder.setInsertionPointToStart(device.getBody());
109 TileOp tile = TileOp::create(builder, builder.getUnknownLoc(), colIndex,
111 tiles[{colIndex, rowIndex}] = tile;
113 Operation *tileOp = tiles[{colIndex, rowIndex}];
114 TileOp tile = dyn_cast<TileOp>(tileOp);
115 builder.setInsertionPointAfter(tileOp);
119 for (
unsigned i = 0; i < callOperands.size(); i++) {
120 Value operand = callOperands[i];
121 MemRefType t =
nullptr;
122 if (llvm::isa<MemRefType>(operand.getType())) {
123 t = llvm::cast<MemRefType>(operand.getType());
124 }
else if (operand.getType().isIntOrFloat()) {
126 int64_t shape[1] = {1};
127 t = MemRefType::get(shape, operand.getType());
130 assert(t &&
"Unsupported type!");
131 coreBufTypes.push_back({t, i});
132 BufferOp buf = BufferOp::create(
133 builder, builder.getUnknownLoc(), t, tile,
nullptr,
136 buffers[callOperands[i]] = buf;
137 operand.replaceAllUsesWith(buf.getResult());
140 MemOp mem = MemOp::create(builder, builder.getUnknownLoc(),
141 builder.getIndexType(), tile);
142 Region &r = mem.getBody();
143 Block *endBlock = builder.createBlock(&r);
146 builder.setInsertionPointToStart(endBlock);
147 EndOp::create(builder, builder.getUnknownLoc());
152 if (CallOpInterface call =
153 dyn_cast<CallOpInterface>(callOp.getOperation())) {
154 Operation *callable = call.resolveCallable();
155 if (func::FuncOp func = dyn_cast<func::FuncOp>(callable)) {
156 funcs[func] = {colIndex, rowIndex};
160 builder.setInsertionPoint(callOp);
165 if (!cores[tileOp]) {
166 core = CoreOp::create(builder, builder.getUnknownLoc(), tile);
167 Region &r = core.getBody();
168 currentBlock = builder.createBlock(&r);
169 builder.setInsertionPointToStart(currentBlock);
171 core = cores[tileOp];
172 currentBlock = &core.getBody().back();
173 builder.setInsertionPoint(currentBlock->getTerminator());
180 for (
auto pair : coreBufTypes) {
181 int operandID = pair.second;
182 Value arg = func.getArgument(operandID);
183 Value buf = buffers[callOperands[operandID]];
184 if (arg.getType().isIntOrFloat()) {
185 assert(pair.first.getShape().size() == 1 &&
186 "Expected MemRefType of shape 1");
187 assert(pair.first.getShape()[0] == 1 &&
188 "Expected MemRefType of single element");
190 Value zero = arith::ConstantIndexOp::create(
191 builder, builder.getUnknownLoc(), 0);
192 auto loadOp = memref::LoadOp::create(
193 builder, builder.getUnknownLoc(), arg.getType(), buf, zero);
194 mapper.map(arg, loadOp);
196 mapper.map(arg, buf);
201 for (
auto &childOp : func.getCallableRegion()->getOps()) {
203 if (
auto returnOp = dyn_cast<func::ReturnOp>(childOp))
206 builder.clone(childOp, mapper);
208 if (!cores[tileOp]) {
210 EndOp::create(builder, builder.getUnknownLoc());
211 cores[tileOp] = core;
240 ConversionTarget target(getContext());
241 RewritePatternSet patterns(&getContext());
242 target.addLegalOp<DMAStartOp>();
243 target.addLegalOp<DMABDOp>();
244 target.addLegalOp<UseTokenOp>();
245 target.addLegalOp<NextBDOp>();
251 if (failed(applyPartialConversion(device, target, std::move(patterns))))