71 DeviceOp device = getOperation();
72 OpBuilder builder = OpBuilder::atBlockTerminator(device.getBody());
74 DenseMap<TileID, Operation *> tiles;
75 DenseMap<Operation *, CoreOp> cores;
76 DenseMap<Operation *, MemOp> mems;
77 DenseMap<Value, Value> buffers;
78 DenseMap<func::FuncOp, std::pair<int, int>> funcs;
81 for (
auto tile : device.getOps<TileOp>()) {
82 int colIndex = tile.colIndex();
83 int rowIndex = tile.rowIndex();
84 tiles[{colIndex, rowIndex}] = tile;
90 for (
auto callOp : device.getOps<func::CallOp>()) {
91 if (!callOp->getAttr(
"aie.x") || !callOp->getAttr(
"aie.y"))
94 SmallVector<Value, 4> callOperands(callOp.getArgOperands());
95 SmallVector<std::pair<MemRefType, int>, 4> coreBufTypes;
97 int colIndex = callOp->getAttrOfType<IntegerAttr>(
"aie.x").getInt();
98 int rowIndex = callOp->getAttrOfType<IntegerAttr>(
"aie.y").getInt();
101 if (!tiles[{colIndex, rowIndex}]) {
102 builder.setInsertionPointToStart(device.getBody());
104 builder.create<TileOp>(builder.getUnknownLoc(), colIndex, rowIndex);
105 tiles[{colIndex, rowIndex}] = tile;
107 Operation *tileOp = tiles[{colIndex, rowIndex}];
108 TileOp tile = dyn_cast<TileOp>(tileOp);
109 builder.setInsertionPointAfter(tileOp);
113 for (
unsigned i = 0; i < callOperands.size(); i++) {
114 Value operand = callOperands[i];
115 MemRefType t =
nullptr;
116 if (llvm::isa<MemRefType>(operand.getType())) {
117 t = llvm::cast<MemRefType>(operand.getType());
118 }
else if (operand.getType().isIntOrFloat()) {
120 int64_t shape[1] = {1};
121 t = MemRefType::get(shape, operand.getType());
124 assert(t &&
"Unsupported type!");
125 coreBufTypes.push_back({t, i});
126 BufferOp buf = builder.create<BufferOp>(
127 builder.getUnknownLoc(), t, tile,
nullptr,
130 buffers[callOperands[i]] = buf;
131 operand.replaceAllUsesWith(buf.getResult());
134 MemOp mem = builder.create<MemOp>(builder.getUnknownLoc(),
135 builder.getIndexType(), tile);
136 Region &r = mem.getBody();
137 Block *endBlock = builder.createBlock(&r);
140 builder.setInsertionPointToStart(endBlock);
141 builder.create<EndOp>(builder.getUnknownLoc());
146 if (CallOpInterface call =
147 dyn_cast<CallOpInterface>(callOp.getOperation())) {
148 Operation *callable = call.resolveCallable();
149 if (func::FuncOp func = dyn_cast<func::FuncOp>(callable)) {
150 funcs[func] = {colIndex, rowIndex};
154 builder.setInsertionPoint(callOp);
159 if (!cores[tileOp]) {
160 core = builder.create<CoreOp>(builder.getUnknownLoc(), tile);
161 Region &r = core.getBody();
162 currentBlock = builder.createBlock(&r);
163 builder.setInsertionPointToStart(currentBlock);
165 core = cores[tileOp];
166 currentBlock = &core.getBody().back();
167 builder.setInsertionPoint(currentBlock->getTerminator());
174 for (
auto pair : coreBufTypes) {
175 int operandID = pair.second;
176 Value arg = func.getArgument(operandID);
177 Value buf = buffers[callOperands[operandID]];
178 if (arg.getType().isIntOrFloat()) {
179 assert(pair.first.getShape().size() == 1 &&
180 "Expected MemRefType of shape 1");
181 assert(pair.first.getShape()[0] == 1 &&
182 "Expected MemRefType of single element");
184 Value zero = builder.create<arith::ConstantIndexOp>(
185 builder.getUnknownLoc(), 0);
186 auto loadOp = builder.create<memref::LoadOp>(
187 builder.getUnknownLoc(), arg.getType(), buf, zero);
188 mapper.map(arg, loadOp);
190 mapper.map(arg, buf);
195 for (
auto &childOp : func.getCallableRegion()->getOps()) {
197 if (
auto returnOp = dyn_cast<func::ReturnOp>(childOp))
200 builder.clone(childOp, mapper);
202 if (!cores[tileOp]) {
204 builder.create<EndOp>(builder.getUnknownLoc());
205 cores[tileOp] = core;
234 ConversionTarget target(getContext());
235 RewritePatternSet patterns(&getContext());
236 target.addLegalOp<DMAStartOp>();
237 target.addLegalOp<DMABDOp>();
238 target.addLegalOp<UseTokenOp>();
239 target.addLegalOp<NextBDOp>();
245 if (failed(applyPartialConversion(device, target, std::move(patterns))))