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 */         \

-- 

Reply via email to