From 67a09aef0506d8b93b1fff7e38788f02d49f6c79 Mon Sep 17 00:00:00 2001 From: Florent Kermarrec Date: Thu, 5 Sep 2019 11:54:14 +0200 Subject: [PATCH] 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... --- litex/soc/interconnect/stream.py | 71 ++++++++++++++++++++++++++++++++ 1 file changed, 71 insertions(+) diff --git a/litex/soc/interconnect/stream.py b/litex/soc/interconnect/stream.py index 1bdaff0a..c99cff6d 100644 --- a/litex/soc/interconnect/stream.py +++ b/litex/soc/interconnect/stream.py @@ -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 -- 2.30.2