From d677c989a80811445b052c2596563489bb2693cf Mon Sep 17 00:00:00 2001 From: Martin Ling Date: Tue, 16 Jul 2024 11:21:15 +0100 Subject: [PATCH] Emit event on buffer overrun. --- .../python/src/gateware/analyzer/analyzer.py | 47 ++++++++++++------- 1 file changed, 29 insertions(+), 18 deletions(-) diff --git a/cynthion/python/src/gateware/analyzer/analyzer.py b/cynthion/python/src/gateware/analyzer/analyzer.py index c97929f5..633c5ffe 100644 --- a/cynthion/python/src/gateware/analyzer/analyzer.py +++ b/cynthion/python/src/gateware/analyzer/analyzer.py @@ -229,26 +229,31 @@ def elaborate(self, platform): # Capture data until the packet is complete. with m.State("CAPTURE_PACKET"): - byte_received = self.utmi.rx_valid & self.utmi.rx_active + # Is the packet still ongoing? + with m.If(self.utmi.rx_active): - # Capture data whenever RxValid is asserted. - m.d.comb += [ - write_packet .eq(byte_received), - ] + # Did we receive a byte? + with m.If(self.utmi.rx_valid): - # Advance the write pointer each time we receive a bit. - with m.If(byte_received): - m.d.usb += [ - packet_size .eq(packet_size + 1), - ] + # Would one more word fill up our buffer? + words_allocated = fifo_word_count + fifo_words_pending + with m.If(words_allocated == self.mem_size_words - 1): + # Write a CAPTURE_FULL event instead of the packet. + m.d.comb += [ + write_event .eq(1), + event_code .eq(USBAnalyzerEvent.CAPTURE_FULL), + ] - # If this would be filling up our data memory, - # move to the OVERRUN state. - with m.If(fifo_word_count + fifo_words_pending == self.mem_size_words - 1): - m.next = "OVERRUN" + # Wait in the OVERRUN state until restarted. + m.next = "OVERRUN" + + with m.Else(): + # Write packet byte and increase packet size. + m.d.comb += write_packet.eq(1) + m.d.usb += packet_size.eq(packet_size + 1) # If we've stopped receiving, write header. - with m.If(~self.utmi.rx_active): + with m.Else(): m.d.comb += [ write_header .eq(1), ] @@ -264,7 +269,6 @@ def elaborate(self, platform): with m.State("OVERRUN"): - # TODO: we should probably set an overrun flag and then emit an EOP, here? # If capture is stopped by the host, reset back to the ready state. with m.If(~self.capture_enable): @@ -277,6 +281,13 @@ def elaborate(self, platform): next_byte_addr_aligned = Mux(self.starting, 0, write_byte_addr + write_odd) next_word_addr = next_byte_addr_aligned[1:] + # The CAPTURE_FULL event is written in place of a packet header. + # Other events are written at the next word address. + event_word_addr = Mux( + event_code == USBAnalyzerEvent.CAPTURE_FULL, + header_word_addr, + next_word_addr) + with m.FSM(domain="sync"): # START: Begin write operation when requested. with m.State("START"): @@ -311,7 +322,7 @@ def elaborate(self, platform): with m.Elif(write_event): # Write event identifier and event code. m.d.comb += [ - mem_write_port.addr .eq(next_word_addr), + mem_write_port.addr .eq(event_word_addr), mem_write_port.data .eq(Cat(event_code, C(0xFF, 8))), mem_write_port.en .eq(0b11), ] @@ -335,7 +346,7 @@ def elaborate(self, platform): # FINISH_EVENT: Write second word of event. with m.State("FINISH_EVENT"): m.d.comb += [ - mem_write_port.addr .eq(header_word_addr + 1), + mem_write_port.addr .eq(event_word_addr + 1), mem_write_port.data .eq(current_time), mem_write_port.en .eq(0b11), data_commit .eq(1),