This is an automated email from Gerrit. "Richard Allen <rsa...@gmail.com>" just uploaded a new patch set to Gerrit, which you can find at https://review.openocd.org/c/openocd/+/8431
-- gerrit commit fd363a0b2fa7759e2d390052bae40f46cc062b55 Author: Richard Allen <rsa...@rsaxvc.net> Date: Wed Jul 31 20:53:52 2024 -0500 target/xtensa: add profiling function Use the TRAX interface DEBUGPC if available. Otherwise use default stop-and-go profiling. ESP32-S3, before this patch: Internal: 8 samples/second FT2232H: 12 samples/second After this patch: Internal: 18ksamples/second FT2232H: 100ksamples/second Change-Id: I681f0bccf4263c1e24f38be511e3b3aec8bf4d60 Signed-off-by: Richard Allen <rsa...@gmail.com> diff --git a/src/target/espressif/esp32.c b/src/target/espressif/esp32.c index 324aa3993b..fa0356da0a 100644 --- a/src/target/espressif/esp32.c +++ b/src/target/espressif/esp32.c @@ -500,4 +500,5 @@ struct target_type esp32_target = { .deinit_target = esp_xtensa_target_deinit, .commands = esp32_command_handlers, + .profiling = xtensa_profiling, }; diff --git a/src/target/espressif/esp32s2.c b/src/target/espressif/esp32s2.c index 2abde479ea..a255ba5908 100644 --- a/src/target/espressif/esp32s2.c +++ b/src/target/espressif/esp32s2.c @@ -537,4 +537,5 @@ struct target_type esp32s2_target = { .deinit_target = esp_xtensa_target_deinit, .commands = esp32s2_command_handlers, + .profiling = xtensa_profiling, }; diff --git a/src/target/espressif/esp32s3.c b/src/target/espressif/esp32s3.c index 22e1630e16..6bac4bcee5 100644 --- a/src/target/espressif/esp32s3.c +++ b/src/target/espressif/esp32s3.c @@ -421,4 +421,5 @@ struct target_type esp32s3_target = { .deinit_target = esp_xtensa_target_deinit, .commands = esp32s3_command_handlers, + .profiling = xtensa_profiling, }; diff --git a/src/target/xtensa/xtensa.c b/src/target/xtensa/xtensa.c index 8369cc4e5c..ac589587f7 100644 --- a/src/target/xtensa/xtensa.c +++ b/src/target/xtensa/xtensa.c @@ -2633,6 +2633,80 @@ int xtensa_breakpoint_remove(struct target *target, struct breakpoint *breakpoin return ERROR_OK; } +int xtensa_profiling(struct target *target, uint32_t *samples, + uint32_t max_num_samples, uint32_t *num_samples, uint32_t seconds) +{ + struct timeval timeout, now; + struct xtensa *xtensa = target_to_xtensa(target); + int retval = ERROR_OK; + int res; + + /* Vary samples per pass to avoid sampling a periodic function periodically */ + #define MIN_PASS 200 + #define MAX_PASS 1000 + + gettimeofday(&timeout, NULL); + timeval_add_time(&timeout, seconds, 0); + + uint8_t buf[sizeof(uint32_t) * MAX_PASS]; + + /* Capture one sample to verify the register is present and working */ + xtensa_queue_dbg_reg_read(xtensa, XDMREG_DEBUGPC, buf); + res = xtensa_dm_queue_execute(&xtensa->dbg_mod); + if (res != ERROR_OK) { + LOG_TARGET_INFO(target, "Failed to read DEBUGPC, fallback to stop-and-go"); + return target_profiling_default(target, samples, max_num_samples, num_samples, seconds); + } else if (buf[0] == 0 && buf[1] == 0 && buf[2] == 0 && buf[3] == 0){ + LOG_TARGET_INFO(target, "NULL DEBUGPC, fallback to stop-and-go"); + return target_profiling_default(target, samples, max_num_samples, num_samples, seconds); + } + + LOG_TARGET_INFO(target, "Starting XTENSA DEBUGPC profiling. Sampling as fast as we can..."); + + /* Make sure the target is running */ + target_poll(target); + if (target->state == TARGET_HALTED) + retval = target_resume(target, 1, 0, 0, 0); + + if (retval != ERROR_OK) { + LOG_TARGET_ERROR(target, "Error while resuming target"); + return retval; + } + + uint32_t sample_count = 0; + + for (;;) { + uint32_t remaining = max_num_samples - sample_count; + uint32_t this_pass = rand() % (MAX_PASS - MIN_PASS) + MIN_PASS; + this_pass = this_pass > remaining ? remaining : this_pass; + for(uint32_t i = 0; i < this_pass; ++i){ + xtensa_queue_dbg_reg_read(xtensa, XDMREG_DEBUGPC, buf + i * sizeof(uint32_t)); + } + res = xtensa_dm_queue_execute(&xtensa->dbg_mod); + if (res != ERROR_OK) { + LOG_TARGET_ERROR(target, "Failed to read DEBUGPC!"); + return res; + } + + for(uint32_t i = 0; i < this_pass; ++i){ + uint32_t sample32 = buf_get_u32(buf + i * sizeof(uint32_t), 0, 32); + samples[sample_count++] = sample32; + } + gettimeofday(&now, NULL); + if (sample_count >= max_num_samples || timeval_compare(&now, &timeout) > 0) { + LOG_TARGET_INFO(target, "Profiling completed. %" PRIu32 " samples.", sample_count); + break; + } + } + + *num_samples = sample_count; + return retval; + + #undef MIN_PASS + #undef MAX_PASS +} + + int xtensa_watchpoint_add(struct target *target, struct watchpoint *watchpoint) { struct xtensa *xtensa = target_to_xtensa(target); diff --git a/src/target/xtensa/xtensa.h b/src/target/xtensa/xtensa.h index 1d56f83682..8f7bf58247 100644 --- a/src/target/xtensa/xtensa.h +++ b/src/target/xtensa/xtensa.h @@ -404,6 +404,8 @@ int xtensa_deassert_reset(struct target *target); int xtensa_soft_reset_halt(struct target *target); int xtensa_breakpoint_add(struct target *target, struct breakpoint *breakpoint); int xtensa_breakpoint_remove(struct target *target, struct breakpoint *breakpoint); +int xtensa_profiling(struct target *target, uint32_t *samples, + uint32_t max_num_samples, uint32_t *num_samples, uint32_t seconds); int xtensa_watchpoint_add(struct target *target, struct watchpoint *watchpoint); int xtensa_watchpoint_remove(struct target *target, struct watchpoint *watchpoint); int xtensa_start_algorithm(struct target *target, diff --git a/src/target/xtensa/xtensa_chip.c b/src/target/xtensa/xtensa_chip.c index ce6d35cabf..ae9ab4020b 100644 --- a/src/target/xtensa/xtensa_chip.c +++ b/src/target/xtensa/xtensa_chip.c @@ -196,4 +196,6 @@ struct target_type xtensa_chip_target = { .get_gdb_fileio_info = xtensa_get_gdb_fileio_info, .gdb_fileio_end = xtensa_gdb_fileio_end, + + .profiling = xtensa_profiling, }; diff --git a/src/target/xtensa/xtensa_debug_module.h b/src/target/xtensa/xtensa_debug_module.h index 495da2a646..312a2c037a 100644 --- a/src/target/xtensa/xtensa_debug_module.h +++ b/src/target/xtensa/xtensa_debug_module.h @@ -75,6 +75,7 @@ enum xtensa_dm_reg { XDMREG_DELAYCNT, XDMREG_MEMADDRSTART, XDMREG_MEMADDREND, + XDMREG_DEBUGPC, XDMREG_EXTTIMELO, XDMREG_EXTTIMEHI, XDMREG_TRAXRSVD48, @@ -184,6 +185,7 @@ struct xtensa_dm_reg_offsets { { .nar = 0x07, .apb = 0x001c }, /* XDMREG_DELAYCNT */ \ { .nar = 0x08, .apb = 0x0020 }, /* XDMREG_MEMADDRSTART */ \ { .nar = 0x09, .apb = 0x0024 }, /* XDMREG_MEMADDREND */ \ + { .nar = 0x0f, .apb = 0x003c }, /* XDMREG_DEBUGPC */ \ { .nar = 0x10, .apb = 0x0040 }, /* XDMREG_EXTTIMELO */ \ { .nar = 0x11, .apb = 0x0044 }, /* XDMREG_EXTTIMEHI */ \ { .nar = 0x12, .apb = 0x0048 }, /* XDMREG_TRAXRSVD48 */ \ --