From 8fb22543c91b16577470195d59ec05e6fe9f6cb4 Mon Sep 17 00:00:00 2001 From: Mateusz Faderewski Date: Thu, 15 Aug 2024 21:02:15 +0200 Subject: [PATCH] better PI IO activity monitoring --- fw/rtl/mcu/mcu_top.sv | 17 +++-- fw/rtl/n64/n64_cic.sv | 6 +- fw/rtl/n64/n64_pi.sv | 29 ++++--- fw/rtl/n64/n64_scb.sv | 22 ++++-- sw/deployer/src/main.rs | 5 +- sw/deployer/src/sc64/types.rs | 138 +++++++++++++++++++++++----------- 6 files changed, 143 insertions(+), 74 deletions(-) diff --git a/fw/rtl/mcu/mcu_top.sv b/fw/rtl/mcu/mcu_top.sv index 58b347a..c9efa11 100644 --- a/fw/rtl/mcu/mcu_top.sv +++ b/fw/rtl/mcu/mcu_top.sv @@ -371,6 +371,8 @@ module mcu_top ( logic dd_bm_ack; + logic [31:0] debug_buffer; + logic cic_invalid_region; logic aux_pending; @@ -649,15 +651,18 @@ module mcu_top ( end REG_DEBUG_0: begin - reg_rdata <= n64_scb.pi_debug[31:0]; + reg_rdata <= n64_scb.pi_debug_address; + debug_buffer <= { + 6'd0, + n64_scb.pi_debug_direction, + n64_scb.pi_debug_rw_count, + n64_scb.cic_debug_step, + n64_scb.pi_debug_fifo_flags + }; end REG_DEBUG_1: begin - reg_rdata <= { - 24'd0, - n64_scb.cic_debug, - n64_scb.pi_debug[35:32] - }; + reg_rdata <= debug_buffer; end REG_CIC_0: begin diff --git a/fw/rtl/n64/n64_cic.sv b/fw/rtl/n64/n64_cic.sv index f0dd4ec..75719e4 100644 --- a/fw/rtl/n64/n64_cic.sv +++ b/fw/rtl/n64/n64_cic.sv @@ -192,7 +192,7 @@ module n64_cic ( end 2'b11: begin - n64_scb.cic_debug <= dbus_wdata[3:0]; + n64_scb.cic_debug_step <= dbus_wdata[3:0]; end endcase end @@ -200,7 +200,7 @@ module n64_cic ( end if (reset) begin - n64_scb.cic_debug <= 3'd0; + n64_scb.cic_debug_step <= 3'd0; end if (reset || !cic_reset) begin @@ -236,7 +236,7 @@ module n64_cic ( cic_dq }; - 2'b11: dbus_rdata = {28'd0, n64_scb.cic_debug}; + 2'b11: dbus_rdata = {28'd0, n64_scb.cic_debug_step}; endcase end endcase diff --git a/fw/rtl/n64/n64_pi.sv b/fw/rtl/n64/n64_pi.sv index af1944a..0d951f8 100644 --- a/fw/rtl/n64/n64_pi.sv +++ b/fw/rtl/n64/n64_pi.sv @@ -127,12 +127,21 @@ module n64_pi ( // Debug: last accessed PI address + logic [15:0] pi_debug_address_buffer; + always_ff @(posedge clk) begin if (aleh_op) begin - n64_scb.pi_debug[31:16] <= n64_pi_dq_in; + pi_debug_address_buffer <= n64_pi_dq_in; end if (alel_op) begin - n64_scb.pi_debug[15:0] <= n64_pi_dq_in; + n64_scb.pi_debug_address <= {pi_debug_address_buffer, n64_pi_dq_in}; + n64_scb.pi_debug_rw_count <= 17'd0; + end + if (pi_reset && (pi_mode == PI_MODE_VALID)) begin + if ((last_read && !pi_read) || (last_write && !pi_write)) begin + n64_scb.pi_debug_rw_count <= n64_scb.pi_debug_rw_count + 1'd1; + n64_scb.pi_debug_direction <= !pi_write; + end end end @@ -296,11 +305,11 @@ module n64_pi ( .reset(reset), .flush(reset || !pi_reset || alel_op), - + .full(read_fifo_full), .write(read_fifo_write), .wdata(read_fifo_wdata), - + .empty(read_fifo_empty), .read(read_fifo_read), .rdata(read_fifo_rdata) @@ -310,7 +319,7 @@ module n64_pi ( read_fifo_read <= 1'b0; if (!pi_reset) begin - n64_scb.pi_debug[33:32] <= 2'b00; + n64_scb.pi_debug_fifo_flags[1:0] <= 2'b00; end if (reset || !pi_reset || alel_op) begin @@ -321,9 +330,9 @@ module n64_pi ( if (read_op) begin if (read_fifo_empty) begin read_fifo_wait <= 1'b1; - n64_scb.pi_debug[32] <= 1'b1; + n64_scb.pi_debug_fifo_flags[0] <= 1'b1; if (read_fifo_wait) begin - n64_scb.pi_debug[33] <= 1'b1; + n64_scb.pi_debug_fifo_flags[1] <= 1'b1; end end else begin read_fifo_read <= 1'b1; @@ -377,7 +386,7 @@ module n64_pi ( write_fifo_write <= 1'b0; if (!pi_reset) begin - n64_scb.pi_debug[35:34] <= 2'b00; + n64_scb.pi_debug_fifo_flags[3:2] <= 2'b00; end if (reset) begin @@ -388,9 +397,9 @@ module n64_pi ( if (write_op) begin if (write_fifo_full) begin write_fifo_wait <= 1'b1; - n64_scb.pi_debug[34] <= 1'b1; + n64_scb.pi_debug_fifo_flags[2] <= 1'b1; if (write_fifo_wait) begin - n64_scb.pi_debug[35] <= 1'b1; + n64_scb.pi_debug_fifo_flags[3] <= 1'b1; end end else begin write_fifo_write <= 1'b1; diff --git a/fw/rtl/n64/n64_scb.sv b/fw/rtl/n64/n64_scb.sv index 8a8f18b..77efa6f 100644 --- a/fw/rtl/n64/n64_scb.sv +++ b/fw/rtl/n64/n64_scb.sv @@ -68,11 +68,14 @@ interface n64_scb (); logic cic_region; logic [7:0] cic_seed; logic [47:0] cic_checksum; - logic [3:0] cic_debug; + logic [3:0] cic_debug_step; logic pi_sdram_active; logic pi_flash_active; - logic [35:0] pi_debug; + logic [31:0] pi_debug_address; + logic [16:0] pi_debug_rw_count; + logic pi_debug_direction; + logic [3:0] pi_debug_fifo_flags; modport controller ( input n64_reset, @@ -126,9 +129,12 @@ interface n64_scb (); output cic_region, output cic_seed, output cic_checksum, - input cic_debug, + input cic_debug_step, - input pi_debug + input pi_debug_address, + input pi_debug_rw_count, + input pi_debug_direction, + input pi_debug_fifo_flags ); modport pi ( @@ -153,7 +159,11 @@ interface n64_scb (); output pi_sdram_active, output pi_flash_active, - output pi_debug + + output pi_debug_address, + output pi_debug_rw_count, + output pi_debug_direction, + output pi_debug_fifo_flags ); modport flashram ( @@ -249,7 +259,7 @@ interface n64_scb (); input cic_region, input cic_seed, input cic_checksum, - output cic_debug + output cic_debug_step ); modport arbiter ( diff --git a/sw/deployer/src/main.rs b/sw/deployer/src/main.rs index 8e3b3d7..d986841 100644 --- a/sw/deployer/src/main.rs +++ b/sw/deployer/src/main.rs @@ -794,10 +794,7 @@ fn handle_info_command(connection: Connection) -> Result<(), sc64::Error> { println!(" LED blink: {}", state.led_enable); println!(" IS-Viewer 64: {}", state.isviewer); println!("{}", "SummerCart64 diagnostic information:".bold()); - println!( - " Last PI address: 0x{:08X}", - state.fpga_debug_data.last_pi_address - ); + println!(" PI I/O access: {}", state.fpga_debug_data.pi_io_access); println!( " PI FIFO flags: {}", state.fpga_debug_data.pi_fifo_flags diff --git a/sw/deployer/src/sc64/types.rs b/sw/deployer/src/sc64/types.rs index d3c476a..647dcc6 100644 --- a/sw/deployer/src/sc64/types.rs +++ b/sw/deployer/src/sc64/types.rs @@ -833,6 +833,90 @@ impl TryFrom for UpdateStatus { } } +pub enum PiIODirection { + Read, + Write, +} + +impl Display for PiIODirection { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.write_str(match self { + Self::Read => "read", + Self::Write => "written", + }) + } +} + +pub struct PiIOAccess { + pub address: u32, + pub count: u32, + pub direction: PiIODirection, +} + +impl From<&[u8; 8]> for PiIOAccess { + fn from(value: &[u8; 8]) -> Self { + let address = u32::from_be_bytes(value[0..4].try_into().unwrap()); + let info = u32::from_be_bytes(value[4..8].try_into().unwrap()); + let count = (info >> 8) & 0x1FFFF; + let direction = if (info & (1 << 25)) == 0 { + PiIODirection::Read + } else { + PiIODirection::Write + }; + PiIOAccess { + address, + count, + direction, + } + } +} + +impl Display for PiIOAccess { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.write_fmt(format_args!("0x{:08X}", self.address))?; + if self.count > 0 { + f.write_fmt(format_args!(" {} bytes {}", self.count * 2, self.direction))?; + } + Ok(()) + } +} + +pub struct PiFifoFlags { + pub read_fifo_wait: bool, + pub read_fifo_failure: bool, + pub write_fifo_wait: bool, + pub write_fifo_failure: bool, +} + +impl Display for PiFifoFlags { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + let mapping = vec![ + (self.read_fifo_wait, "Read wait"), + (self.read_fifo_failure, "Read failure"), + (self.write_fifo_wait, "Write wait"), + (self.write_fifo_failure, "Write failure"), + ]; + let filtered: Vec<&str> = mapping.into_iter().filter(|x| x.0).map(|x| x.1).collect(); + if filtered.len() > 0 { + f.write_str(filtered.join(", ").as_str())?; + } else { + f.write_str("None")?; + } + Ok(()) + } +} + +impl From<&[u8; 8]> for PiFifoFlags { + fn from(value: &[u8; 8]) -> Self { + PiFifoFlags { + read_fifo_wait: (value[7] & (1 << 0)) != 0, + read_fifo_failure: (value[7] & (1 << 1)) != 0, + write_fifo_wait: (value[7] & (1 << 2)) != 0, + write_fifo_failure: (value[7] & (1 << 3)) != 0, + } + } +} + pub enum CicStep { Unavailable, PowerOff, @@ -875,10 +959,10 @@ impl Display for CicStep { } } -impl TryFrom for CicStep { - type Error = Error; - fn try_from(value: u8) -> Result { - Ok(match value { +impl From<&[u8; 8]> for CicStep { + fn from(value: &[u8; 8]) -> Self { + let cic_step = (value[7] >> 4) & 0x0F; + match cic_step { 0 => Self::Unavailable, 1 => Self::PowerOff, 2 => Self::ConfigLoad, @@ -895,49 +979,12 @@ impl TryFrom for CicStep { 13 => Self::DieInvalidRegion, 14 => Self::DieCommand, _ => Self::Unknown, - }) - } -} - -pub struct PiFifoFlags { - pub read_fifo_wait: bool, - pub read_fifo_failure: bool, - pub write_fifo_wait: bool, - pub write_fifo_failure: bool, -} - -impl Display for PiFifoFlags { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - let mapping = vec![ - (self.read_fifo_wait, "Read wait"), - (self.read_fifo_failure, "Read failure"), - (self.write_fifo_wait, "Write wait"), - (self.write_fifo_failure, "Write failure"), - ]; - let filtered: Vec<&str> = mapping.into_iter().filter(|x| x.0).map(|x| x.1).collect(); - if filtered.len() > 0 { - f.write_str(filtered.join(", ").as_str())?; - } else { - f.write_str("None")?; } - Ok(()) - } -} - -impl TryFrom for PiFifoFlags { - type Error = Error; - fn try_from(value: u8) -> Result { - Ok(PiFifoFlags { - read_fifo_wait: (value & (1 << 0)) != 0, - read_fifo_failure: (value & (1 << 1)) != 0, - write_fifo_wait: (value & (1 << 2)) != 0, - write_fifo_failure: (value & (1 << 3)) != 0, - }) } } pub struct FpgaDebugData { - pub last_pi_address: u32, + pub pi_io_access: PiIOAccess, pub pi_fifo_flags: PiFifoFlags, pub cic_step: CicStep, } @@ -948,10 +995,11 @@ impl TryFrom> for FpgaDebugData { if value.len() != 8 { return Err(Error::new("Invalid data length for FPGA debug data")); } + let data: &[u8; 8] = &value[0..8].try_into().unwrap(); Ok(FpgaDebugData { - last_pi_address: u32::from_be_bytes(value[0..4].try_into().unwrap()), - pi_fifo_flags: (value[7] & 0x0F).try_into().unwrap(), - cic_step: ((value[7] >> 4) & 0x0F).try_into().unwrap(), + pi_io_access: data.into(), + pi_fifo_flags: data.into(), + cic_step: data.into(), }) } }