analyzer: use EOP, flush pipeline on stop

This commit is contained in:
Sebastien Bourdeauducq 2016-03-15 17:49:59 +08:00
parent fc60f3504c
commit 8a6873cab2
4 changed files with 108 additions and 62 deletions

View File

@ -19,6 +19,9 @@ InputMessage = namedtuple(
ExceptionMessage = namedtuple( ExceptionMessage = namedtuple(
"ExceptionMessage", "channel rtio_counter exception_type") "ExceptionMessage", "channel rtio_counter exception_type")
StoppedMessage = namedtuple(
"StoppedMessage", "rtio_counter")
def decode_message(data): def decode_message(data):
message_type_channel = struct.unpack(">I", data[28:32])[0] message_type_channel = struct.unpack(">I", data[28:32])[0]
@ -37,6 +40,11 @@ def decode_message(data):
exception_type, rtio_counter = struct.unpack(">BQ", data[11:20]) exception_type, rtio_counter = struct.unpack(">BQ", data[11:20])
return ExceptionMessage(channel, rtio_counter, return ExceptionMessage(channel, rtio_counter,
ExceptionType(exception_type)) ExceptionType(exception_type))
elif message_type == MessageType.stopped:
rtio_counter = struct.unpack(">Q", data[12:20])[0]
return StoppedMessage(rtio_counter)
else:
raise ValueError
DecodedDump = namedtuple( DecodedDump = namedtuple(

View File

@ -27,13 +27,23 @@ exception_layout = [
("padding1", 88) ("padding1", 88)
] ]
assert layout_len(input_output_layout) == 256 stopped_layout = [
assert layout_len(exception_layout) == 256 ("message_type", 2),
("padding0", 94),
("rtio_counter", 64),
("padding1", 96)
]
message_len = 256
assert layout_len(input_output_layout) == message_len
assert layout_len(exception_layout) == message_len
assert layout_len(stopped_layout) == message_len
class MessageEncoder(Module, AutoCSR): class MessageEncoder(Module, AutoCSR):
def __init__(self, rtio_core): def __init__(self, rtio_core, enable):
self.source = stream.Endpoint([("data", 256)]) self.source = stream.Endpoint([("data", message_len)])
self.overflow = CSRStatus() self.overflow = CSRStatus()
self.overflow_reset = CSR() self.overflow_reset = CSR()
@ -106,20 +116,38 @@ class MessageEncoder(Module, AutoCSR):
) )
] ]
stopped = Record(stopped_layout)
self.comb += [
stopped.message_type.eq(MessageType.stopped.value),
stopped.rtio_counter.eq(
rtio_core.counter.value_sys << rtio_core.fine_ts_width),
]
enable_r = Signal()
stopping = Signal()
self.sync += [ self.sync += [
enable_r.eq(enable),
If(~enable & enable_r, stopping.eq(1)),
If(~stopping,
If(exception_stb, If(exception_stb,
self.source.data.eq(exception.raw_bits()) self.source.data.eq(exception.raw_bits())
).Else( ).Else(
self.source.data.eq(input_output.raw_bits()) self.source.data.eq(input_output.raw_bits())
), ),
self.source.stb.eq(input_output_stb | exception_stb) self.source.stb.eq(enable &
] (input_output_stb | exception_stb)),
self.sync += [
If(self.overflow_reset.re, self.overflow.status.eq(0)), If(self.overflow_reset.re, self.overflow.status.eq(0)),
If(self.source.stb & ~self.source.ack, If(self.source.stb & ~self.source.ack,
self.overflow.status.eq(1) self.overflow.status.eq(1)
) )
).Else(
self.source.data.eq(stopped.raw_bits()),
self.source.eop.eq(1),
self.source.stb.eq(1),
If(self.source.ack, stopping.eq(0))
)
] ]
@ -127,77 +155,86 @@ class DMAWriter(Module, AutoCSR):
def __init__(self, membus): def __init__(self, membus):
aw = len(membus.adr) aw = len(membus.adr)
dw = len(membus.dat_w) dw = len(membus.dat_w)
messages_per_dw = dw//message_len
data_alignment = log2_int(dw//8) data_alignment = log2_int(dw//8)
# shutdown procedure: set enable to 0, wait until busy=0
self.enable = CSRStorage()
self.busy = CSRStatus()
self.reset = CSR() # only apply when shut down self.reset = CSR() # only apply when shut down
# All numbers in bytes # All numbers in bytes
self.base_address = CSRStorage(aw + data_alignment, self.base_address = CSRStorage(aw + data_alignment,
alignment_bits=data_alignment) alignment_bits=data_alignment)
self.last_address = CSRStorage(aw + data_alignment, self.last_address = CSRStorage(aw + data_alignment,
alignment_bits=data_alignment) alignment_bits=data_alignment)
self.byte_count = CSRStatus(64) # only read when shut down self.byte_count = CSRStatus(32) # only read when shut down
self.sink = stream.Endpoint([("data", dw)]) sink_layout = [("data", dw)]
if messages_per_dw > 1:
sink_layout.append(("valid_token_count",
bits_for(messages_per_dw)))
self.sink = stream.Endpoint(sink_layout)
# # # # # #
event_counter = Signal(63) self.comb += [
self.comb += self.byte_count.status.eq( membus.stb.eq(self.sink.stb),
event_counter << data_alignment) self.sink.ack.eq(membus.ack),
membus.we.eq(1),
membus.dat_w.eq(self.sink.data)
]
if messages_per_dw > 1:
for i in range(dw//8):
self.comb += membus.sel[i].eq(
self.sink.valid_token_count >= i//(256//8))
else:
self.comb += membus.sel.eq(2**(dw//8)-1)
fsm = FSM() self.sync += [
self.submodules += fsm
fsm.act("IDLE",
If(self.enable.storage & self.sink.stb,
NextState("WRITE")
),
If(~self.enable.storage,
self.sink.ack.eq(1)
),
If(self.reset.re, If(self.reset.re,
NextValue(membus.adr, self.base_address.storage), membus.adr.eq(self.base_address.storage)),
NextValue(event_counter, 0)
)
)
fsm.act("WRITE",
self.busy.status.eq(1),
membus.cyc.eq(1),
membus.stb.eq(1),
If(membus.ack, If(membus.ack,
If(membus.adr == self.last_address.storage, If(membus.adr == self.last_address.storage,
NextValue(membus.adr, self.base_address.storage) membus.adr.eq(self.base_address.storage)
).Else( ).Else(
NextValue(membus.adr, membus.adr + 1) membus.adr.eq(membus.adr + 1)
), ),
NextValue(event_counter, event_counter + 1),
self.sink.ack.eq(1),
NextState("IDLE")
) )
) ]
self.comb += [
membus.we.eq(1), event_counter = Signal(32)
membus.sel.eq(2**len(membus.sel)-1), self.comb += self.byte_count.status.eq(
membus.dat_w.eq(self.sink.data) event_counter << data_alignment)
self.sync += [
If(self.reset.re, event_counter.eq(0)),
If(membus.ack, event_counter.eq(event_counter + 1))
] ]
class Analyzer(Module, AutoCSR): class Analyzer(Module, AutoCSR):
def __init__(self, rtio_core, membus, fifo_depth=128): def __init__(self, rtio_core, membus, fifo_depth=128):
dw = len(membus.dat_w) # shutdown procedure: set enable to 0, wait until busy=0
self.enable = CSRStorage()
self.busy = CSRStatus()
self.submodules.message_encoder = MessageEncoder(rtio_core) self.submodules.message_encoder = MessageEncoder(
self.submodules.converter = stream.Converter(256, dw, reverse=True) rtio_core, self.enable.storage)
self.submodules.fifo = stream.SyncFIFO( self.submodules.fifo = stream.SyncFIFO(
[("data", dw)], fifo_depth, True) [("data", message_len)], fifo_depth, True)
dw = len(membus.dat_w)
self.submodules.converter = stream.Converter(
message_len, dw, reverse=True,
report_valid_token_count=dw > message_len)
self.submodules.dma = DMAWriter(membus) self.submodules.dma = DMAWriter(membus)
self.comb += [ enable_r = Signal()
self.message_encoder.source.connect(self.converter.sink), self.sync += [
self.converter.source.connect(self.fifo.sink), enable_r.eq(self.enable.storage),
self.fifo.source.connect(self.dma.sink) If(self.enable.storage & ~enable_r,
self.busy.status.eq(1)),
If(self.dma.sink.stb & self.dma.sink.ack & self.dma.sink.eop,
self.busy.status.eq(0))
]
self.comb += [
self.message_encoder.source.connect(self.fifo.sink),
self.fifo.source.connect(self.converter.sink),
self.converter.source.connect(self.dma.sink)
] ]

View File

@ -5,6 +5,7 @@ class MessageType(Enum):
output = 0b00 output = 0b00
input = 0b01 input = 0b01
exception = 0b10 exception = 0b10
stopped = 0b11
class ExceptionType(Enum): class ExceptionType(Enum):

View File

@ -27,13 +27,13 @@ static void arm(void)
rtio_analyzer_dma_base_address_write((unsigned int)analyzer_buffer); rtio_analyzer_dma_base_address_write((unsigned int)analyzer_buffer);
rtio_analyzer_dma_last_address_write((unsigned int)analyzer_buffer + ANALYZER_BUFFER_SIZE - 1); rtio_analyzer_dma_last_address_write((unsigned int)analyzer_buffer + ANALYZER_BUFFER_SIZE - 1);
rtio_analyzer_dma_reset_write(1); rtio_analyzer_dma_reset_write(1);
rtio_analyzer_dma_enable_write(1); rtio_analyzer_enable_write(1);
} }
static void disarm(void) static void disarm(void)
{ {
rtio_analyzer_dma_enable_write(0); rtio_analyzer_enable_write(0);
while(rtio_analyzer_dma_busy_read()); while(rtio_analyzer_busy_read());
flush_cpu_dcache(); flush_cpu_dcache();
flush_l2_cache(); flush_l2_cache();
} }