diff --git a/lib/Dialect/AIE/Transforms/AIEObjectFifoStatefulTransform.cpp b/lib/Dialect/AIE/Transforms/AIEObjectFifoStatefulTransform.cpp index 121c1a73be7..71c3167484f 100644 --- a/lib/Dialect/AIE/Transforms/AIEObjectFifoStatefulTransform.cpp +++ b/lib/Dialect/AIE/Transforms/AIEObjectFifoStatefulTransform.cpp @@ -1812,11 +1812,20 @@ struct AIEObjectFifoStatefulTransformPass : !crossTileInfos.at(producer); if (shouldProcessProducer) { - bool requiresAdjacentTileAccessChannels = crossTileInfos.at(producer); - int channelIndex = dmaAnalysis.getDMAChannelIndex( - producer.getProducerTileOp(), DMAChannelDir::MM2S, - requiresAdjacentTileAccessChannels); - fifo_dma_channel_index[producer] = channelIndex; + // Skip stream-port producers — they use Core ports, not DMA channels + bool prodIsStream = false; + if (producer.getAieStream()) { + int streamEnd = producer.getAieStream().value(); + prodIsStream = (streamEnd == 0 || streamEnd == 2); + } + if (!prodIsStream) { + bool requiresAdjacentTileAccessChannels = + crossTileInfos.at(producer); + int channelIndex = dmaAnalysis.getDMAChannelIndex( + producer.getProducerTileOp(), DMAChannelDir::MM2S, + requiresAdjacentTileAccessChannels); + fifo_dma_channel_index[producer] = channelIndex; + } } for (auto consumer : consumers) { @@ -1827,6 +1836,12 @@ struct AIEObjectFifoStatefulTransformPass : !crossTileInfos.at(consumer); if (shouldProcessConsumer) { + // Skip stream-port consumers — they use Core ports, not DMA channels + if (consumer.getAieStream()) { + int streamEnd = consumer.getAieStream().value(); + if (streamEnd == 1 || streamEnd == 2) + continue; + } bool requiresAdjacentTileAccessChannels = crossTileInfos.at(consumer); int channelIndex = dmaAnalysis.getDMAChannelIndex( consumer.getProducerTileOp(), DMAChannelDir::S2MM, diff --git a/python/iron/dataflow/objectfifo.py b/python/iron/dataflow/objectfifo.py index ef6bc9de614..860887aaf68 100644 --- a/python/iron/dataflow/objectfifo.py +++ b/python/iron/dataflow/objectfifo.py @@ -79,6 +79,8 @@ def __init__( self._cons: list[ObjectFifoHandle] = [] self._resolving = False self._iter_count: int | None = None + self._aie_stream: int | None = None + self._aie_stream_port: int | None = None @classmethod def __get_index(cls) -> int: @@ -137,6 +139,19 @@ def set_iter_count(self, iter_count: int): self._iter_count = iter_count + def set_aie_stream(self, stream_end: int, stream_port: int = 0): + """Configure one end of this ObjectFifo to use a Core stream port + instead of DMA, bypassing L1 buffering. + + Args: + stream_end: 0 (producer stream), 1 (consumer stream), 2 (both) + stream_port: Core stream port index (default 0) + """ + if stream_end not in (0, 1, 2): + raise ValueError("stream_end must be 0 (producer), 1 (consumer), or 2 (both)") + self._aie_stream = stream_end + self._aie_stream_port = stream_port + def __str__(self) -> str: prod_endpoint = None if self._prod: @@ -300,6 +315,9 @@ def resolve( iter_count=self._iter_count, ) + if self._aie_stream is not None: + self._op.set_aie_stream(self._aie_stream, self._aie_stream_port) + if isinstance(self._prod.endpoint, ObjectFifoLink): self._prod.endpoint.resolve() for con in self._cons: