795 ObjectFifoCreateOp op, DMAChannelDir channelDir,
796 int channelIndex,
int lockMode,
797 BDDimLayoutArrayAttr dims,
798 BDPadLayoutArrayAttr padDimensions) {
799 size_t numBlocks = op.size();
803 auto fifo = llvm::cast<AIEObjectFifoType>(op.getElemType());
804 auto elemType = llvm::cast<MemRefType>(fifo.getElementType());
805 int lenOut = elemType.getNumElements();
811 if (op.getRepeatCount().has_value())
812 repeatCount = op.getRepeatCount().value();
816 ObjectFifoCreateOp target = op;
817 bool isDistribute =
false;
820 int joinDistribFactor = 1;
821 int joinDistribLockIndex = 0;
826 auto srcOffsets = linkOp->getSrcOffsets();
827 auto dstOffsets = linkOp->getDstOffsets();
829 if (linkOp->getRepeatCount().has_value())
830 if (linkOp->getInputObjectFifos()[0] == op) {
831 acqNum *= linkOp->getRepeatCount().value();
832 relNum *= linkOp->getRepeatCount().value();
835 if (linkOp->isJoin()) {
839 joinDistribFactor *= linkOp->getFifoIns().size();
842 for (
auto fifoIn : linkOp->getInputObjectFifos()) {
843 if (fifoIn.name() == op.name())
847 extraOffset = *getConstantIntValue(srcOffsets[i]);
848 lenOut = linkOp->getJoinTransferLengths()[i];
849 joinDistribLockIndex = i;
851 }
else if (linkOp->isDistribute()) {
855 joinDistribFactor *= linkOp->getFifoOuts().size();
858 for (
auto fifoOut : linkOp->getOutputObjectFifos()) {
859 if (fifoOut.name() == op.name())
863 extraOffset = *getConstantIntValue(dstOffsets[i]);
864 lenOut = linkOp->getDistributeTransferLengths()[i];
865 joinDistribLockIndex = i;
870 llvm::cast<AIEObjectFifoType>(target.getElemType());
871 auto targetElemType =
872 llvm::cast<MemRefType>(targetFifo.getElementType());
873 lenOut = targetElemType.getNumElements();
879 numBlocks = target.size();
884 Operation *producerDMA =
nullptr;
885 for (
auto dmaOp : device.getOps<MemTileDMAOp>()) {
886 if (dmaOp.getTile() == target.getProducerTile()) {
887 producerDMA = dmaOp.getOperation();
893 TileOp objFifoTileOp = target.getProducerTileOp();
894 if (producerDMA ==
nullptr) {
895 OpBuilder::InsertionGuard g(builder);
896 builder.setInsertionPoint(device.getBody()->getTerminator());
898 builder.create<MemTileDMAOp>(builder.getUnknownLoc(), objFifoTileOp);
900 OpBuilder::InsertionGuard g(builder);
901 builder.setInsertionPointToStart(&newDMAOp.getRegion().emplaceBlock());
902 builder.create<EndOp>(builder.getUnknownLoc());
904 producerDMA = newDMAOp.getOperation();
908 Block *lastDmaBlock = endBlock->getSinglePredecessor();
909 Block *dmaBlock = builder.createBlock(endBlock);
910 Block *bdBlock = builder.createBlock(endBlock);
913 builder.setInsertionPointToStart(dmaBlock);
914 builder.create<DMAStartOp>(builder.getUnknownLoc(), channelDir,
915 channelIndex, 0, bdBlock,
917 if (lastDmaBlock !=
nullptr)
918 lastDmaBlock->getTerminator()->setSuccessor(dmaBlock, 1);
922 Block *curr = bdBlock;
923 size_t elemIndex = 0;
924 size_t lockIndex = 0;
925 size_t totalBlocks = 0;
926 bool distribOrJoin =
false;
927 for (
size_t i = 0; i < numBlocks; i++) {
930 for (
int r = 0; r < repeatCount * joinDistribFactor; r++) {
931 if (totalBlocks == numBlocks * repeatCount * joinDistribFactor - 1)
934 succ = builder.createBlock(endBlock);
936 builder.setInsertionPointToStart(curr);
938 if (isDistribute || isJoin) {
939 distribOrJoin =
true;
942 offset = *getConstantIntValue(linkOp->getDstOffsets()[r]);
943 lenOut = linkOp->getDistributeTransferLengths()[r];
945 offset = *getConstantIntValue(linkOp->getSrcOffsets()[r]);
946 lenOut = linkOp->getJoinTransferLengths()[r];
948 lockIndex = r % joinDistribFactor;
950 offset = extraOffset;
951 lockIndex = joinDistribLockIndex;
954 lockIndex = elemIndex;
956 createBdBlock<BufferOp>(builder, target, lockMode, acqNum, relNum,
958 lenOut, channelDir, lockIndex, succ, dims,
959 padDimensions, distribOrJoin);
978 std::set<TileOp> objectFifoTiles) {
979 for (
auto coreOp : device.getOps<CoreOp>()) {
980 if (objectFifoTiles.count(coreOp.getTileOp()) > 0) {
981 std::vector<scf::ForOp> unrolledLoops;
982 std::map<Operation *, bool> foundMap;
983 std::map<Operation *, int64_t> remainderMap;
984 std::map<Operation *, int64_t> tripCountMap;
985 WalkResult res = coreOp.walk([&](scf::ForOp forLoop) {
989 foundMap[forLoop.getOperation()] =
false;
990 std::set<int> objFifoSizes;
991 Block *body = forLoop.getBody();
992 remainderMap[forLoop.getOperation()] = 0;
993 for (
auto acqOp : body->getOps<ObjectFifoAcquireOp>()) {
994 if (acqOp.getOperation()->getParentOp() == forLoop) {
995 foundMap[forLoop.getOperation()] =
true;
996 ObjectFifoCreateOp op = acqOp.getObjectFifo();
997 objFifoSizes.insert(op.size());
1002 if (!foundMap[forLoop.getOperation()]) {
1003 unrolledLoops.push_back(forLoop);
1004 return WalkResult::advance();
1007 Region *region = forLoop->getParentRegion();
1008 scf::ForOp prevLoop;
1010 tripCountMap[prevLoop.getOperation()] = 0;
1011 while (remainderMap[prevLoop.getOperation()] > 1 ||
1012 foundMap[prevLoop.getOperation()]) {
1013 region->walk([&](scf::ForOp remLoop) {
1014 bool skipLoop =
false;
1015 int64_t tripCount = 0;
1016 if (remLoop.getSingleLowerBound() &&
1017 remLoop.getSingleUpperBound() && remLoop.getSingleStep()) {
1018 tripCount = constantTripCount(*(remLoop.getSingleLowerBound()),
1019 *(remLoop.getSingleUpperBound()),
1020 *(remLoop.getSingleStep()))
1032 if (remainderMap[prevLoop.getOperation()] > 1 &&
1033 foundMap[remLoop.getOperation()] ==
false &&
1034 prevLoop != remLoop) {
1037 if (std::count(unrolledLoops.begin(), unrolledLoops.end(),
1040 tripCountMap[remLoop.getOperation()] = tripCount;
1042 if (tripCountMap[remLoop.getOperation()] < unrollFactor)
1043 unrollFactor = tripCountMap[remLoop.getOperation()];
1045 if (unrollFactor == 0) {
1046 remLoop.emitOpError()
1047 <<
"could not be unrolled with unrollFactor = 0, check "
1050 return WalkResult::interrupt();
1052 remainderMap[remLoop.getOperation()] =
1053 tripCountMap[remLoop.getOperation()] % unrollFactor;
1054 auto step = remLoop.getStep()
1055 .getDefiningOp<arith::ConstantOp>()
1057 int64_t step_value = llvm::dyn_cast<IntegerAttr>(step).getInt();
1059 if (step_value < unrollFactor ||
1060 foundMap[remLoop.getOperation()]) {
1062 if (failed(mlir::loopUnrollByFactor(remLoop, unrollFactor))) {
1063 remLoop.emitOpError()
1064 <<
"could not be unrolled with unrollFactor: "
1065 << unrollFactor <<
"\n";
1066 return WalkResult::interrupt();
1068 unrolledLoops.push_back(remLoop);
1069 foundMap[remLoop.getOperation()] =
false;
1071 remainderMap[remLoop.getOperation()] = 0;
1072 foundMap[remLoop.getOperation()] =
false;
1075 remainderMap[remLoop.getOperation()] = 0;
1076 foundMap[remLoop.getOperation()] =
false;
1079 return WalkResult::advance();
1082 return WalkResult::advance();
1084 if (res.wasInterrupted())
1115 std::set<TileOp> objectFifoTiles) {
1116 for (
auto coreOp : device.getOps<CoreOp>()) {
1117 if (objectFifoTiles.count(coreOp.getTileOp()) <= 0)
1119 if (objectFifoTiles.count(coreOp.getTileOp()) > 0) {
1125 std::map<std::pair<ObjectFifoCreateOp, ObjectFifoPort>,
int> fifoSizes;
1128 std::map<std::pair<ObjectFifoCreateOp, ObjectFifoPort>,
1131 std::map<std::pair<ObjectFifoCreateOp, ObjectFifoPort>,
1136 builder.setInsertionPointToStart(&(coreOp.getBody().front()));
1137 Value initVal = builder.create<arith::ConstantOp>(
1138 builder.getUnknownLoc(), builder.getI32IntegerAttr(0));
1139 coreOp.walk([&](ObjectFifoAcquireOp acqOp) {
1140 ObjectFifoCreateOp op = acqOp.getObjectFifo();
1141 ObjectFifoPort
port = acqOp.getPort();
1142 if (fifoSizes.find({op,
port}) == fifoSizes.end()) {
1143 fifoSizes[{op,
port}] = op.size();
1144 auto indexOp = builder.create<arith::ConstantOp>(
1145 initVal.getLoc(), builder.getIndexAttr(index));
1146 globalIndices[{op,
port}] = indexOp;
1148 auto size = builder.create<arith::ConstantOp>(
1149 indexOp.getLoc(), builder.getI32IntegerAttr(op.size()));
1150 constantSizes[{op,
port}] = size;
1153 builder.setInsertionPoint(coreOp);
1155 MemRefType::get(SmallVector<int64_t>{(int64_t)fifoSizes.size()},
1156 builder.getI32Type());
1157 auto globalNextIndex = builder.create<BufferOp>(
1158 builder.getUnknownLoc(), memrefTy, coreOp.getTile(),
1163 for (
auto i : constantSizes) {
1164 builder.setInsertionPointAfter(i.second);
1165 builder.create<memref::StoreOp>(
1166 builder.getUnknownLoc(), initVal, globalNextIndex,
1167 ValueRange(ArrayRef({globalIndices[i.first].getResult()})));
1176 WalkResult res = coreOp.walk([&](Operation *op) {
1177 if (
auto relOp = dyn_cast<ObjectFifoReleaseOp>(op)) {
1178 ObjectFifoCreateOp createOp = relOp.getObjectFifo();
1179 ObjectFifoPort
port = relOp.getPort();
1180 updateGlobalNextIndex(builder, relOp, globalNextIndex,
1181 globalIndices[{createOp,
port}],
1182 constantSizes[{createOp,
port}]);
1184 if (
auto acqOp = dyn_cast<ObjectFifoAcquireOp>(op)) {
1185 std::vector<ObjectFifoSubviewAccessOp> accessOps;
1186 for (
auto u : acqOp->getUsers())
1187 if (
auto accessOp = dyn_cast<ObjectFifoSubviewAccessOp>(u))
1188 accessOps.push_back(accessOp);
1190 for (
auto accessOp : accessOps) {
1191 ObjectFifoCreateOp createOp = acqOp.getObjectFifo();
1192 ObjectFifoPort
port = acqOp.getPort();
1195 if (fifoSizes[{createOp,
port}] == 1)
1196 return WalkResult::advance();
1199 builder.setInsertionPointAfter(accessOp);
1200 auto switchIndexAsInteger = builder.create<memref::LoadOp>(
1201 builder.getUnknownLoc(), globalNextIndex,
1203 ArrayRef({globalIndices[{createOp,
port}].getResult()})));
1204 auto switchIndex = builder.create<arith::IndexCastOp>(
1205 builder.getUnknownLoc(), builder.getIndexType(),
1206 switchIndexAsInteger);
1207 unsigned caseRegionCounts = fifoSizes[{createOp,
port}];
1208 SmallVector<int64_t, 4> caseValues;
1209 for (
int i = 0; i < fifoSizes[{createOp,
port}]; ++i) {
1210 caseValues.push_back(i);
1213 DenseI64ArrayAttr::get(builder.getContext(), caseValues);
1214 auto switchOp = builder.create<scf::IndexSwitchOp>(
1215 switchIndex.getLoc(),
1216 TypeRange({buffersPerFifo[createOp][0].getType()}),
1217 switchIndex, cases, caseRegionCounts);
1219 builder.createBlock(&switchOp.getDefaultRegion());
1220 auto bufferIndex = (accessOp.getIndex()) % createOp.size();
1221 builder.setInsertionPointToStart(&(switchOp.getDefaultBlock()));
1222 builder.create<scf::YieldOp>(
1223 builder.getUnknownLoc(),
1224 buffersPerFifo[createOp][bufferIndex].getResult());
1225 for (
int i = 0; i < fifoSizes[{createOp,
port}]; ++i) {
1227 builder.createBlock(&switchOp.getCaseRegions()[i]);
1228 builder.setInsertionPoint(&switchOp.getCaseBlock(i),
1229 switchOp.getCaseBlock(i).begin());
1230 int bufferToBeAccesed =
1231 (accessOp.getIndex() + i) % fifoSizes[{createOp,
port}];
1232 builder.create<scf::YieldOp>(
1233 switchOp.getCaseRegions()[i].getLoc(),
1234 buffersPerFifo[createOp][bufferToBeAccesed].getResult());
1239 accessOp.getOutput().replaceAllUsesWith(switchOp.getResult(0));
1242 return WalkResult::advance();
1244 if (res.wasInterrupted())
1445 DeviceOp device = getOperation();
1448 OpBuilder builder = OpBuilder::atBlockTerminator(device.getBody());
1449 auto ctx = device->getContext();
1450 auto producerWireType = WireBundle::DMA;
1451 auto consumerWireType = WireBundle::DMA;
1455 verifyObjectFifoLinks(device);
1463 std::vector<ObjectFifoCreateOp> createFifoOps;
1464 auto range = device.getOps<ObjectFifoCreateOp>();
1465 createFifoOps.insert(createFifoOps.end(), range.begin(), range.end());
1466 for (
auto createOp : createFifoOps) {
1467 std::vector<ObjectFifoCreateOp> splitConsumerFifos;
1468 int consumerIndex = 0;
1469 int consumerDepth = createOp.size();
1470 ArrayRef<BDDimLayoutArrayAttr> consumerDims =
1471 createOp.getDimensionsFromStreamPerConsumer();
1475 if (
int share_direction = 0; !requiresDMAs(createOp, share_direction)) {
1479 for (
auto consumerTile : createOp.getConsumerTiles()) {
1480 auto consumerTileOp = dyn_cast<TileOp>(consumerTile.getDefiningOp());
1482 if (isa<ArrayAttr>(createOp.getElemNumber())) {
1484 consumerDepth = createOp.size(consumerIndex + 1);
1486 consumerDepth = findObjectFifoSize(device, consumerTileOp, createOp);
1489 builder.setInsertionPointAfter(createOp);
1490 auto datatype = llvm::cast<AIEObjectFifoType>(createOp.getElemType());
1491 auto consumerObjFifoSize =
1492 builder.getIntegerAttr(builder.getI32Type(), consumerDepth);
1494 std::string consumerFifoName;
1495 if (createOp.getConsumerTiles().size() > 1) {
1496 consumerFifoName = createOp.name().str() +
"_" +
1497 std::to_string(consumerIndex) +
"_cons";
1499 consumerFifoName = createOp.name().str() +
"_cons";
1501 BDDimLayoutArrayAttr emptyDims =
1502 BDDimLayoutArrayAttr::get(builder.getContext(), {});
1503 BDDimLayoutArrayAttr singletonFromStreamDims =
1504 BDDimLayoutArrayAttr::get(
1505 builder.getContext(),
1506 ArrayRef<BDDimLayoutAttr>{consumerDims[consumerIndex]});
1507 BDDimLayoutArrayArrayAttr fromStreamDims =
1508 BDDimLayoutArrayArrayAttr::get(builder.getContext(),
1509 singletonFromStreamDims);
1511 ObjectFifoCreateOp consumerFifo = createObjectFifo(
1512 builder, datatype, consumerFifoName, consumerTile, consumerTile,
1513 consumerObjFifoSize, emptyDims, fromStreamDims);
1514 if (createOp.getDisableSynchronization())
1515 consumerFifo.setDisableSynchronization(
true);
1516 replaceSplitFifo(createOp, consumerFifo, consumerTileOp);
1519 if (consumerTile.getDefiningOp<TileOp>().isShimTile())
1520 detectExternalBuffers(device, createOp, consumerFifo, consumerTile);
1523 splitConsumerFifos.push_back(consumerFifo);
1526 if (
auto linkOp = getOptionalLinkOp(createOp))
1527 for (ObjectFifoCreateOp fifoIn : linkOp->getInputObjectFifos())
1528 if (fifoIn.name() == createOp.name() &&
1529 consumerTile == *linkOp->getOptionalSharedTile())
1530 if (failed(SymbolTable::replaceAllSymbolUses(
1531 createOp, consumerFifo.name(), linkOp->getOperation())))
1532 llvm::report_fatal_error(
"unable to update all symbol uses");
1537 if (!splitConsumerFifos.empty()) {
1538 splitFifos.emplace_back(createOp, splitConsumerFifos);
1549 for (
auto createOp : device.getOps<ObjectFifoCreateOp>()) {
1550 int share_direction = 0;
1551 bool shared = !requiresDMAs(createOp, share_direction);
1555 objectFifoTiles.insert(createOp.getProducerTileOp());
1556 for (
auto consumerTile : createOp.getConsumerTiles()) {
1557 auto consumerTileOp = dyn_cast<TileOp>(consumerTile.getDefiningOp());
1558 objectFifoTiles.insert(consumerTileOp);
1563 if (createOp.getProducerTileOp().isShimTile())
1564 detectExternalBuffers(device, createOp, createOp,
1565 createOp.getProducerTile());
1569 checkAndApplyViaSharedMemAttribute(createOp, share_direction);
1570 createObjectFifoElements(builder, lockAnalysis, createOp,
1573 if (createOp.getViaSharedMem().has_value())
1574 createOp->emitOpError(
1575 "no access to shared memory module specified by "
1576 "`via_shared_mem`");
1578 if (isa<ArrayAttr>(createOp.getElemNumber()))
1579 createOp.setElemNumberAttr(
1580 builder.getI32IntegerAttr(createOp.size()));
1582 if (!createOp.getInitValues().has_value()) {
1583 int prodMaxAcquire = findObjectFifoSize(
1584 device, createOp.getProducerTileOp(), createOp);
1585 createOp.setElemNumberAttr(
1586 builder.getI32IntegerAttr(prodMaxAcquire));
1589 createObjectFifoElements(builder, lockAnalysis, createOp,
1599 for (
auto &[producer, consumers] : splitFifos) {
1602 producer.getProducerTileOp(), DMAChannelDir::MM2S);
1603 if (producerChanIndex == -1)
1604 producer.getProducerTileOp().emitOpError(
1605 "number of output DMA channel exceeded!");
1606 DMAChannel producerChan = {DMAChannelDir::MM2S, producerChanIndex};
1607 createDMA(device, builder, producer, producerChan.direction,
1608 producerChan.channel, 0, producer.getDimensionsToStreamAttr(),
1609 producer.getPadDimensionsAttr());
1611 builder.setInsertionPoint(device.getBody()->getTerminator());
1613 if (producer.getProducerTileOp().isShimTile())
1614 createObjectFifoAllocationInfo(
1615 builder, ctx, SymbolRefAttr::get(ctx, producer.getName()),
1616 producer.getProducerTileOp().colIndex(), producerChan.direction,
1617 producerChan.channel, producer.getPlio());
1619 for (
auto consumer : consumers) {
1623 consumer.getProducerTileOp(), DMAChannelDir::S2MM);
1624 if (consumerChanIndex == -1)
1625 consumer.getProducerTileOp().emitOpError(
1626 "number of input DMA channel exceeded!");
1627 DMAChannel consumerChan = {DMAChannelDir::S2MM, consumerChanIndex};
1628 BDDimLayoutArrayAttr consumerDims =
1629 consumer.getDimensionsFromStreamPerConsumer()[0];
1630 createDMA(device, builder, consumer, consumerChan.direction,
1631 consumerChan.channel, 1, consumerDims,
nullptr);
1633 builder.setInsertionPoint(device.getBody()->getTerminator());
1636 if (producer.getPlio()) {
1637 producerWireType = producer.getProducerTileOp().isShimTile()
1640 consumerWireType = consumer.getProducerTileOp().isShimTile()
1644 producerWireType = WireBundle::DMA;
1645 consumerWireType = WireBundle::DMA;
1648 if (consumer.getProducerTileOp().isShimTile())
1649 createObjectFifoAllocationInfo(
1650 builder, ctx, SymbolRefAttr::get(ctx, producer.getName()),
1651 consumer.getProducerTileOp().colIndex(), consumerChan.direction,
1652 consumerChan.channel, producer.getPlio());
1655 builder.setInsertionPointAfter(producer);
1656 builder.create<FlowOp>(builder.getUnknownLoc(),
1657 producer.getProducerTile(), producerWireType,
1658 producerChan.channel, consumer.getProducerTile(),
1659 consumerWireType, consumerChan.channel);
1666 if (clDynamicObjectFifos) {
1667 if (failed(dynamicGlobalObjectFifos(device, builder, objectFifoTiles)))
1668 signalPassFailure();
1670 std::set<TileOp> dynamicTiles;
1671 std::set<TileOp> unrollTiles;
1672 for (
auto c : device.getOps<CoreOp>()) {
1673 TileOp t = c.getTileOp();
1674 if (objectFifoTiles.count(t) > 0) {
1675 if (c.getDynamicObjfifoLowering().has_value()) {
1676 if (c.getDynamicObjfifoLowering().value())
1677 dynamicTiles.insert(t);
1679 unrollTiles.insert(t);
1681 unrollTiles.insert(t);
1685 if (failed(dynamicGlobalObjectFifos(device, builder, dynamicTiles)))
1686 signalPassFailure();
1687 if (failed(unrollForLoops(device, builder, unrollTiles)))
1688 signalPassFailure();
1694 for (
auto coreOp : device.getOps<CoreOp>()) {
1695 DenseMap<ObjectFifoAcquireOp, std::vector<BufferOp *>>
1698 DenseMap<std::pair<ObjectFifoCreateOp, int>, std::vector<int>>
1702 DenseMap<std::pair<ObjectFifoCreateOp, int>,
1703 std::vector<ObjectFifoReleaseOp>>
1706 DenseMap<std::pair<ObjectFifoCreateOp, int>,
int>
1709 DenseMap<std::pair<ObjectFifoCreateOp, int>,
int>
1716 coreOp.walk([&](ObjectFifoReleaseOp releaseOp) {
1717 builder.setInsertionPointAfter(releaseOp);
1718 ObjectFifoCreateOp op = releaseOp.getObjectFifo();
1719 auto port = releaseOp.getPort();
1720 auto portNum =
port == ObjectFifoPort::Produce ? 0 : 1;
1721 auto core = releaseOp->getParentOfType<CoreOp>();
1723 if (
auto linkOp = getOptionalLinkOp(op)) {
1724 if (core.getTile() == *linkOp->getOptionalSharedTile()) {
1725 releaseOp->emitOpError(
"currently cannot access objectFifo used in "
1726 "ObjectFifoLinkOp");
1732 updateAndReturnIndex(relPerFifo, {op, portNum});
1735 int numLocks = releaseOp.relNumber();
1737 if (op.getRepeatCount().has_value())
1738 numLocks *= op.getRepeatCount().value();
1739 createUseLocks(builder, op,
port, relPerFifo, numLocks,
1740 LockAction::Release);
1743 if (releaseOps.find({op, portNum}) != releaseOps.end()) {
1744 releaseOps[{op, portNum}].push_back(releaseOp);
1746 std::vector release = {releaseOp};
1747 releaseOps[{op, portNum}] = release;
1754 coreOp.walk([&](ObjectFifoAcquireOp acquireOp) {
1755 ObjectFifoCreateOp op = acquireOp.getObjectFifo();
1756 builder.setInsertionPointAfter(acquireOp);
1757 auto port = acquireOp.getPort();
1758 auto portNum =
port == ObjectFifoPort::Produce ? 0 : 1;
1759 auto core = acquireOp->getParentOfType<CoreOp>();
1761 auto linkOp = getOptionalLinkOp(op);
1763 if (core.getTile() == *linkOp->getOptionalSharedTile()) {
1764 acquireOp->emitOpError(
"currently cannot access objectFifo used in "
1765 "ObjectFifoLinkOp");
1771 int start = updateAndReturnIndex(
1772 acqPerFifo, {op, portNum});
1779 for (std::vector<ObjectFifoReleaseOp>::iterator relOp =
1780 releaseOps[{op, portNum}].begin();
1781 relOp != releaseOps[{op, portNum}].end();) {
1782 bool erased =
false;
1783 Operation *acqBlockDefOp = acquireOp.getOperation();
1785 Operation *relBlockDefOp = (*relOp).getOperation();
1787 if (acqBlockDefOp->getBlock() == relBlockDefOp->getBlock()) {
1788 if (relBlockDefOp->isBeforeInBlock(acqBlockDefOp)) {
1789 numRel += (*relOp).relNumber();
1790 relOp = releaseOps[{op, portNum}].erase(relOp);
1797 }
while ((relBlockDefOp = relBlockDefOp->getParentOp()) &&
1798 !isa<DeviceOp>(relBlockDefOp) && !erased);
1799 }
while ((acqBlockDefOp = acqBlockDefOp->getParentOp()) &&
1800 !isa<DeviceOp>(acqBlockDefOp) && !erased);
1806 std::vector<int> acquiredIndices;
1807 if (!acquiresPerFifo[{op, portNum}].empty()) {
1810 acquiredIndices = acquiresPerFifo[{op, portNum}];
1812 if (
static_cast<size_t>(numRel) > acquiredIndices.size()) {
1813 acquireOp->emitOpError(
"cannot release more elements than are "
1814 "already acquired");
1817 for (
int i = 0; i < numRel; i++)
1818 acquiredIndices.erase(acquiredIndices.begin());
1822 int numLocks = acquireOp.acqNumber();
1823 int alreadyAcq = acquiredIndices.size();
1825 if (numLocks > alreadyAcq)
1826 numCreate = numLocks - alreadyAcq;
1831 if (op.getRepeatCount().has_value())
1832 numCreate *= op.getRepeatCount().value();
1834 auto dev = op->getParentOfType<DeviceOp>();
1835 if (
auto &targetArch = dev.getTargetModel();
1836 targetArch.getTargetArch() == AIEArch::AIE1)
1837 createUseLocks(builder, op,
port, acqPerFifo, numCreate,
1838 LockAction::Acquire);
1840 createUseLocks(builder, op,
port, acqPerFifo, numCreate,
1841 LockAction::AcquireGreaterEqual);
1845 ObjectFifoCreateOp target = op;
1847 if (objFifoLinks.find(*linkOp) != objFifoLinks.end())
1848 target = objFifoLinks[*linkOp];
1851 for (
int i = 0; i < numCreate; i++) {
1852 acquiredIndices.push_back(start);
1853 start = (start + 1) % op.size();
1855 std::vector<BufferOp *> subviewRefs;
1856 subviewRefs.reserve(acquiredIndices.size());
1857 for (
auto index : acquiredIndices)
1858 subviewRefs.push_back(&buffersPerFifo[target][index]);
1860 subviews[acquireOp] = subviewRefs;
1861 acquiresPerFifo[{op, portNum}] = acquiredIndices;
1867 coreOp.walk([&](ObjectFifoSubviewAccessOp accessOp) {
1868 auto acqOp = accessOp.getSubview().getDefiningOp<ObjectFifoAcquireOp>();
1869 if (ObjectFifoCreateOp op = acqOp.getObjectFifo()) {
1870 if (
auto linkOp = getOptionalLinkOp(op); linkOp.has_value()) {
1871 if (!linkOp->isDistribute() && !linkOp->isJoin()) {
1872 for (
auto consumerTile : op.getConsumerTiles()) {
1873 if (
auto consumerTileOp =
1874 dyn_cast<TileOp>(consumerTile.getDefiningOp())) {
1875 int share_dir_value = 0;
1876 bool sharing = isSharedMemory(
1877 op.getProducerTileOp(), consumerTileOp, &share_dir_value);
1879 accessOp->emitOpError(
1880 "currently cannot access objectFifo used in "
1881 "ObjectFifoLinkOp if the tiles don't share memory");
1885 accessOp->emitOpError(
1886 "currently cannot access objectFifo used in "
1887 "ObjectFifoLinkOp if it is a distribute or join link");
1890 accessOp.getOutput().replaceAllUsesWith(
1891 subviews[acqOp][accessOp.getIndex()]->getBuffer());
1895 for (
auto createOp : device.getOps<ObjectFifoCreateOp>()) {
1896 builder.setInsertionPointToStart(device.getBody());
1897 auto sym_name = createOp.getName();
1898 createOp->setAttr(SymbolTable::getSymbolAttrName(),
1899 builder.getStringAttr(
"__erase_" + sym_name));
1900 auto memrefType = llvm::cast<AIEObjectFifoType>(createOp.getElemType())
1902 builder.create<memref::GlobalOp>(builder.getUnknownLoc(), sym_name,
1903 builder.getStringAttr(
"public"),
1904 memrefType,
nullptr,
false,
nullptr);
1910 SetVector<Operation *> opsToErase;
1911 device.walk([&](Operation *op) {
1912 if (isa<ObjectFifoCreateOp, ObjectFifoLinkOp,
1913 ObjectFifoRegisterExternalBuffersOp, ObjectFifoAcquireOp,
1914 ObjectFifoSubviewAccessOp, ObjectFifoReleaseOp>(op))
1915 opsToErase.insert(op);
1917 SmallVector<Operation *> sorted{opsToErase.begin(), opsToErase.end()};
1918 computeTopologicalSorting(sorted);
1919 for (
auto *op : llvm::reverse(sorted))