2013-07-24 13:25:14 -04:00
|
|
|
from migen.fhdl.std import *
|
|
|
|
|
|
|
|
class ReorderSlot:
|
|
|
|
def __init__(self, tag_width, data_width):
|
|
|
|
self.wait_data = Signal()
|
|
|
|
self.has_data = Signal()
|
|
|
|
self.tag = Signal(tag_width)
|
|
|
|
self.data = Signal(data_width)
|
|
|
|
|
|
|
|
class ReorderBuffer(Module):
|
|
|
|
def __init__(self, tag_width, data_width, depth):
|
|
|
|
# issue
|
|
|
|
self.can_issue = Signal()
|
|
|
|
self.issue = Signal()
|
|
|
|
self.tag_issue = Signal(tag_width)
|
2014-10-17 05:08:37 -04:00
|
|
|
|
2013-07-24 13:25:14 -04:00
|
|
|
# call
|
|
|
|
self.call = Signal()
|
|
|
|
self.tag_call = Signal(tag_width)
|
|
|
|
self.data_call = Signal(data_width)
|
2014-10-17 05:08:37 -04:00
|
|
|
|
2013-07-24 13:25:14 -04:00
|
|
|
# readback
|
|
|
|
self.can_read = Signal()
|
|
|
|
self.read = Signal()
|
|
|
|
self.data_read = Signal(data_width)
|
2014-10-17 05:08:37 -04:00
|
|
|
|
2013-07-24 13:25:14 -04:00
|
|
|
###
|
|
|
|
|
|
|
|
empty_count = Signal(max=depth+1, reset=depth)
|
|
|
|
produce = Signal(max=depth)
|
|
|
|
consume = Signal(max=depth)
|
|
|
|
slots = Array(ReorderSlot(tag_width, data_width)
|
|
|
|
for n in range(depth))
|
|
|
|
|
|
|
|
# issue
|
|
|
|
self.comb += self.can_issue.eq(empty_count != 0)
|
|
|
|
self.sync += If(self.issue & self.can_issue,
|
|
|
|
empty_count.eq(empty_count - 1),
|
|
|
|
If(produce == depth - 1,
|
|
|
|
produce.eq(0)
|
|
|
|
).Else(
|
|
|
|
produce.eq(produce + 1)
|
|
|
|
),
|
|
|
|
slots[produce].wait_data.eq(1),
|
|
|
|
slots[produce].tag.eq(self.tag_issue)
|
|
|
|
)
|
2014-10-17 05:08:37 -04:00
|
|
|
|
2013-07-24 13:25:14 -04:00
|
|
|
# call
|
|
|
|
for n, slot in enumerate(slots):
|
|
|
|
self.sync += 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)
|
|
|
|
)
|
2014-10-17 05:08:37 -04:00
|
|
|
|
2013-07-24 13:25:14 -04:00
|
|
|
# readback
|
|
|
|
self.comb += [
|
|
|
|
self.can_read.eq(slots[consume].has_data),
|
|
|
|
self.data_read.eq(slots[consume].data)
|
|
|
|
]
|
|
|
|
self.sync += [
|
|
|
|
If(self.read & self.can_read,
|
|
|
|
empty_count.eq(empty_count + 1),
|
|
|
|
If(consume == depth - 1,
|
|
|
|
consume.eq(0)
|
|
|
|
).Else(
|
|
|
|
consume.eq(consume + 1)
|
|
|
|
),
|
|
|
|
slots[consume].has_data.eq(0)
|
|
|
|
)
|
|
|
|
]
|
2014-10-17 05:08:37 -04:00
|
|
|
|
2013-07-24 13:25:14 -04:00
|
|
|
# do not touch empty count when issuing and reading at the same time
|
|
|
|
self.sync += If(self.issue & self.can_issue & self.read & self.can_read,
|
|
|
|
empty_count.eq(empty_count)
|
|
|
|
)
|