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)
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 = {
/** */
.set_count_to_check_dbger = aice_usb_set_count_to_check_dbger,
/** */
.set_data_endian = aice_usb_set_data_endian,
+ /** */
+ .profiling = aice_usb_profiling,
};