75 DeviceOp device = getOperation();
76 OpBuilder builder = OpBuilder::atBlockTerminator(device.getBody());
78 DenseMap<TileID, Operation *> tiles;
79 DenseMap<Operation *, CoreOp> cores;
80 DenseMap<Operation *, MemOp> mems;
81 DenseMap<Value, Value> buffers;
82 DenseMap<func::FuncOp, std::pair<int, int>> funcs;
85 for (
auto tile : device.getOps<TileOp>()) {
86 int colIndex = tile.colIndex();
87 int rowIndex = tile.rowIndex();
88 tiles[{colIndex, rowIndex}] = tile;
94 for (
auto callOp : device.getOps<func::CallOp>()) {
95 if (!callOp->getAttr(
"aie.x") || !callOp->getAttr(
"aie.y"))
98 SmallVector<Value, 4> callOperands(callOp.getArgOperands());
99 SmallVector<std::pair<MemRefType, int>, 4> coreBufTypes;
101 int colIndex = callOp->getAttrOfType<IntegerAttr>(
"aie.x").getInt();
102 int rowIndex = callOp->getAttrOfType<IntegerAttr>(
"aie.y").getInt();
105 if (!tiles[{colIndex, rowIndex}]) {
106 builder.setInsertionPointToStart(device.getBody());
108 TileOp::create(builder, callOp.getLoc(), colIndex, rowIndex);
109 tiles[{colIndex, rowIndex}] = tile;
111 Operation *tileOp = tiles[{colIndex, rowIndex}];
112 TileOp tile = cast<TileOp>(tileOp);
113 builder.setInsertionPointAfter(tileOp);
117 for (
unsigned i = 0; i < callOperands.size(); i++) {
118 Value operand = callOperands[i];
119 MemRefType t =
nullptr;
120 if (llvm::isa<MemRefType>(operand.getType())) {
121 t = llvm::cast<MemRefType>(operand.getType());
122 }
else if (operand.getType().isIntOrFloat()) {
124 int64_t shape[1] = {1};
125 t = MemRefType::get(shape, operand.getType());
128 assert(t &&
"Unsupported type!");
129 coreBufTypes.push_back({t, i});
130 BufferOp buf = BufferOp::create(
131 builder, callOp.getLoc(), t, tile,
nullptr,
134 buffers[callOperands[i]] = buf;
135 operand.replaceAllUsesWith(buf.getResult());
138 MemOp mem = MemOp::create(builder, callOp.getLoc(),
139 builder.getIndexType(), tile);
140 Region &r = mem.getBody();
141 Block *endBlock = builder.createBlock(&r);
144 builder.setInsertionPointToStart(endBlock);
145 EndOp::create(builder, callOp.getLoc());
150 if (CallOpInterface call =
151 dyn_cast<CallOpInterface>(callOp.getOperation())) {
152 Operation *callable = call.resolveCallable();
153 if (func::FuncOp
func = dyn_cast<func::FuncOp>(callable)) {
154 funcs[
func] = {colIndex, rowIndex};
158 builder.setInsertionPoint(callOp);
163 if (!cores[tileOp]) {
164 core = CoreOp::create(builder, callOp.getLoc(), tile);
165 Region &r = core.getBody();
166 currentBlock = builder.createBlock(&r);
167 builder.setInsertionPointToStart(currentBlock);
169 core = cores[tileOp];
170 currentBlock = &core.getBody().back();
171 builder.setInsertionPoint(currentBlock->getTerminator());
178 for (
auto pair : coreBufTypes) {
179 int operandID = pair.second;
180 Value arg =
func.getArgument(operandID);
181 Value buf = buffers[callOperands[operandID]];
182 if (arg.getType().isIntOrFloat()) {
183 assert(pair.first.getShape().size() == 1 &&
184 "Expected MemRefType of shape 1");
185 assert(pair.first.getShape()[0] == 1 &&
186 "Expected MemRefType of single element");
189 arith::ConstantIndexOp::create(builder, callOp.getLoc(), 0);
190 auto loadOp = memref::LoadOp::create(builder, callOp.getLoc(),
191 arg.getType(), buf, zero);
192 mapper.map(arg, loadOp);
194 mapper.map(arg, buf);
199 for (
auto &childOp :
func.getCallableRegion()->getOps()) {
201 if (
auto returnOp = dyn_cast<func::ReturnOp>(childOp))
204 builder.clone(childOp, mapper);
206 if (!cores[tileOp]) {
208 EndOp::create(builder, callOp.getLoc());
209 cores[tileOp] = core;
238 ConversionTarget target(getContext());
239 RewritePatternSet patterns(&getContext());
240 target.addLegalOp<DMAStartOp>();
241 target.addLegalOp<DMABDOp>();
242 target.addLegalOp<UseTokenOp>();
243 target.addLegalOp<NextBDOp>();
249 if (failed(applyPartialConversion(device, target, std::move(patterns))))