diff --git a/migen/actorlib/dma_asmi.py b/migen/actorlib/dma_asmi.py index 6a201f576..9dad76530 100644 --- a/migen/actorlib/dma_asmi.py +++ b/migen/actorlib/dma_asmi.py @@ -1,5 +1,6 @@ from migen.fhdl.structure import * from migen.flow.actor import * +from migen.corelogic.buffers import ReorderBuffer class SequentialReader(Actor): def __init__(self, port): @@ -42,3 +43,49 @@ class SequentialReader(Actor): ] return Fragment(comb, sync) + +class OOOReader(Actor): + def __init__(self, port): + self.port = port + assert(len(self.port.slots) > 1) + super().__init__( + ("address", Sink, [("a", BV(self.port.hub.aw))]), + ("data", Source, [("d", BV(self.port.hub.dw))])) + + def get_fragment(self): + tag_width = len(self.port.tag_call) + data_width = self.port.hub.dw + depth = len(self.port.slots) + rob = ReorderBuffer(tag_width, data_width, depth) + + comb = [ + self.port.adr.eq(self.token("address").a), + self.port.we.eq(0), + self.port.stb.eq(self.endpoints["address"].stb & rob.can_issue), + self.endpoints["address"].ack.eq(self.port.ack & rob.can_issue), + rob.issue.eq(self.endpoints["address"].stb & self.port.ack), + rob.tag_issue.eq(self.port.base + self.port.tag_issue), + + rob.data_call.eq(self.port.dat_r), + + self.endpoints["data"].stb.eq(rob.can_read), + rob.read.eq(self.endpoints["data"].ack), + self.token("data").d.eq(rob.data_read) + ] + sync = [ + # Data is announced one cycle in advance. + # Register the call to synchronize it with the data signal. + rob.call.eq(self.port.call), + rob.tag_call.eq(self.port.tag_call) + ] + + return Fragment(comb, sync) + rob.get_fragment() + +class Reader: + def __init__(self, port): + if len(port.slots) == 1: + self.__class__ = SequentialReader + SequentialReader.__init__(self, port) + else: + self.__class__ = OOOReader + OOOReader.__init__(self, port)