mirror of
https://github.com/antonblanchard/microwatt.git
synced 2026-01-11 23:43:15 +00:00
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 <paulus@ozlabs.org>
This commit is contained in:
parent
5535257c71
commit
470f1b2140
@ -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);
|
||||
|
||||
@ -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();
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user