actorlib/dma_asmi: out-of-order reader and class factory
authorSebastien Bourdeauducq <sebastien@milkymist.org>
Thu, 12 Jul 2012 16:34:13 +0000 (18:34 +0200)
committerSebastien Bourdeauducq <sebastien@milkymist.org>
Thu, 12 Jul 2012 16:34:13 +0000 (18:34 +0200)
migen/actorlib/dma_asmi.py

index 6a201f576f122ad291542870709e85afcdecdf4b..9dad765309c2da1ba0c4dd1d2c27d7c148aa7544 100644 (file)
@@ -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)