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)