litex/misoclib/tools/litescope/core/storage.py

174 lines
5.4 KiB
Python

from misoclib.tools.litescope.common import *
from migen.flow.plumbing import Buffer
class LiteScopeSubSamplerUnit(Module):
def __init__(self, dw):
self.sink = sink = Sink(data_layout(dw))
self.source = source = Source(data_layout(dw))
self.value = Signal(32)
###
self.submodules.counter = Counter(32)
done = Signal()
self.comb += [
done.eq(self.counter.value >= self.value),
Record.connect(sink, source),
source.stb.eq(sink.stb & done),
self.counter.ce.eq(source.ack),
self.counter.reset.eq(source.stb & source.ack & done)
]
class LiteScopeSubSampler(LiteScopeSubSamplerUnit, AutoCSR):
def __init__(self, dw):
LiteScopeSubSamplerUnit.__init__(self, dw)
self._value = CSRStorage(32)
###
self.comb += self.value.eq(self._value.storage)
class LiteScopeRunLengthEncoderUnit(Module):
def __init__(self, dw, length):
self.dw = dw
self.length = length
self.sink = sink = Sink(data_layout(dw))
self.source = source = Source(data_layout(dw))
self.enable = Signal()
###
self.submodules.buf = buf = Buffer(sink.description)
self.comb += Record.connect(sink, buf.d)
self.submodules.counter = counter = Counter(max=length)
counter_done = Signal()
self.comb += counter_done.eq(counter.value == length-1)
change = Signal()
self.comb += change.eq(
sink.stb &
(sink.data != buf.q.data)
)
self.submodules.fsm = fsm = FSM(reset_state="BYPASS")
fsm.act("BYPASS",
Record.connect(buf.q, source),
counter.reset.eq(1),
If(sink.stb & ~change,
If(self.enable,
NextState("COUNT")
)
)
)
fsm.act("COUNT",
buf.q.ack.eq(1),
counter.ce.eq(sink.stb),
If(~self.enable,
NextState("BYPASS")
).Elif(change | counter_done,
source.stb.eq(1),
source.data[:flen(counter.value)].eq(counter.value),
source.data[-1].eq(1), # Set RLE bit
buf.q.ack.eq(source.ack),
If(source.ack,
NextState("BYPASS")
)
)
)
class LiteScopeRunLengthEncoder(LiteScopeRunLengthEncoderUnit, AutoCSR):
def __init__(self, dw, length=1024):
LiteScopeRunLengthEncoderUnit.__init__(self, dw, length)
self._enable = CSRStorage()
self.external_enable = Signal(reset=1)
###
self.comb += self.enable.eq(self._enable.storage & self.external_enable)
class LiteScopeRecorderUnit(Module):
def __init__(self, dw, depth):
self.dw = dw
self.depth = depth
self.trigger_sink = trigger_sink = Sink(hit_layout())
self.data_sink = data_sink = Sink(data_layout(dw))
self.trigger = Signal()
self.qualifier = Signal()
self.length = Signal(bits_for(depth))
self.offset = Signal(bits_for(depth))
self.done = Signal()
self.post_hit = Signal()
self.source = Source(data_layout(dw))
###
fifo = InsertReset(SyncFIFO(data_layout(dw), depth, buffered=True))
self.submodules += fifo
fsm = FSM(reset_state="IDLE")
self.submodules += fsm
self.comb += [
self.source.stb.eq(fifo.source.stb),
self.source.data.eq(fifo.source.data)
]
fsm.act("IDLE",
self.done.eq(1),
If(self.trigger,
NextState("PRE_HIT_RECORDING"),
fifo.reset.eq(1),
),
fifo.source.ack.eq(self.source.ack)
)
fsm.act("PRE_HIT_RECORDING",
fifo.sink.stb.eq(data_sink.stb),
fifo.sink.data.eq(data_sink.data),
data_sink.ack.eq(fifo.sink.ack),
fifo.source.ack.eq(fifo.fifo.level >= self.offset),
If(trigger_sink.stb & trigger_sink.hit, NextState("POST_HIT_RECORDING"))
)
fsm.act("POST_HIT_RECORDING",
self.post_hit.eq(1),
If(self.qualifier,
fifo.sink.stb.eq(trigger_sink.stb & trigger_sink.hit & data_sink.stb)
).Else(
fifo.sink.stb.eq(data_sink.stb)
),
fifo.sink.data.eq(data_sink.data),
data_sink.ack.eq(fifo.sink.ack),
If(~fifo.sink.ack | (fifo.fifo.level >= self.length), NextState("IDLE"))
)
class LiteScopeRecorder(LiteScopeRecorderUnit, AutoCSR):
def __init__(self, dw, depth):
LiteScopeRecorderUnit.__init__(self, dw, depth)
self._trigger = CSR()
self._qualifier = CSRStorage()
self._length = CSRStorage(bits_for(depth))
self._offset = CSRStorage(bits_for(depth))
self._done = CSRStatus()
self._source_stb = CSRStatus()
self._source_ack = CSR()
self._source_data = CSRStatus(dw)
###
self.comb += [
self.trigger.eq(self._trigger.re),
self.qualifier.eq(self._qualifier.storage),
self.length.eq(self._length.storage),
self.offset.eq(self._offset.storage),
self._done.status.eq(self.done),
self._source_stb.status.eq(self.source.stb),
self._source_data.status.eq(self.source.data),
self.source.ack.eq(self._source_ack.re)
]