core_debug: Add an address trigger to stop logging at a given address
authorPaul Mackerras <paulus@ozlabs.org>
Thu, 12 Nov 2020 04:06:38 +0000 (15:06 +1100)
committerPaul Mackerras <paulus@ozlabs.org>
Fri, 15 Jan 2021 01:40:09 +0000 (12:40 +1100)
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 <paulus@ozlabs.org>
core_debug.vhdl
scripts/mw_debug/mw_debug.c

index 9efaa7c79e9f06462a9d7d0edb0d4db44e8200c2..09e3e4831fa1e7a6915a4bde2ec78882623edbff 100644 (file)
@@ -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);
index d03e61c5de3f3b9013d5c0b3f5724b0c92451578..4179264cc443e166a92f702618e84849c7c2f869 100644 (file)
@@ -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 <jtag|sim> <command> <args>\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 <file>                 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 <addr>                 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();