nds32: support Andes profiling function
[openocd.git] / src / jtag / aice / aice_usb.c
index 30509d3b2c03d1d8c6f96204797fe5e75cff56dc..f25a0f5ce999b2a9b5a203b0924491846fb7ec71 100644 (file)
@@ -390,7 +390,7 @@ static uint32_t usb_out_packets_buffer_length;
 static uint32_t usb_in_packets_buffer_length;
 static enum aice_command_mode aice_command_mode;
 
-extern int aice_batch_buffer_write(uint8_t buf_index, const uint8_t *word,
+static int aice_batch_buffer_write(uint8_t buf_index, const uint8_t *word,
                uint32_t num_of_words);
 
 static int aice_usb_packet_flush(void)
@@ -3788,6 +3788,168 @@ static int aice_usb_set_data_endian(enum aice_target_endian target_data_endian)
        return ERROR_OK;
 }
 
+static int fill_profiling_batch_commands(uint32_t reg_no)
+{
+       uint32_t dim_instructions[4];
+
+       aice_usb_set_command_mode(AICE_COMMAND_MODE_BATCH);
+
+       /* halt */
+       if (aice_write_misc(current_target_id, NDS_EDM_MISC_EDM_CMDR, 0) != ERROR_OK)
+               return ERROR_FAIL;
+
+       /* backup $r0 */
+       dim_instructions[0] = MTSR_DTR(0);
+       dim_instructions[1] = DSB;
+       dim_instructions[2] = NOP;
+       dim_instructions[3] = BEQ_MINUS_12;
+       if (aice_write_dim(current_target_id, dim_instructions, 4) != ERROR_OK)
+               return ERROR_FAIL;
+       aice_read_dtr_to_buffer(current_target_id, AICE_BATCH_DATA_BUFFER_0);
+
+       /* get samples */
+       if (NDS32_REG_TYPE_GPR == nds32_reg_type(reg_no)) {
+               /* general registers */
+               dim_instructions[0] = MTSR_DTR(reg_no);
+               dim_instructions[1] = DSB;
+               dim_instructions[2] = NOP;
+               dim_instructions[3] = BEQ_MINUS_12;
+       } else if (NDS32_REG_TYPE_SPR == nds32_reg_type(reg_no)) {
+               /* user special registers */
+               dim_instructions[0] = MFUSR_G0(0, nds32_reg_sr_index(reg_no));
+               dim_instructions[1] = MTSR_DTR(0);
+               dim_instructions[2] = DSB;
+               dim_instructions[3] = BEQ_MINUS_12;
+       } else { /* system registers */
+               dim_instructions[0] = MFSR(0, nds32_reg_sr_index(reg_no));
+               dim_instructions[1] = MTSR_DTR(0);
+               dim_instructions[2] = DSB;
+               dim_instructions[3] = BEQ_MINUS_12;
+       }
+       if (aice_write_dim(current_target_id, dim_instructions, 4) != ERROR_OK)
+               return ERROR_FAIL;
+       aice_read_dtr_to_buffer(current_target_id, AICE_BATCH_DATA_BUFFER_1);
+
+       /* restore $r0 */
+       aice_write_dtr_from_buffer(current_target_id, AICE_BATCH_DATA_BUFFER_0);
+       dim_instructions[0] = MFSR_DTR(0);
+       dim_instructions[1] = DSB;
+       dim_instructions[2] = NOP;
+       dim_instructions[3] = IRET;  /* free run */
+       if (aice_write_dim(current_target_id, dim_instructions, 4) != ERROR_OK)
+               return ERROR_FAIL;
+
+       aice_command_mode = AICE_COMMAND_MODE_NORMAL;
+
+       /* use BATCH_BUFFER_WRITE to fill command-batch-buffer */
+       if (aice_batch_buffer_write(AICE_BATCH_COMMAND_BUFFER_0,
+                               usb_out_packets_buffer,
+                               (usb_out_packets_buffer_length + 3) / 4) != ERROR_OK)
+               return ERROR_FAIL;
+
+       usb_out_packets_buffer_length = 0;
+       usb_in_packets_buffer_length = 0;
+
+       return ERROR_OK;
+}
+
+static int aice_usb_profiling(uint32_t interval, uint32_t iteration,
+               uint32_t reg_no, uint32_t *samples, uint32_t *num_samples)
+{
+       uint32_t iteration_count;
+       uint32_t this_iteration;
+       int retval = ERROR_OK;
+       const uint32_t MAX_ITERATION = 250;
+
+       *num_samples = 0;
+
+       /* init DIM size */
+       if (aice_write_ctrl(AICE_WRITE_CTRL_BATCH_DIM_SIZE, 4) != ERROR_OK)
+               return ERROR_FAIL;
+
+       /* Use AICE_BATCH_DATA_BUFFER_0 to read/write $DTR.
+        * Set it to circular buffer */
+       if (aice_write_ctrl(AICE_WRITE_CTRL_BATCH_DATA_BUF0_CTRL, 0xC0000) != ERROR_OK)
+               return ERROR_FAIL;
+
+       fill_profiling_batch_commands(reg_no);
+
+       iteration_count = 0;
+       while (iteration_count < iteration) {
+               if (iteration - iteration_count < MAX_ITERATION)
+                       this_iteration = iteration - iteration_count;
+               else
+                       this_iteration = MAX_ITERATION;
+
+               /* set number of iterations */
+               uint32_t val_iteration;
+               val_iteration = interval << 16 | this_iteration;
+               if (aice_write_ctrl(AICE_WRITE_CTRL_BATCH_ITERATION,
+                                       val_iteration) != ERROR_OK) {
+                       retval = ERROR_FAIL;
+                       goto end_profiling;
+               }
+
+               /* init AICE_WRITE_CTRL_BATCH_DATA_BUF1_CTRL to store $PC */
+               if (aice_write_ctrl(AICE_WRITE_CTRL_BATCH_DATA_BUF1_CTRL,
+                                       0x40000) != ERROR_OK) {
+                       retval = ERROR_FAIL;
+                       goto end_profiling;
+               }
+
+               aice_usb_run();
+
+               /* enable BATCH command */
+               if (aice_write_ctrl(AICE_WRITE_CTRL_BATCH_CTRL,
+                                       0x80000000) != ERROR_OK) {
+                       aice_usb_halt();
+                       retval = ERROR_FAIL;
+                       goto end_profiling;
+               }
+
+               /* wait a while (AICE bug, workaround) */
+               alive_sleep(this_iteration);
+
+               /* check status */
+               uint32_t i;
+               uint32_t batch_status;
+
+               i = 0;
+               while (1) {
+                       aice_read_ctrl(AICE_READ_CTRL_BATCH_STATUS, &batch_status);
+
+                       if (batch_status & 0x1) {
+                               break;
+                       } else if (batch_status & 0xE) {
+                               aice_usb_halt();
+                               retval = ERROR_FAIL;
+                               goto end_profiling;
+                       }
+
+                       if ((i % 30) == 0)
+                               keep_alive();
+
+                       i++;
+               }
+
+               aice_usb_halt();
+
+               /* get samples from batch data buffer */
+               if (aice_batch_buffer_read(AICE_BATCH_DATA_BUFFER_1,
+                                       samples + iteration_count, this_iteration) != ERROR_OK) {
+                       retval = ERROR_FAIL;
+                       goto end_profiling;
+               }
+
+               iteration_count += this_iteration;
+       }
+
+end_profiling:
+       *num_samples = iteration_count;
+
+       return retval;
+}
+
 /** */
 struct aice_port_api_s aice_usb_api = {
        /** */
@@ -3858,4 +4020,6 @@ struct aice_port_api_s aice_usb_api = {
        .set_count_to_check_dbger = aice_usb_set_count_to_check_dbger,
        /** */
        .set_data_endian = aice_usb_set_data_endian,
+       /** */
+       .profiling = aice_usb_profiling,
 };

Linking to existing account procedure

If you already have an account and want to add another login method you MUST first sign in with your existing account and then change URL to read https://review.openocd.org/login/?link to get to this page again but this time it'll work for linking. Thank you.

SSH host keys fingerprints

1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=..              |
|+o..   .         |
|*.o   . .        |
|+B . . .         |
|Bo. = o S        |
|Oo.+ + =         |
|oB=.* = . o      |
| =+=.+   + E     |
|. .=o   . o      |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)