From 470f1b21400645e42417c7baa779d0555e875709 Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Thu, 12 Nov 2020 15:06:38 +1100 Subject: [PATCH] core_debug: Add an address trigger to stop logging at a given address This compares the address being fetched with the contents of a register that can be set via DMI, and if they match, stops the logging. Since this works on the address being fetched rather than executed, it is subject to false positives. Signed-off-by: Paul Mackerras --- core_debug.vhdl | 17 +++++++++++- scripts/mw_debug/mw_debug.c | 55 +++++++++++++++++++++++++++++++++---- 2 files changed, 65 insertions(+), 7 deletions(-) diff --git a/core_debug.vhdl b/core_debug.vhdl index 9efaa7c..09e3e48 100644 --- a/core_debug.vhdl +++ b/core_debug.vhdl @@ -91,6 +91,7 @@ architecture behave of core_debug is -- Log buffer address and data registers constant DBG_CORE_LOG_ADDR : std_ulogic_vector(3 downto 0) := "0110"; constant DBG_CORE_LOG_DATA : std_ulogic_vector(3 downto 0) := "0111"; + constant DBG_CORE_LOG_TRIGGER : std_ulogic_vector(3 downto 0) := "1000"; constant LOG_INDEX_BITS : natural := log2(LOG_LENGTH); @@ -108,6 +109,8 @@ architecture behave of core_debug is signal log_dmi_addr : std_ulogic_vector(31 downto 0) := (others => '0'); signal log_dmi_data : std_ulogic_vector(63 downto 0) := (others => '0'); + signal log_dmi_trigger : std_ulogic_vector(63 downto 0) := (others => '0'); + signal do_log_trigger : std_ulogic := '0'; signal do_dmi_log_rd : std_ulogic; signal dmi_read_log_data : std_ulogic; signal dmi_read_log_data_1 : std_ulogic; @@ -133,6 +136,7 @@ begin dbg_gpr_data when DBG_CORE_GSPR_DATA, log_write_addr & log_dmi_addr when DBG_CORE_LOG_ADDR, log_dmi_data when DBG_CORE_LOG_DATA, + log_dmi_trigger when DBG_CORE_LOG_TRIGGER, (others => '0') when others; -- DMI writes @@ -149,6 +153,9 @@ begin stopping <= '0'; terminated <= '0'; else + if do_log_trigger = '1' then + log_dmi_trigger(1) <= '1'; + end if; -- Edge detect on dmi_req for 1-shot pulses dmi_req_1 <= dmi_req; if dmi_req = '1' and dmi_req_1 = '0' then @@ -180,6 +187,8 @@ begin elsif dmi_addr = DBG_CORE_LOG_ADDR then log_dmi_addr <= dmi_din(31 downto 0); do_dmi_log_rd <= '1'; + elsif dmi_addr = DBG_CORE_LOG_TRIGGER then + log_dmi_trigger <= dmi_din; end if; else report("DMI read from " & to_string(dmi_addr)); @@ -246,7 +255,7 @@ begin begin -- Use MSB of read addresses to stop the logging - log_wr_enable <= not (log_read_addr(31) or log_dmi_addr(31)); + log_wr_enable <= not (log_read_addr(31) or log_dmi_addr(31) or log_dmi_trigger(1)); log_ram: process(clk) begin @@ -285,6 +294,12 @@ begin end if; log_dmi_read_done <= log_dmi_reading; log_dmi_reading <= do_dmi_log_rd; + do_log_trigger <= '0'; + if log_data(42) = log_dmi_trigger(63) and + log_data(41 downto 0) = log_dmi_trigger(43 downto 2) and + log_dmi_trigger(0) = '1' then + do_log_trigger <= '1'; + end if; end if; end process; log_write_addr(LOG_INDEX_BITS - 1 downto 0) <= std_ulogic_vector(log_wr_ptr); diff --git a/scripts/mw_debug/mw_debug.c b/scripts/mw_debug/mw_debug.c index d03e61c..4179264 100644 --- a/scripts/mw_debug/mw_debug.c +++ b/scripts/mw_debug/mw_debug.c @@ -44,6 +44,7 @@ #define DBG_LOG_ADDR 0x16 #define DBG_LOG_DATA 0x17 +#define DBG_LOG_TRIGGER 0x18 static bool debug; @@ -466,8 +467,11 @@ static void gpr_read(uint64_t reg, uint64_t count) static void mem_read(uint64_t addr, uint64_t count) { - uint64_t data; - int i, rc; + union { + uint64_t data; + unsigned char c[8]; + } u; + int i, j, rc; rc = dmi_write(DBG_WB_CTRL, 0x7ff); if (rc < 0) @@ -476,12 +480,15 @@ static void mem_read(uint64_t addr, uint64_t count) if (rc < 0) return; for (i = 0; i < count; i++) { - rc = dmi_read(DBG_WB_DATA, &data); + rc = dmi_read(DBG_WB_DATA, &u.data); if (rc < 0) return; - printf("%016llx: %016llx\n", + printf("%016llx: %016llx ", (unsigned long long)addr, - (unsigned long long)data); + (unsigned long long)u.data); + for (j = 0; j < 8; ++j) + putchar(u.c[j] >= 0x20 && u.c[j] < 0x7f? u.c[j]: '.'); + putchar('\n'); addr += 8; } } @@ -622,6 +629,28 @@ static void log_dump(const char *filename) check(dmi_write(DBG_LOG_ADDR, orig_laddr), "writing LOG_ADDR"); } +static void ltrig_show(void) +{ + uint64_t trig; + + check(dmi_read(DBG_LOG_TRIGGER, &trig), "reading LOG_TRIGGER"); + if (trig & 1) + printf("log stop trigger at %" PRIx64, trig & ~3); + else + printf("log stop trigger disabled"); + printf(", %striggered\n", (trig & 2? "": "not ")); +} + +static void ltrig_off(void) +{ + check(dmi_write(DBG_LOG_TRIGGER, 0), "writing LOG_TRIGGER"); +} + +static void ltrig_set(uint64_t addr) +{ + check(dmi_write(DBG_LOG_TRIGGER, (addr & ~(uint64_t)2) | 1), "writing LOG_TRIGGER"); +} + static void usage(const char *cmd) { fprintf(stderr, "Usage: %s -b \n", cmd); @@ -651,6 +680,9 @@ static void usage(const char *cmd) fprintf(stderr, " lstart start logging\n"); fprintf(stderr, " lstop stop logging\n"); fprintf(stderr, " ldump dump log to file\n"); + fprintf(stderr, " ltrig show logging stop trigger status\n"); + fprintf(stderr, " ltrig off clear logging stop trigger address\n"); + fprintf(stderr, " ltrig set logging stop trigger address\n"); fprintf(stderr, "\n"); fprintf(stderr, " JTAG:\n"); @@ -801,9 +833,20 @@ int main(int argc, char *argv[]) usage(argv[0]); filename = argv[++i]; log_dump(filename); + } else if (strcmp(argv[i], "ltrig") == 0) { + uint64_t addr; + + if ((i+1) >= argc) + ltrig_show(); + else if (strcmp(argv[++i], "off") == 0) + ltrig_off(); + else { + addr = strtoul(argv[i], NULL, 16); + ltrig_set(addr); + } } else { fprintf(stderr, "Unknown command %s\n", argv[i]); - exit(1); + usage(argv[0]); } } core_status();