forked from M-Labs/artiq
analyzer: use EOP, flush pipeline on stop
This commit is contained in:
parent
fc60f3504c
commit
8a6873cab2
|
@ -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(
|
||||||
|
|
|
@ -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)
|
||||||
]
|
]
|
||||||
|
|
|
@ -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):
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue