diff --git a/artiq/coredevice/comm_analyzer.py b/artiq/coredevice/comm_analyzer.py index 45766f3400..ad428148a8 100644 --- a/artiq/coredevice/comm_analyzer.py +++ b/artiq/coredevice/comm_analyzer.py @@ -307,6 +307,83 @@ def process_read(self, address, data, read_slack): raise NotImplementedError +class GenericWishboneHandler(WishboneHandler): + """Generic Wishbone Bus Data Handler. + + Useful for testing out-of-tree PHY devices and viewing their bus transactions + in a VCD file. + """ + + comm_buses_and_width = { + "out_address": 8, + "out_data": 32, + "out_stb": 1, + "in_data": 14, + "in_stb": 1 + } + def __init__(self, vcd_manager, name, channel): + """Create the Wishbone Data Handler. + + Args: + vcd_manager (VCDManager): VCD Manager to add this device's channels to. + name (str): Name of the coredevice that communicates on this channel. + """ + self.channels = {} + with vcd_manager.scope("bus_device/{}(chan{})".format(name, channel)): + for bus_name, bus_width in self.comm_buses_and_width.items(): + self.channels[bus_name] = vcd_manager.get_channel( + "{}/{}".format(name, bus_name), + bus_width + ) + + def set_channel(self, channel_name, value): + """Set channel to a specific value. + + Formats the data properly for interpretation by VCD viewer + (on a per-channel basis). + + Args: + channel_name (str): Name of the channel to write + value (int): Value to be stored to VCD. Should be some sort of integer. + """ + # format all outputs as binary of proper length + chan_fmt_string = "{{:0{}b}}".format(self.comm_buses_and_width[channel_name]) + self.channels[channel_name].set_value(chan_fmt_string.format(value)) + + def process_message(self, message): + """Process a Wishbone message into VCD events. + + Args: + message (typing.Union[InputMessage, OutputMessage]): + A message from the coredevice, either an InputMessage + (signal from PHY to coredevice) or an OutputMessage + (signal from coredevice to PHY). + """ + # TODO: doesn't reset bus (addr/data) to 0 after bus transaction is done + # TODO: stb doesn't display width, but edges register when jumping through waveform + if isinstance(message, OutputMessage): + logger.debug( + "Wishbone out @%d adr=0x%02x data=0x%08x", + message.timestamp, + message.address, + message.data + ) + self.set_channel("out_stb", 1) + self.set_channel("out_stb", 0) + self.set_channel("out_address", message.address) + self.set_channel("out_data", message.data) + elif isinstance(message, InputMessage): + logger.debug( + "Wishbone in @%d(ts=%d) data=0x%08x", + message.rtio_counter, + message.timestamp, + message.data + ) + self.set_channel("in_data", message.data) + self.set_channel("in_stb", 1) + self.set_channel("in_stb", 0) + + class SPIMasterHandler(WishboneHandler): def __init__(self, vcd_manager, name): self.channels = {}