195 DeviceOp device = getOperation();
196 const auto &targetModel = device.getTargetModel();
197 OpBuilder builder = OpBuilder::atBlockTerminator(device.getBody());
199 if (targetModel.getTargetArch() == AIEArch::AIE1)
203 llvm::MapVector<AIE::TileID, AIE::TileOp> tiles;
204 llvm::SmallSet<int, 1> occupiedCols;
205 for (
auto tile : device.getOps<AIE::TileOp>()) {
206 int colIndex = tile.colIndex();
207 int rowIndex = tile.rowIndex();
208 tiles[{colIndex, rowIndex}] = tile;
209 occupiedCols.insert(colIndex);
213 for (
int col : occupiedCols) {
214 builder.setInsertionPointToStart(device.getBody());
215 AIE::TileOp shimTile = TileOp::getOrCreate(builder, device,
col, 0);
217 if (clRouteShimCTRLToTCT ==
"all-tiles" ||
218 clRouteShimCTRLToTCT ==
"shim-only") {
220 SmallVector<AIE::TileOp> tilesOnCol;
221 for (
auto &[tId, tOp] : tiles) {
224 if (clRouteShimCTRLToTCT ==
"shim-only" && !tOp.isShimNOCorPLTile())
226 tilesOnCol.push_back(tOp);
230 builder, device, shimTile, AIE::WireBundle::South, tilesOnCol,
231 AIE::WireBundle::TileControl, 0, tileIDMap,
false);
233 if (clRouteShimDmaToTileCTRL) {
235 SmallVector<AIE::TileOp> tilesOnCol;
236 for (
auto &[tId, tOp] : tiles) {
239 tilesOnCol.push_back(tOp);
243 builder, device, shimTile, AIE::WireBundle::DMA, tilesOnCol,
244 AIE::WireBundle::TileControl, 0, tileIDMap,
true);
251 xilinx::AIE::WireBundle sourceBundle,
252 uint32_t sourceChannel, Value dest,
253 xilinx::AIE::WireBundle destBundle,
254 uint32_t destChannel,
255 mlir::BoolAttr keep_pkt_header =
nullptr,
256 mlir::BoolAttr ctrl_pkt_flow =
nullptr) {
257 OpBuilder::InsertionGuard guard(builder);
259 AIE::PacketFlowOp pktFlow =
260 AIE::PacketFlowOp::create(builder, builder.getUnknownLoc(), flowID++,
261 keep_pkt_header, ctrl_pkt_flow);
262 Region &r_pktFlow = pktFlow.getPorts();
263 Block *b_pktFlow = builder.createBlock(&r_pktFlow);
264 builder.setInsertionPointToStart(b_pktFlow);
265 AIE::PacketSourceOp::create(builder, builder.getUnknownLoc(), source,
266 sourceBundle, sourceChannel);
267 AIE::PacketDestOp::create(builder, builder.getUnknownLoc(), dest,
268 destBundle, destChannel);
269 AIE::EndOp::create(builder, builder.getUnknownLoc());
276 WireBundle shimWireBundle,
278 SmallVector<int> availableShimChans;
279 DenseMap<int, AIE::FlowOp> flowOpUsers;
280 const auto &targetModel = device.getTargetModel();
282 for (
auto user : shimTile.getResult().getUsers()) {
283 auto fOp = dyn_cast<AIE::FlowOp>(user);
286 if (isShimMM2S && fOp.getSource() == shimTile &&
287 fOp.getSourceBundle() == shimWireBundle)
288 flowOpUsers[fOp.getSourceChannel()] = fOp;
289 else if (!isShimMM2S && fOp.getDest() == shimTile &&
290 fOp.getDestBundle() == shimWireBundle)
291 flowOpUsers[fOp.getDestChannel()] = fOp;
293 int numShimChans = 0;
295 numShimChans = targetModel.getNumSourceShimMuxConnections(
296 shimTile.colIndex(), shimTile.rowIndex(), shimWireBundle);
298 numShimChans = targetModel.getNumDestShimMuxConnections(
299 shimTile.colIndex(), shimTile.rowIndex(), shimWireBundle);
300 for (
int i = 0; i < numShimChans; i++) {
301 if (!flowOpUsers.count(i))
302 availableShimChans.push_back(i);
305 return availableShimChans;
311 TileOp shimTile, WireBundle shimWireBundle,
312 SmallVector<AIE::TileOp> ctrlTiles,
313 WireBundle ctrlWireBundle,
315 DenseMap<TileID, int> tileIDMap,
317 int ctrlPktFlowID = 0;
318 auto rowToShimChanMap =
322 auto availableShimChans =
325 builder.setInsertionPoint(device.getBody()->getTerminator());
326 for (
auto tOp : ctrlTiles) {
327 if (tOp->hasAttr(
"controller_id"))
329 (
int)tOp->getAttrOfType<AIE::PacketInfoAttr>(
"controller_id")
332 ctrlPktFlowID = tileIDMap[{tOp.colIndex(), tOp.rowIndex()}];
334 if (!llvm::is_contained(availableShimChans,
335 rowToShimChanMap[tOp.rowIndex()])) {
337 "failed to generate column control overlay from shim dma to tile "
338 "ctrl ports, because some shim mm2s dma channels were reserved "
339 "from routing control packets.");
340 return signalPassFailure();
343 auto keep_pkt_header = builder.getBoolAttr(
true);
344 auto ctrl_pkt_flow = builder.getBoolAttr(
true);
347 builder, ctrlPktFlowID, shimTile, shimWireBundle,
348 rowToShimChanMap[tOp.rowIndex()], tOp, ctrlWireBundle,
349 coreOrMemChanId, keep_pkt_header, ctrl_pkt_flow);
352 coreOrMemChanId, shimTile, shimWireBundle,
353 rowToShimChanMap[tOp.rowIndex()],
354 keep_pkt_header, ctrl_pkt_flow);
358 if (shimWireBundle != WireBundle::DMA)
361 AIE::DMAChannelDir dir =
362 isShimMM2S ? AIE::DMAChannelDir::MM2S : AIE::DMAChannelDir::S2MM;
363 int chan = rowToShimChanMap[tOp.rowIndex()];
364 int col = shimTile.colIndex();
365 std::string dma_name =
"ctrlpkt";
366 dma_name +=
"_col" + std::to_string(
col);
367 dma_name += isShimMM2S ?
"_mm2s" :
"_s2mm";
368 dma_name +=
"_chan" + std::to_string(chan);
371 if (device.lookupSymbol(dma_name))
374 AIE::ShimDMAAllocationOp::create(
375 builder, builder.getUnknownLoc(), StringRef(dma_name),
376 shimTile.getResult(), dir, rowToShimChanMap[tOp.rowIndex()],
false,
383 WireBundle srcBundle,
384 int srcChan, TileOp destTile,
385 WireBundle destBundle,
387 AIE::PacketFlowOp result =
nullptr;
388 device.walk([&](AIE::PacketFlowOp fOp) {
389 for (
auto srcOp : fOp.getOps<AIE::PacketSourceOp>()) {
390 if (srcOp.getTile() == srcTile && srcOp.getBundle() == srcBundle &&
391 srcOp.channelIndex() == srcChan) {
396 for (
auto destOp : fOp.getOps<AIE::PacketDestOp>()) {
397 if (destOp.getTile() == destTile && destOp.getBundle() == destBundle &&
398 destOp.channelIndex() == destChan) {