rtio/sed: add minimum buffer space reporting

This commit is contained in:
Sebastien Bourdeauducq 2017-09-20 11:27:57 +08:00
parent 63e39dec94
commit d8aa75b742
3 changed files with 56 additions and 3 deletions

View File

@ -27,6 +27,9 @@ layout = [
# o_status bits: # o_status bits:
# <0:wait> <1:underflow> <2:sequence_error> # <0:wait> <1:underflow> <2:sequence_error>
("o_status", 3, DIR_S_TO_M), ("o_status", 3, DIR_S_TO_M),
# targets may optionally report a pessimistic estimate of the number
# of outputs events that can be written without waiting.
("o_buffer_space", 16, DIR_S_TO_M),
("i_data", 32, DIR_S_TO_M), ("i_data", 32, DIR_S_TO_M),
("i_timestamp", 64, DIR_S_TO_M), ("i_timestamp", 64, DIR_S_TO_M),

View File

@ -13,7 +13,7 @@ __all__ = ["SED"]
class SED(Module): class SED(Module):
def __init__(self, channels, glbl_fine_ts_width, mode, def __init__(self, channels, glbl_fine_ts_width, mode,
lane_count=8, fifo_depth=128, enable_spread=True, lane_count=8, fifo_depth=128, enable_spread=True,
quash_channels=[], interface=None): quash_channels=[], interface=None, report_min_space=False):
if mode == "sync": if mode == "sync":
lane_dist_cdr = lambda x: x lane_dist_cdr = lambda x: x
fifos_cdr = lambda x: x fifos_cdr = lambda x: x
@ -37,7 +37,7 @@ class SED(Module):
interface=interface)) interface=interface))
self.submodules.fifos = fifos_cdr( self.submodules.fifos = fifos_cdr(
FIFOs(lane_count, fifo_depth, FIFOs(lane_count, fifo_depth,
layouts.fifo_payload(channels), mode)) layouts.fifo_payload(channels), mode, report_min_space))
self.submodules.gates = gates_cdr( self.submodules.gates = gates_cdr(
Gates(lane_count, seqn_width, Gates(lane_count, seqn_width,
layouts.fifo_payload(channels), layouts.fifo_payload(channels),
@ -52,6 +52,9 @@ class SED(Module):
for o, i in zip(self.gates.output, self.output_driver.input): for o, i in zip(self.gates.output, self.output_driver.input):
self.comb += i.eq(o) self.comb += i.eq(o)
if report_min_space:
self.comb += self.cri.o_buffer_space.eq(self.fifos.min_space)
@property @property
def cri(self): def cri(self):
return self.lane_dist.cri return self.lane_dist.cri

View File

@ -1,3 +1,6 @@
from operator import or_
from functools import reduce
from migen import * from migen import *
from migen.genlib.fifo import * from migen.genlib.fifo import *
@ -8,13 +11,18 @@ __all__ = ["FIFOs"]
class FIFOs(Module): class FIFOs(Module):
def __init__(self, lane_count, fifo_depth, layout_payload, mode): def __init__(self, lane_count, fifo_depth, layout_payload, mode, report_min_space=False):
seqn_width = layouts.seqn_width(lane_count, fifo_depth) seqn_width = layouts.seqn_width(lane_count, fifo_depth)
self.input = [Record(layouts.fifo_ingress(seqn_width, layout_payload)) self.input = [Record(layouts.fifo_ingress(seqn_width, layout_payload))
for _ in range(lane_count)] for _ in range(lane_count)]
self.output = [Record(layouts.fifo_egress(seqn_width, layout_payload)) self.output = [Record(layouts.fifo_egress(seqn_width, layout_payload))
for _ in range(lane_count)] for _ in range(lane_count)]
if report_min_space:
self.min_space = Signal(max=fifo_depth+1)
# # #
if mode == "sync": if mode == "sync":
fifo_cls = SyncFIFOBuffered fifo_cls = SyncFIFOBuffered
elif mode == "async": elif mode == "async":
@ -22,9 +30,11 @@ class FIFOs(Module):
else: else:
raise ValueError raise ValueError
fifos = []
for input, output in zip(self.input, self.output): for input, output in zip(self.input, self.output):
fifo = fifo_cls(layout_len(layout_payload), fifo_depth) fifo = fifo_cls(layout_len(layout_payload), fifo_depth)
self.submodules += fifo self.submodules += fifo
fifos.append(fifo)
self.comb += [ self.comb += [
fifo.din.eq(input.payload.raw_bits()), fifo.din.eq(input.payload.raw_bits()),
@ -35,3 +45,40 @@ class FIFOs(Module):
output.readable.eq(fifo.readable), output.readable.eq(fifo.readable),
fifo.re.eq(output.re) fifo.re.eq(output.re)
] ]
if report_min_space:
if mode != "sync":
raise NotImplementedError
def compute_max(elts):
l = len(elts)
if l == 1:
return elts[0], 0
else:
maximum1, latency1 = compute_max(elts[:l//2])
maximum2, latency2 = compute_max(elts[l//2:])
maximum = Signal(max(len(maximum1), len(maximum2)))
self.sync += [
If(maximum1 > maximum2,
maximum.eq(maximum1)
).Else(
maximum.eq(maximum2)
)
]
latency = max(latency1, latency2) + 1
return maximum, latency
max_level, latency = compute_max([fifo.level for fifo in fifos])
max_level_valid = Signal()
max_level_valid_counter = Signal(max=latency)
self.sync += [
If(reduce(or_, [fifo.we for fifo in fifos]),
max_level_valid.eq(0),
max_level_valid_counter.eq(latency - 1)
).Elif(max_level_valid_counter == 0,
max_level_valid.eq(1)
).Else(
max_level_valid_counter.eq(max_level_valid_counter - 1)
)
]
self.comb += If(max_level_valid, self.min_space.eq(fifo_depth - max_level))