587 ObjectFifoCreateOp op,
int share_direction,
592 if (op.getAieStream())
595 std::vector<BufferOp> buffers;
596 auto fifo = llvm::cast<AIEObjectFifoType>(op.getElemType());
597 auto elemType = llvm::cast<MemRefType>(fifo.getElementType());
598 int numElem = op.size();
599 int of_elem_index = 0;
608 auto fifoIn = linkOp->getInputObjectFifos()[0];
609 auto fifoOut = linkOp->getOutputObjectFifos()[0];
613 if (linkOp->isJoin()) {
615 if (op.name() != fifoOut.name())
617 }
else if (linkOp->isDistribute()) {
619 if (op.name() != fifoIn.name())
623 if (fifoOut.getInitValues().has_value()) {
624 if (fifoOut.name() != op.name())
628 auto fifoInType = llvm::cast<AIEObjectFifoType>(fifoIn.getElemType());
629 auto elemInType = llvm::cast<MemRefType>(fifoInType.getElementType());
630 int inSize = elemInType.getNumElements();
633 llvm::cast<AIEObjectFifoType>(fifoOut.getElemType());
635 llvm::cast<MemRefType>(fifoOutType.getElementType());
637 if (
int outSize = elemOutType.getNumElements(); inSize >= outSize) {
638 if (op.name() != fifoIn.name())
643 bool outHasPadding = fifoOut.getPadDimensions().has_value();
645 if (op.name() != fifoIn.name())
648 if (fifoOut.name() != op.name())
656 TileOp creation_tile;
657 auto consumerTileOp =
658 dyn_cast<TileOp>(op.getConsumerTiles()[0].getDefiningOp());
659 if (share_direction != 1)
660 creation_tile = op.getProducerTileOp();
662 creation_tile = consumerTileOp;
665 if (opAlloc.has_value()) {
666 TileOp delegate = opAlloc->getDelegateTileOp();
671 if ((prodShareDir == -1 || prodShareDir == 2) &&
672 (consShareDir == -1 || consShareDir == 2))
673 creation_tile = delegate;
675 opAlloc->emitOpError(
"objectfifo has no shared memory access to "
676 "delegate tile's memory module");
680 Operation *t =
nullptr;
681 auto dev = op->getParentOfType<DeviceOp>();
682 for (
auto tile_op : dev.getBody()->getOps<TileOp>()) {
683 t = tile_op.getOperation();
686 builder.setInsertionPointAfter(t);
687 for (
int i = 0; i < numElem; i++) {
689 mlir::ElementsAttr initValues =
nullptr;
690 if (!creation_tile.isShimTile()) {
691 if (op.getInitValues().has_value()) {
693 llvm::cast<mlir::ElementsAttr>(op.getInitValues().value()[i]);
696 auto elementType = elemType.getElementType();
698 DataLayout dataLayout = DataLayout::closest(op.getOperation());
699 int64_t elementBitWidth = dataLayout.getTypeSizeInBits(elementType);
701 auto totalSizeBytes = elemType.getNumElements() * elementBitWidth / 8;
702 auto &targetModel = dev.getTargetModel();
704 int maxDataMemorySize = 0;
705 if (creation_tile.isMemTile())
707 targetModel.getMemTileSize();
711 .getLocalMemorySize();
718 TileOp current_buf_allocation_tile =
721 if (creation_tile.isMemTile()) {
722 if (
static_cast<int>(currentUsedMemory + totalSizeBytes) >
726 std::vector<TileOp> neighborTiles;
727 int currentCol = creation_tile.getCol();
728 int currentRow = creation_tile.getRow();
731 if (currentCol > 0) {
733 currentCol - 1, currentRow);
735 int share_direction = 0;
737 (share_direction == 1 || share_direction == 2)) {
738 neighborTiles.push_back(leftTile);
743 if (currentCol < (targetModel.columns() - 1)) {
745 currentCol + 1, currentRow);
746 int share_direction = 0;
748 (share_direction == 1 || share_direction == 2)) {
749 neighborTiles.push_back(rightTile);
754 if (!neighborTiles.empty()) {
755 for (
auto &tile : neighborTiles) {
759 if (
static_cast<int>(neighborUsedMemory + totalSizeBytes) <=
763 current_buf_allocation_tile = tile;
770 auto buff = BufferOp::create(
771 builder, builder.getUnknownLoc(), elemType,
772 current_buf_allocation_tile,
773 builder.getStringAttr(op.name().str() +
"_buff_" +
774 std::to_string(of_elem_index)),
777 buffers.push_back(buff);
783 int joinDistribFactor = 1;
784 if (op.getRepeatCount().has_value())
785 repeatCount = op.getRepeatCount().value();
787 if (linkOp->getRepeatCount().has_value())
788 repeatCount = linkOp->getRepeatCount().value();
789 if (linkOp->isDistribute())
790 joinDistribFactor *= linkOp->getFifoOuts().size();
791 else if (linkOp->isJoin())
792 joinDistribFactor *= linkOp->getFifoIns().size();
796 builder, lockAnalysis, op, numElem, joinDistribFactor, creation_tile,
1087 ObjectFifoCreateOp op, DMAChannelDir channelDir,
1088 int channelIndex,
int lockMode,
1089 BDDimLayoutArrayAttr dims,
1090 BDPadLayoutArrayAttr padDimensions,
1091 std::optional<PacketInfoAttr> bdPacket,
1093 size_t numBlocks = op.size();
1097 auto fifo = llvm::cast<AIEObjectFifoType>(op.getElemType());
1098 auto elemType = llvm::cast<MemRefType>(fifo.getElementType());
1099 int lenOut = elemType.getNumElements();
1104 int repeatCount = 1;
1105 if (op.getRepeatCount().has_value())
1106 repeatCount = op.getRepeatCount().value();
1109 auto bdChainIterCount = op.getIterCount();
1113 ObjectFifoCreateOp target = op;
1114 bool isDistribute =
false;
1115 bool isJoin =
false;
1116 int extraOffset = 0;
1117 int joinDistribFactor = 1;
1118 int joinDistribLockIndex = 0;
1123 auto srcOffsets = linkOp->getSrcOffsets();
1124 auto dstOffsets = linkOp->getDstOffsets();
1126 if (linkOp->getRepeatCount().has_value())
1127 if (linkOp->getInputObjectFifos()[0] == op) {
1128 acqNum *= linkOp->getRepeatCount().value();
1129 relNum *= linkOp->getRepeatCount().value();
1132 if (linkOp->isJoin()) {
1136 joinDistribFactor *= linkOp->getFifoIns().size();
1139 for (
auto fifoIn : linkOp->getInputObjectFifos()) {
1140 if (fifoIn.name() == op.name())
1144 extraOffset = *getConstantIntValue(srcOffsets[i]);
1145 lenOut = linkOp->getJoinTransferLengths()[i];
1146 joinDistribLockIndex = i;
1148 }
else if (linkOp->isDistribute()) {
1150 isDistribute =
true;
1152 joinDistribFactor *= linkOp->getFifoOuts().size();
1155 for (
auto fifoOut : linkOp->getOutputObjectFifos()) {
1156 if (fifoOut.name() == op.name())
1160 extraOffset = *getConstantIntValue(dstOffsets[i]);
1161 lenOut = linkOp->getDistributeTransferLengths()[i];
1162 joinDistribLockIndex = i;
1167 llvm::cast<AIEObjectFifoType>(target.getElemType());
1168 auto targetElemType =
1169 llvm::cast<MemRefType>(targetFifo.getElementType());
1170 int targetLen = targetElemType.getNumElements();
1174 if (targetLen >= lenOut)
1181 numBlocks = target.size();
1187 Operation *producerDMA =
nullptr;
1188 for (
auto dmaOp : device.getOps<MemTileDMAOp>()) {
1189 if (dmaOp.getTile() == target.getProducerTile()) {
1190 producerDMA = dmaOp.getOperation();
1196 TileOp objFifoTileOp = target.getProducerTileOp();
1197 if (producerDMA ==
nullptr) {
1198 OpBuilder::InsertionGuard g(builder);
1199 builder.setInsertionPoint(device.getBody()->getTerminator());
1201 MemTileDMAOp::create(builder, builder.getUnknownLoc(), objFifoTileOp);
1203 OpBuilder::InsertionGuard g(builder);
1204 builder.setInsertionPointToStart(&newDMAOp.getRegion().emplaceBlock());
1205 EndOp::create(builder, builder.getUnknownLoc());
1207 producerDMA = newDMAOp.getOperation();
1211 Block *lastDmaBlock = endBlock->getSinglePredecessor();
1212 Block *dmaBlock = builder.createBlock(endBlock);
1213 Block *bdBlock = builder.createBlock(endBlock);
1216 builder.setInsertionPointToStart(dmaBlock);
1220 bool isBdChainMode =
false;
1221 if (bdChainIterCount.has_value()) {
1222 taskCount = bdChainIterCount.value() - 1;
1223 isBdChainMode =
true;
1225 DMAStartOp::create(builder, builder.getUnknownLoc(), channelDir,
1226 channelIndex, taskCount, bdBlock, endBlock);
1227 if (lastDmaBlock !=
nullptr)
1228 lastDmaBlock->getTerminator()->setSuccessor(dmaBlock, 1);
1232 Block *curr = bdBlock;
1233 size_t elemIndex = 0;
1234 size_t lockIndex = 0;
1235 size_t totalBlocks = 0;
1236 bool distribOrJoin =
false;
1238 for (
size_t i = 0; i < numBlocks; i++) {
1241 for (
int r = 0; r < repeatCount * joinDistribFactor; r++) {
1242 if (totalBlocks == numBlocks * repeatCount * joinDistribFactor - 1) {
1245 if (isBdChainMode) {
1246 succ = builder.createBlock(endBlock);
1249 builder.setInsertionPointToStart(succ);
1250 EndOp::create(builder, builder.getUnknownLoc());
1255 succ = builder.createBlock(endBlock);
1258 builder.setInsertionPointToStart(curr);
1260 if (isDistribute || isJoin) {
1261 distribOrJoin =
true;
1264 offset = *getConstantIntValue(linkOp->getDstOffsets()[r]);
1265 lenOut = linkOp->getDistributeTransferLengths()[r];
1267 offset = *getConstantIntValue(linkOp->getSrcOffsets()[r]);
1268 lenOut = linkOp->getJoinTransferLengths()[r];
1270 lockIndex = r % joinDistribFactor;
1272 offset = extraOffset;
1273 lockIndex = joinDistribLockIndex;
1276 lockIndex = elemIndex;
1279 createBdBlock<BufferOp>(builder, target, lockMode, acqNum, relNum,
1281 lenOut, channelDir, lockIndex, succ, dims,
1282 padDimensions, bdPacket, state, distribOrJoin);
1436 std::set<TileOp> objectFifoTiles,
1438 for (
auto coreOp : device.getOps<CoreOp>()) {
1439 if (objectFifoTiles.count(coreOp.getTileOp()) <= 0)
1441 if (objectFifoTiles.count(coreOp.getTileOp()) > 0) {
1447 std::map<std::pair<ObjectFifoCreateOp, ObjectFifoPort>,
int> fifoSizes;
1450 std::map<std::pair<ObjectFifoCreateOp, ObjectFifoPort>,
1453 std::map<std::pair<ObjectFifoCreateOp, ObjectFifoPort>,
1458 builder.setInsertionPointToStart(&(coreOp.getBody().front()));
1459 Value initVal = arith::ConstantOp::create(
1460 builder, builder.getUnknownLoc(), builder.getI32IntegerAttr(0));
1461 coreOp.walk([&](ObjectFifoAcquireOp acqOp) {
1462 ObjectFifoCreateOp op = acqOp.getObjectFifo();
1463 ObjectFifoPort
port = acqOp.getPort();
1464 if (fifoSizes.find({op, port}) == fifoSizes.end()) {
1465 fifoSizes[{op, port}] = op.size();
1466 auto indexOp = arith::ConstantOp::create(
1467 builder, initVal.getLoc(), builder.getIndexAttr(index));
1468 globalIndices[{op,
port}] = indexOp;
1471 arith::ConstantOp::create(builder, indexOp.getLoc(),
1472 builder.getI32IntegerAttr(op.size()));
1473 constantSizes[{op,
port}] = size;
1476 builder.setInsertionPoint(coreOp);
1478 MemRefType::get(SmallVector<int64_t>{(int64_t)fifoSizes.size()},
1479 builder.getI32Type());
1480 auto globalNextIndex = BufferOp::create(
1481 builder, builder.getUnknownLoc(), memrefTy, coreOp.getTile(),
1486 for (
auto i : constantSizes) {
1487 builder.setInsertionPointAfter(i.second);
1488 memref::StoreOp::create(
1489 builder, builder.getUnknownLoc(), initVal, globalNextIndex,
1490 ValueRange(ArrayRef({globalIndices[i.first].getResult()})));
1499 WalkResult res = coreOp.walk([&](Operation *op) {
1500 if (
auto relOp = dyn_cast<ObjectFifoReleaseOp>(op)) {
1501 ObjectFifoCreateOp createOp = relOp.getObjectFifo();
1502 ObjectFifoPort
port = relOp.getPort();
1503 updateGlobalNextIndex(builder, relOp, globalNextIndex,
1504 globalIndices[{createOp,
port}],
1505 constantSizes[{createOp,
port}]);
1507 if (
auto acqOp = dyn_cast<ObjectFifoAcquireOp>(op)) {
1508 std::vector<ObjectFifoSubviewAccessOp> accessOps;
1509 for (
auto u : acqOp->getUsers())
1510 if (
auto accessOp = dyn_cast<ObjectFifoSubviewAccessOp>(u))
1511 accessOps.push_back(accessOp);
1513 for (
auto accessOp : accessOps) {
1514 ObjectFifoCreateOp createOp = acqOp.getObjectFifo();
1515 ObjectFifoPort
port = acqOp.getPort();
1518 if (fifoSizes[{createOp,
port}] == 1)
1519 return WalkResult::advance();
1522 builder.setInsertionPointAfter(accessOp);
1523 auto switchIndexAsInteger = memref::LoadOp::create(
1524 builder, builder.getUnknownLoc(), globalNextIndex,
1526 ArrayRef({globalIndices[{createOp,
port}].getResult()})));
1527 auto switchIndex = arith::IndexCastOp::create(
1528 builder, builder.getUnknownLoc(), builder.getIndexType(),
1529 switchIndexAsInteger);
1530 unsigned caseRegionCounts = fifoSizes[{createOp,
port}];
1531 SmallVector<int64_t, 4> caseValues;
1532 for (
int i = 0; i < fifoSizes[{createOp,
port}]; ++i) {
1533 caseValues.push_back(i);
1536 DenseI64ArrayAttr::get(builder.getContext(), caseValues);
1537 auto switchOp = scf::IndexSwitchOp::create(
1538 builder, switchIndex.getLoc(),
1540 switchIndex, cases, caseRegionCounts);
1542 builder.createBlock(&switchOp.getDefaultRegion());
1543 auto bufferIndex = (accessOp.getIndex()) % createOp.size();
1544 builder.setInsertionPointToStart(&(switchOp.getDefaultBlock()));
1545 scf::YieldOp::create(
1546 builder, builder.getUnknownLoc(),
1548 for (
int i = 0; i < fifoSizes[{createOp,
port}]; ++i) {
1550 builder.createBlock(&switchOp.getCaseRegions()[i]);
1551 builder.setInsertionPoint(&switchOp.getCaseBlock(i),
1552 switchOp.getCaseBlock(i).begin());
1553 int bufferToBeAccesed =
1554 (accessOp.getIndex() + i) % fifoSizes[{createOp,
port}];
1555 scf::YieldOp::create(
1556 builder, switchOp.getCaseRegions()[i].getLoc(),
1563 accessOp.getOutput().replaceAllUsesWith(switchOp.getResult(0));
1566 return WalkResult::advance();
1568 if (res.wasInterrupted())
1842 DeviceOp device = getOperation();
1850 OpBuilder builder = OpBuilder::atBlockTerminator(device.getBody());
1851 auto ctx = device->getContext();
1852 auto producerWireType = WireBundle::DMA;
1853 auto consumerWireType = WireBundle::DMA;
1857 if (failed(verifyObjectFifoLinks(device)))
1858 return signalPassFailure();
1866 std::vector<ObjectFifoCreateOp> createFifoOps;
1867 auto range = device.getOps<ObjectFifoCreateOp>();
1868 createFifoOps.insert(createFifoOps.end(), range.begin(), range.end());
1869 for (
auto createOp : createFifoOps) {
1870 std::vector<ObjectFifoCreateOp> splitConsumerFifos;
1871 int consumerIndex = 0;
1872 int consumerDepth = createOp.size();
1873 ArrayRef<BDDimLayoutArrayAttr> consumerDims =
1874 createOp.getDimensionsFromStreamPerConsumer();
1878 if (
int share_direction = 0;
1879 !requiresDMAs(createOp, share_direction, state)) {
1883 for (
auto consumerTile : createOp.getConsumerTiles()) {
1884 auto consumerTileOp = dyn_cast<TileOp>(consumerTile.getDefiningOp());
1886 if (isa<ArrayAttr>(createOp.getElemNumber())) {
1888 consumerDepth = createOp.size(consumerIndex + 1);
1890 consumerDepth = findObjectFifoSize(device, consumerTileOp, createOp);
1893 builder.setInsertionPointAfter(createOp);
1894 auto datatype = llvm::cast<AIEObjectFifoType>(createOp.getElemType());
1895 auto consumerObjFifoSize =
1896 builder.getIntegerAttr(builder.getI32Type(), consumerDepth);
1898 std::string consumerFifoName;
1899 if (createOp.getConsumerTiles().size() > 1) {
1900 consumerFifoName = createOp.name().str() +
"_" +
1901 std::to_string(consumerIndex) +
"_cons";
1903 consumerFifoName = createOp.name().str() +
"_cons";
1905 BDDimLayoutArrayAttr emptyDims =
1906 BDDimLayoutArrayAttr::get(builder.getContext(), {});
1907 BDDimLayoutArrayAttr singletonFromStreamDims =
1908 BDDimLayoutArrayAttr::get(
1909 builder.getContext(),
1910 ArrayRef<BDDimLayoutAttr>{consumerDims[consumerIndex]});
1911 BDDimLayoutArrayArrayAttr fromStreamDims =
1912 BDDimLayoutArrayArrayAttr::get(builder.getContext(),
1913 singletonFromStreamDims);
1915 ObjectFifoCreateOp consumerFifo = createObjectFifo(
1916 builder, datatype, consumerFifoName, consumerTile, consumerTile,
1917 consumerObjFifoSize, emptyDims, fromStreamDims);
1918 if (createOp.getDisableSynchronization())
1919 consumerFifo.setDisableSynchronization(
true);
1922 if (
auto bdChainIterCount = createOp.getIterCount()) {
1923 consumerFifo.setIterCountAttr(
1924 builder.getI32IntegerAttr(*bdChainIterCount));
1926 replaceSplitFifo(createOp, consumerFifo, consumerTileOp);
1927 if (createOp.getAieStream()) {
1928 int streamEnd = createOp.getAieStream().value();
1929 if (streamEnd > 0) {
1930 consumerFifo->setAttr(
"aie_stream",
1931 builder.getI32IntegerAttr(streamEnd));
1932 consumerFifo->setAttr(
1934 builder.getI32IntegerAttr(createOp.getAieStreamPort().value()));
1936 if (streamEnd == 1) {
1937 createOp->removeAttr(
"aie_stream");
1938 createOp->removeAttr(
"aie_stream_port");
1943 if (consumerTile.getDefiningOp<TileOp>().isShimTile())
1944 detectExternalBuffers(device, createOp, consumerFifo, consumerTile,
1948 splitConsumerFifos.push_back(consumerFifo);
1951 if (
auto linkOp = getOptionalLinkOp(createOp))
1952 for (ObjectFifoCreateOp fifoIn : linkOp->getInputObjectFifos())
1953 if (fifoIn.name() == createOp.name() &&
1954 consumerTile == *linkOp->getOptionalSharedTile())
1955 if (failed(SymbolTable::replaceAllSymbolUses(
1956 createOp, consumerFifo.name(), linkOp->getOperation())))
1957 llvm::report_fatal_error(
"unable to update all symbol uses");
1962 if (!splitConsumerFifos.empty()) {
1963 state.
splitFifos.emplace_back(createOp, splitConsumerFifos);
1973 for (
auto createOp : device.getOps<ObjectFifoCreateOp>()) {
1975 int share_direction = 0;
1976 bool shared = !requiresDMAs(createOp, share_direction, state);
1980 objectFifoTiles.insert(createOp.getProducerTileOp());
1981 for (
auto consumerTile : createOp.getConsumerTiles()) {
1982 auto consumerTileOp = dyn_cast<TileOp>(consumerTile.getDefiningOp());
1983 objectFifoTiles.insert(consumerTileOp);
1988 if (createOp.getProducerTileOp().isShimTile())
1989 detectExternalBuffers(device, createOp, createOp,
1990 createOp.getProducerTile(), state);
1994 createObjectFifoElements(builder, lockAnalysis, createOp,
1995 share_direction, state);
1997 if (isa<ArrayAttr>(createOp.getElemNumber()))
1998 createOp.setElemNumberAttr(
1999 builder.getI32IntegerAttr(createOp.size()));
2001 if (!createOp.getInitValues().has_value()) {
2003 int prodMaxAcquire = findObjectFifoSize(
2004 device, createOp.getProducerTileOp(), createOp);
2005 createOp.setElemNumberAttr(
2006 builder.getI32IntegerAttr(prodMaxAcquire));
2009 createObjectFifoElements(builder, lockAnalysis, createOp,
2010 share_direction, state);
2021 auto crossTileInfos = analyzeCrossTileFIFOBuffers(state);
2024 std::map<ObjectFifoCreateOp, int> fifo_dma_channel_index;
2027 assignDMAChannelIndices(dmaAnalysis, crossTileInfos, fifo_dma_channel_index,
2030 assignDMAChannelIndices(dmaAnalysis, crossTileInfos, fifo_dma_channel_index,
2033 int packetID = getStartPacketID(device);
2034 for (
auto &[producer, consumers] : state.
splitFifos) {
2035 int producerChanIndex = -1;
2037 PacketFlowOp packetflow;
2038 if (producer.getAieStream()) {
2039 int prodStreamEnd = producer.getAieStream().value();
2040 if (prodStreamEnd == 0 || prodStreamEnd == 2) {
2041 producerChanIndex = producer.getAieStreamPort().value();
2042 producerChan = {DMAChannelDir::MM2S, producerChanIndex};
2047 producerChanIndex = fifo_dma_channel_index[producer];
2048 if (producerChanIndex == -1) {
2049 producer.getProducerTileOp().emitOpError(
2050 "number of output DMA channel exceeded!");
2051 return signalPassFailure();
2053 producerChan = {DMAChannelDir::MM2S, producerChanIndex};
2054 std::optional<PacketInfoAttr> bdPacket = {};
2055 if (clPacketSwObjectFifos) {
2056 if (packetID > 31) {
2057 device.emitOpError(
"max number of packet IDs reached");
2058 return signalPassFailure();
2060 bdPacket = {AIE::PacketInfoAttr::get(ctx, 0,
2064 createDMA(device, builder, producer, producerChan.direction,
2065 producerChan.channel, 0, producer.getDimensionsToStreamAttr(),
2066 producer.getPadDimensionsAttr(), bdPacket, state);
2069 builder.setInsertionPoint(device.getBody()->getTerminator());
2070 if (producer.getProducerTileOp().isShimTile())
2071 createObjectFifoAllocationInfo(
2072 builder, ctx, producer, producer.getProducerTileOp(),
2073 producerChan.direction, producerChan.channel, producer.getPlio(),
2076 if (clPacketSwObjectFifos) {
2078 builder.setInsertionPointAfter(producer);
2079 packetflow = builder.create<PacketFlowOp>(
2080 builder.getUnknownLoc(),
2081 builder.getIntegerAttr(builder.getI8Type(), bdPacket->getPktId()),
2084 OpBuilder::InsertionGuard g(builder);
2085 builder.setInsertionPointToStart(
2086 &packetflow.getRegion().emplaceBlock());
2087 builder.create<EndOp>(builder.getUnknownLoc());
2092 for (
auto consumer : consumers) {
2094 int consumerChanIndex = -1;
2096 if (consumer.getAieStream()) {
2097 int consStreamEnd = consumer.getAieStream().value();
2098 if (consStreamEnd == 1 || consStreamEnd == 2) {
2099 consumerChanIndex = consumer.getAieStreamPort().value();
2100 consumerChan = {DMAChannelDir::S2MM, consumerChanIndex};
2105 consumerChanIndex = fifo_dma_channel_index[consumer];
2106 if (consumerChanIndex == -1) {
2107 consumer.getProducerTileOp().emitOpError(
2108 "number of input DMA channel exceeded!");
2109 return signalPassFailure();
2111 consumerChan = {DMAChannelDir::S2MM, consumerChanIndex};
2112 BDDimLayoutArrayAttr consumerDims =
2113 consumer.getDimensionsFromStreamPerConsumer()[0];
2114 createDMA(device, builder, consumer, consumerChan.direction,
2115 consumerChan.channel, 1, consumerDims,
nullptr, {}, state);
2118 builder.setInsertionPoint(device.getBody()->getTerminator());
2119 if (!consumer.getAieStream()) {
2121 builder.setInsertionPoint(device.getBody()->getTerminator());
2122 if (consumer.getProducerTileOp().isShimTile())
2123 createObjectFifoAllocationInfo(
2124 builder, ctx, producer, consumer.getProducerTileOp(),
2125 consumerChan.direction, consumerChan.channel,
2126 producer.getPlio(), {});
2129 if (clPacketSwObjectFifos) {
2130 builder.setInsertionPointToStart(&packetflow.getPorts().front());
2131 builder.create<PacketDestOp>(builder.getUnknownLoc(),
2132 consumer.getProducerTile(),
2133 WireBundle::DMA, consumerChan.channel);
2138 if (producer.getPlio()) {
2139 producerWireType = producer.getProducerTileOp().isShimTile()
2142 consumerWireType = consumer.getProducerTileOp().isShimTile()
2146 producerWireType = WireBundle::DMA;
2147 consumerWireType = WireBundle::DMA;
2148 if (producer.getAieStream()) {
2149 int prodStreamEnd = producer.getAieStream().value();
2150 if (prodStreamEnd == 0 || prodStreamEnd == 2)
2151 producerWireType = WireBundle::Core;
2153 if (consumer.getAieStream()) {
2154 int consumerStreamEnd = consumer.getAieStream().value();
2155 if (consumerStreamEnd == 1 || consumerStreamEnd == 2)
2156 consumerWireType = WireBundle::Core;
2160 if (!clPacketSwObjectFifos) {
2162 builder.setInsertionPointAfter(producer);
2163 FlowOp::create(builder, builder.getUnknownLoc(),
2164 producer.getProducerTile(), producerWireType,
2165 producerChan.channel, consumer.getProducerTile(),
2166 consumerWireType, consumerChan.channel);
2170 if (clPacketSwObjectFifos) {
2171 builder.setInsertionPointToStart(&packetflow.getPorts().front());
2172 PacketSourceOp::create(builder, builder.getUnknownLoc(),
2173 producer.getProducerTile(), WireBundle::DMA,
2174 producerChan.channel);
2181 if (clDynamicObjectFifos) {
2182 if (failed(dynamicGlobalObjectFifos(device, builder, objectFifoTiles,
2184 return signalPassFailure();
2186 std::set<TileOp> dynamicTiles;
2187 std::set<TileOp> unrollTiles;
2188 for (
auto c : device.getOps<CoreOp>()) {
2189 TileOp t = c.getTileOp();
2190 if (objectFifoTiles.count(t) > 0) {
2191 if (c.getDynamicObjfifoLowering().has_value()) {
2192 if (c.getDynamicObjfifoLowering().value())
2193 dynamicTiles.insert(t);
2195 unrollTiles.insert(t);
2197 unrollTiles.insert(t);
2202 dynamicGlobalObjectFifos(device, builder, dynamicTiles, state)))
2203 return signalPassFailure();
2204 if (failed(unrollForLoops(device, builder, unrollTiles)))
2205 return signalPassFailure();
2211 for (
auto coreOp : device.getOps<CoreOp>()) {
2212 DenseMap<ObjectFifoAcquireOp, std::vector<BufferOp *>>
2215 DenseMap<std::pair<ObjectFifoCreateOp, int>, std::vector<int>>
2219 DenseMap<std::pair<ObjectFifoCreateOp, int>,
2220 std::vector<ObjectFifoReleaseOp>>
2223 DenseMap<std::pair<ObjectFifoCreateOp, int>,
int>
2226 DenseMap<std::pair<ObjectFifoCreateOp, int>,
int>
2233 WalkResult res = coreOp.walk([&](ObjectFifoReleaseOp releaseOp) {
2234 builder.setInsertionPointAfter(releaseOp);
2235 ObjectFifoCreateOp op = releaseOp.getObjectFifo();
2236 auto port = releaseOp.getPort();
2237 auto portNum =
port == ObjectFifoPort::Produce ? 0 : 1;
2238 auto core = releaseOp->getParentOfType<CoreOp>();
2240 if (
auto linkOp = getOptionalLinkOp(op)) {
2241 if (core.getTile() == *linkOp->getOptionalSharedTile()) {
2242 releaseOp->emitOpError(
"currently cannot access objectFifo used in "
2243 "ObjectFifoLinkOp");
2244 return WalkResult::interrupt();
2249 if (op.getAieStream().has_value()) {
2250 int streamEnd = op.getAieStream().value();
2251 if (streamEnd == 2 || streamEnd == portNum)
2252 releaseOp->emitOpError(
"cannot release from objectfifo stream "
2254 return WalkResult::interrupt();
2258 updateAndReturnIndex(relPerFifo, {op, portNum});
2261 int numLocks = releaseOp.relNumber();
2263 if (op.getRepeatCount().has_value())
2264 numLocks *= op.getRepeatCount().value();
2265 createUseLocks(builder, op,
port, relPerFifo, numLocks,
2266 LockAction::Release, state);
2269 if (releaseOps.find({op, portNum}) != releaseOps.end()) {
2270 releaseOps[{op, portNum}].push_back(releaseOp);
2272 std::vector release = {releaseOp};
2273 releaseOps[{op, portNum}] = release;
2275 return WalkResult::advance();
2277 if (res.wasInterrupted())
2278 return signalPassFailure();
2283 res = coreOp.walk([&](ObjectFifoAcquireOp acquireOp) {
2284 ObjectFifoCreateOp op = acquireOp.getObjectFifo();
2285 builder.setInsertionPointAfter(acquireOp);
2286 auto port = acquireOp.getPort();
2287 auto portNum =
port == ObjectFifoPort::Produce ? 0 : 1;
2288 auto core = acquireOp->getParentOfType<CoreOp>();
2290 auto linkOp = getOptionalLinkOp(op);
2292 if (core.getTile() == *linkOp->getOptionalSharedTile()) {
2293 acquireOp->emitOpError(
"currently cannot access objectFifo used in "
2294 "ObjectFifoLinkOp");
2295 return WalkResult::interrupt();
2300 if (op.getAieStream().has_value()) {
2301 int streamEnd = op.getAieStream().value();
2302 if (streamEnd == 2 || streamEnd == portNum)
2303 acquireOp->emitOpError(
"cannot acquire from objectfifo stream "
2305 return WalkResult::interrupt();
2309 int start = updateAndReturnIndex(
2310 acqPerFifo, {op, portNum});
2317 for (std::vector<ObjectFifoReleaseOp>::iterator relOp =
2318 releaseOps[{op, portNum}].begin();
2319 relOp != releaseOps[{op, portNum}].end();) {
2320 bool erased =
false;
2321 Operation *acqBlockDefOp = acquireOp.getOperation();
2323 Operation *relBlockDefOp = (*relOp).getOperation();
2325 if (acqBlockDefOp->getBlock() == relBlockDefOp->getBlock()) {
2326 if (relBlockDefOp->isBeforeInBlock(acqBlockDefOp)) {
2327 numRel += (*relOp).relNumber();
2328 relOp = releaseOps[{op, portNum}].erase(relOp);
2335 }
while ((relBlockDefOp = relBlockDefOp->getParentOp()) &&
2336 !isa<DeviceOp>(relBlockDefOp) && !erased);
2337 }
while ((acqBlockDefOp = acqBlockDefOp->getParentOp()) &&
2338 !isa<DeviceOp>(acqBlockDefOp) && !erased);
2344 std::vector<int> acquiredIndices;
2345 if (!acquiresPerFifo[{op, portNum}].empty()) {
2348 acquiredIndices = acquiresPerFifo[{op, portNum}];
2350 if (
static_cast<size_t>(numRel) > acquiredIndices.size()) {
2351 acquireOp->emitOpError(
"cannot release more elements than are "
2352 "already acquired");
2353 return WalkResult::interrupt();
2355 for (
int i = 0; i < numRel; i++)
2356 acquiredIndices.erase(acquiredIndices.begin());
2360 int numLocks = acquireOp.acqNumber();
2361 int alreadyAcq = acquiredIndices.size();
2363 if (numLocks > alreadyAcq)
2364 numCreate = numLocks - alreadyAcq;
2369 if (op.getRepeatCount().has_value())
2370 numCreate *= op.getRepeatCount().value();
2372 auto dev = op->getParentOfType<DeviceOp>();
2373 if (
auto &targetArch = dev.getTargetModel();
2374 targetArch.getTargetArch() == AIEArch::AIE1)
2375 createUseLocks(builder, op,
port, acqPerFifo, numCreate,
2376 LockAction::Acquire, state);
2378 createUseLocks(builder, op,
port, acqPerFifo, numCreate,
2379 LockAction::AcquireGreaterEqual, state);
2383 ObjectFifoCreateOp target = op;
2389 for (
int i = 0; i < numCreate; i++) {
2390 acquiredIndices.push_back(start);
2391 start = (start + 1) % op.size();
2393 std::vector<BufferOp *> subviewRefs;
2394 subviewRefs.reserve(acquiredIndices.size());
2395 for (
auto index : acquiredIndices)
2398 subviews[acquireOp] = subviewRefs;
2399 acquiresPerFifo[{op, portNum}] = acquiredIndices;
2401 return WalkResult::advance();
2403 if (res.wasInterrupted())
2404 return signalPassFailure();
2409 res = coreOp.walk([&](ObjectFifoSubviewAccessOp accessOp) {
2410 auto acqOp = accessOp.getSubview().getDefiningOp<ObjectFifoAcquireOp>();
2411 if (ObjectFifoCreateOp op = acqOp.getObjectFifo()) {
2412 if (
auto linkOp = getOptionalLinkOp(op); linkOp.has_value()) {
2413 if (!linkOp->isDistribute() && !linkOp->isJoin()) {
2414 for (
auto consumerTile : op.getConsumerTiles()) {
2415 if (
auto consumerTileOp =
2416 dyn_cast<TileOp>(consumerTile.getDefiningOp())) {
2417 int share_dir_value = 0;
2418 bool sharing = isSharedMemory(
2419 op.getProducerTileOp(), consumerTileOp, &share_dir_value);
2421 accessOp->emitOpError(
2422 "currently cannot access objectFifo used in "
2423 "ObjectFifoLinkOp if the tiles don't share memory");
2424 return WalkResult::interrupt();
2429 accessOp->emitOpError(
2430 "currently cannot access objectFifo used in "
2431 "ObjectFifoLinkOp if it is a distribute or join link");
2432 return WalkResult::interrupt();
2436 accessOp.getOutput().replaceAllUsesWith(
2437 subviews[acqOp][accessOp.getIndex()]->getBuffer());
2438 return WalkResult::advance();
2440 if (res.wasInterrupted())
2441 return signalPassFailure();
2447 SetVector<Operation *> opsToErase;
2448 device.walk([&](Operation *op) {
2449 if (isa<ObjectFifoLinkOp, ObjectFifoRegisterExternalBuffersOp,
2450 ObjectFifoAcquireOp, ObjectFifoSubviewAccessOp,
2451 ObjectFifoReleaseOp, ObjectFifoAllocateOp>(op))
2452 opsToErase.insert(op);
2454 SmallVector<Operation *> sorted{opsToErase.begin(), opsToErase.end()};
2455 computeTopologicalSorting(sorted);
2456 for (
auto *op : llvm::reverse(sorted))
2464 for (
auto createOp : device.getOps<ObjectFifoCreateOp>()) {
2465 std::string shimAllocName = getShimAllocationName(createOp.getName());
2466 if (failed(SymbolTable::replaceAllSymbolUses(
2467 createOp.getNameAttr(), builder.getStringAttr(shimAllocName),
2470 "failed to replace symbol uses with shim allocation");
2471 return signalPassFailure();
2473 opsToErase.insert(createOp);
2475 for (
auto *op : opsToErase) {