Skip to content

Commit

Permalink
coredevice: analyzer message decoding
Browse files Browse the repository at this point in the history
sbourdeauducq committed Dec 20, 2015
1 parent d521687 commit 46f59b6
Showing 3 changed files with 88 additions and 52 deletions.
77 changes: 77 additions & 0 deletions artiq/coredevice/analyzer.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
from enum import Enum
from collections import namedtuple
import struct
import logging


logger = logging.getLogger(__name__)


class MessageType(Enum):
output = 0b00
input = 0b01
exception = 0b10


class ExceptionType(Enum):
reset_rising = 0b000000
reset_falling = 0b000001
reset_phy_rising = 0b000010
reset_phy_falling = 0b000011

o_underflow_reset = 0b010000
o_sequence_error_reset = 0b010001
o_collision_error_reset = 0b010010

i_overflow_reset = 0b100000


OutputMessage = namedtuple(
"OutputMessage", "channel timestamp rtio_counter address data")

InputMessage = namedtuple(
"InputMessage", "channel timestamp rtio_counter data")

ExceptionMessage = namedtuple(
"ExceptionMessage", "channel rtio_counter exception_type")


def decode_message(data):
message_type_channel = struct.unpack(">I", data[28:32])[0]
message_type = MessageType(message_type_channel & 0b11)
channel = message_type_channel >> 2

if message_type == MessageType.output:
parts = struct.unpack(">QIQQ", data[:28])
data, address, rtio_counter, timestamp = parts
return OutputMessage(channel, timestamp, rtio_counter, address, data)
elif message_type == MessageType.input:
parts = struct.unpack(">QIQQ", data[:28])
data, _, rtio_counter, timestamp = parts
return InputMessage(channel, timestamp, rtio_counter, data)
elif message_type == MessageType.exception:
exception_type, rtio_counter = struct.unpack(">BQ", data[11:20])
return ExceptionMessage(channel, rtio_counter,
ExceptionType(exception_type))


def decode_dump(data):
parts = struct.unpack(">IQI", data[:16])
sent_bytes, total_byte_count, overflow_occured = parts

if sent_bytes + 16 != len(data):
raise ValueError("analyzer dump has incorrect length")
if overflow_occured:
logger.warning("analyzer FIFO overflow occured, "
"some messages have been lost")
if total_byte_count > sent_bytes:
logger.info("analyzer ring buffer has wrapped %d times",
total_byte_count//sent_bytes)

position = 16
messages = []
for _ in range(sent_bytes//32):
messages.append(decode_message(data[position:position+32]))
position += 32
return messages

25 changes: 3 additions & 22 deletions artiq/frontend/artiq_coretool.py
Original file line number Diff line number Diff line change
@@ -5,27 +5,7 @@

from artiq.master.databases import DeviceDB
from artiq.master.worker_db import DeviceManager


def print_analyzer_dump(dump):
sent_bytes, total_byte_count, overflow_occured = struct.unpack(">IQI", dump[:16])
dump = dump[16:]
print(sent_bytes, total_byte_count, overflow_occured)

while dump:
message_type_channel = struct.unpack(">I", dump[28:32])[0]
message_type = message_type_channel & 0b11
channel = message_type_channel >> 2

if message_type == 2:
exception_type, rtio_counter = struct.unpack(">BQ", dump[11:20])
print("EXC exception_type={} channel={} rtio_counter={}"
.format(exception_type, channel, rtio_counter))
else:
(data, address_padding, rtio_counter, timestamp) = struct.unpack(">QIQQ", dump[:28])
print("IO type={} channel={} timestamp={} rtio_counter={} address_padding={} data={}"
.format(message_type, channel, timestamp, rtio_counter, address_padding, data))
dump = dump[32:]
from artiq.coredevice.analyzer import decode_dump


def get_argparser():
@@ -100,7 +80,8 @@ def main():
comm.flash_storage_erase()
elif args.action == "analyzer-dump":
dump = comm.get_analyzer_dump()
print_analyzer_dump(dump)
for msg in decode_dump(dump):
print(msg)
finally:
device_mgr.close_devices()

38 changes: 8 additions & 30 deletions artiq/gateware/rtio/analyzer.py
Original file line number Diff line number Diff line change
@@ -3,6 +3,8 @@
from misoc.interconnect.csr import *
from misoc.interconnect import stream

from artiq.coredevice.analyzer import MessageType, ExceptionType


__all__ = ["Analyzer"]

@@ -29,34 +31,10 @@
assert layout_len(exception_layout) == 256


class MessageTypes(AutoCSR):
def __init__(self):
self.output = CSRConstant(0b00)
self.input = CSRConstant(0b01)
self.exception = CSRConstant(0b10)


class ExceptionTypes(AutoCSR):
def __init__(self):
self.reset_rising = CSRConstant(0b000000)
self.reset_falling = CSRConstant(0b000001)
self.reset_phy_rising = CSRConstant(0b000010)
self.reset_phy_falling = CSRConstant(0b000011)

self.o_underflow_reset = CSRConstant(0b010000)
self.o_sequence_error_reset = CSRConstant(0b010001)
self.o_collision_error_reset = CSRConstant(0b010010)

self.i_overflow_reset = CSRConstant(0b100000)


class MessageEncoder(Module, AutoCSR):
def __init__(self, rtio_core):
self.source = stream.Endpoint([("data", 256)])

self.message_types = MessageTypes()
self.exception_types = ExceptionTypes()

self.overflow = CSRStatus()
self.overflow_reset = CSR()

@@ -84,11 +62,11 @@ def __init__(self, rtio_core):
input_output.rtio_counter.eq(
rtio_core.counter.value_sys << rtio_core.fine_ts_width),
If(kcsrs.o_we.re,
input_output.message_type.eq(self.message_types.output.value),
input_output.message_type.eq(MessageType.output.value),
input_output.timestamp.eq(kcsrs.o_timestamp.storage),
input_output.data.eq(o_data)
).Else(
input_output.message_type.eq(self.message_types.input.value),
input_output.message_type.eq(MessageType.input.value),
input_output.timestamp.eq(kcsrs.i_timestamp.status),
input_output.data.eq(i_data)
),
@@ -98,7 +76,7 @@ def __init__(self, rtio_core):
exception_stb = Signal()
exception = Record(exception_layout)
self.comb += [
exception.message_type.eq(self.message_types.exception.value),
exception.message_type.eq(MessageType.exception.value),
exception.channel.eq(kcsrs.chan_sel.storage),
exception.rtio_counter.eq(
rtio_core.counter.value_sys << rtio_core.fine_ts_width),
@@ -109,7 +87,7 @@ def __init__(self, rtio_core):
If(getattr(kcsrs, ename).re,
exception_stb.eq(1),
exception.exception_type.eq(
getattr(self.exception_types, ename).value)
getattr(ExceptionType, ename).value)
)
for rname in "reset", "reset_phy":
r_d = Signal()
@@ -119,12 +97,12 @@ def __init__(self, rtio_core):
If(r & ~r_d,
exception_stb.eq(1),
exception.exception_type.eq(
getattr(self.exception_types, rname+"_rising").value)
getattr(ExceptionType, rname+"_rising").value)
),
If(~r & r_d,
exception_stb.eq(1),
exception.exception_type.eq(
getattr(self.exception_types, rname+"_falling").value)
getattr(ExceptionType, rname+"_falling").value)
)
]

0 comments on commit 46f59b6

Please sign in to comment.