soc/interconnect/stream: add Monitor module

Generic module to monitor endpoints activity: tokens/overflows/underflows that
can be plugged on a endpoint. Can be useful for various purpose:
- endpoint bandwidth calculation.
- underflows/overflows detection.
- etc...
This commit is contained in:
Florent Kermarrec 2019-09-05 11:54:14 +02:00
parent 6f150a5626
commit 67a09aef05
1 changed files with 71 additions and 0 deletions

View File

@ -8,6 +8,9 @@ import math
from migen import *
from migen.genlib.record import *
from migen.genlib import fifo
from migen.genlib.cdc import MultiReg, PulseSynchronizer
from litex.soc.interconnect.csr import *
(DIR_SINK, DIR_SOURCE) = range(2)
@ -430,6 +433,74 @@ class Gearbox(Module):
else:
self.comb += source.data.eq(o_data[::-1])
class Monitor(Module, AutoCSR):
def __init__(self, endpoint, count_width=32, clock_domain="sys",
with_tokens=False,
with_overflows=False,
with_underflows=False):
self.reset = CSR()
self.latch = CSR()
if with_tokens:
self.tokens = CSRStatus(count_width)
if with_overflows:
self.overflows = CSRStatus(count_width)
if with_underflows:
self.underflows = CSRStatus(count_width)
# # #
reset = Signal()
latch = Signal()
if clock_domain == "sys":
self.comb += reset.eq(self.reset.re)
self.comb += latch.eq(self.latch.re)
else:
reset_ps = PulseSynchronizer("sys", clock_domain)
latch_ps = PulseSynchronizer("sys", clock_domain)
self.submodules += reset_ps, latch_ps
self.comb += reset_ps.i.eq(self.reset.re)
self.comb += reset.eq(reset_ps.o)
self.comb += latch_ps.i.eq(self.latch.re)
self.comb += latch.eq(latch_ps.o)
# Generic Monitor Counter ------------------------------------------------------------------
class MonitorCounter(Module):
def __init__(self, reset, latch, enable, count):
_count = Signal.like(count)
_count_latched = Signal.like(count)
_sync = getattr(self.sync, clock_domain)
_sync += [
If(reset,
_count.eq(0),
_count_latched.eq(0),
).Elif(enable,
If(_count != (2**len(count)-1),
_count.eq(_count + 1)
)
),
If(latch,
_count_latched.eq(_count)
)
]
self.specials += MultiReg(_count_latched, count)
# Tokens Count -----------------------------------------------------------------------------
if with_tokens:
tokens_counter = MonitorCounter(reset, latch, endpoint.valid & endpoint.ready, self.tokens.status)
self.submodules += token_counter
# Overflows Count (only useful when endpoint is expected to always be ready) ---------------
if with_overflows:
overflow_counter = MonitorCounter(reset, latch, endpoint.valid & ~endpoint.ready, self.overflows.status)
self.submodules += overflow_counter
# Underflows Count (only useful when endpoint is expected to always be valid) --------------
if with_underflows:
underflow_counter = MonitorCounter(reset, latch, ~endpoint.valid & endpoint.ready, self.underflows.status)
self.submodules += underflow_counter
# TODO: clean up code below
# XXX