corelogic: reorder buffer (untested)
authorSebastien Bourdeauducq <sebastien@milkymist.org>
Thu, 12 Jul 2012 16:33:28 +0000 (18:33 +0200)
committerSebastien Bourdeauducq <sebastien@milkymist.org>
Thu, 12 Jul 2012 16:33:28 +0000 (18:33 +0200)
migen/corelogic/buffers.py [new file with mode: 0644]

diff --git a/migen/corelogic/buffers.py b/migen/corelogic/buffers.py
new file mode 100644 (file)
index 0000000..b788a34
--- /dev/null
@@ -0,0 +1,80 @@
+from migen.fhdl.structure import *
+
+class ReorderSlot:
+       def __init__(self, tag_width, data_width):
+               self.wait_data = Signal()
+               self.has_data = Signal()
+               self.tag = Signal(BV(tag_width))
+               self.data = Signal(BV(data_width))
+
+class ReorderBuffer:
+       def __init__(self, tag_width, data_width, depth):
+               self.depth = depth
+               
+               # issue
+               self.can_issue = Signal()
+               self.issue = Signal()
+               self.tag_issue = Signal(BV(tag_width))
+               
+               # call
+               self.call = Signal()
+               self.tag_call = Signal(BV(tag_width))
+               self.data_call = Signal(BV(data_width))
+               
+               # readback
+               self.can_read = Signal()
+               self.read = Signal()
+               self.data_read = Signal(BV(data_width))
+               
+               self._empty_count = Signal(BV(bits_for(self.depth)), reset=self.depth)
+               self._produce = Signal(BV(bits_for(self.depth-1)))
+               self._consume = Signal(BV(bits_for(self.depth-1)))
+               self._slots = Array(ReorderSlot(tag_width, data_width)
+                       for n in range(self.depth))
+       
+       def get_fragment(self):
+               # issue
+               comb = [
+                       self.can_issue.eq(self._empty_count != 0)
+               ]
+               sync = [
+                       If(self.issue & self.can_issue,
+                               self._empty_count.eq(self._empty_count - 1),
+                               If(self._produce == self.depth - 1,
+                                       self._produce.eq(0)
+                               ).Else(
+                                       self._produce.eq(self._produce + 1)
+                               ),
+                               self._slots[self._produce].wait_data.eq(1),
+                               self._slots[self._produce].tag.eq(self.tag_issue)
+                       )
+               ]
+               
+               # call
+               for n, slot in enumerate(self._slots):
+                       sync.append(
+                               If(self.call & slot.wait_data & (self.tag_call == slot.tag),
+                                       slot.wait_data.eq(0),
+                                       slot.has_data.eq(1),
+                                       slot.data.eq(self.data_call)
+                               )
+                       )
+               
+               # readback
+               comb += [
+                       self.can_read.eq(self._slots[self._consume].has_data),
+                       self.data_read.eq(self._slots[self._consume].data)
+               ]
+               sync += [
+                       If(self.read & self.can_read,
+                               self._empty_count.eq(self._empty_count + 1),
+                               If(self._consume == self.depth - 1,
+                                       self._consume.eq(0)
+                               ).Else(
+                                       self._consume.eq(self._consume + 1)
+                               ),
+                               self._slots[self._consume].has_data.eq(0)
+                       )
+               ]
+               
+               return Fragment(comb, sync)
\ No newline at end of file