@@ -3570,6 +3570,9 @@ static int read_memory_bus_v1(struct target *target, target_addr_t address,
35703570 target_addr_t next_address = address ;
35713571 target_addr_t end_address = address + (increment ? count : 1 ) * size ;
35723572
3573+ /* TODO: Reading all the elements in a single batch will boost the
3574+ * performance.
3575+ */
35733576 while (next_address < end_address ) {
35743577 uint32_t sbcs_write = set_field (0 , DM_SBCS_SBREADONADDR , 1 );
35753578 sbcs_write |= sb_sbaccess (size );
@@ -3600,77 +3603,44 @@ static int read_memory_bus_v1(struct target *target, target_addr_t address,
36003603 * completed. */
36013604
36023605 static int sbdata [4 ] = {DM_SBDATA0 , DM_SBDATA1 , DM_SBDATA2 , DM_SBDATA3 };
3606+ /* TODO: The only purpose of "sbvalue" is to be passed to
3607+ * "log_memory_access()". If "log_memory_access()" were to
3608+ * accept "uint8_t *" instead of "uint32_t *", "sbvalue" would
3609+ * be unnecessary.
3610+ */
36033611 uint32_t sbvalue [4 ] = {0 };
36043612 assert (size <= 16 );
3605- target_addr_t next_read = address - 1 ;
3606- uint32_t buffer_offset = 0 ;
3607- int next_read_j = 0 ;
36083613 for (uint32_t i = (next_address - address ) / size ; i < count - 1 ; i ++ ) {
3609- for (int j = (size - 1 ) / 4 ; j >= 0 ; j -- ) {
3610- unsigned attempt = 0 ;
3611- while (1 ) {
3612- if (attempt ++ > 100 ) {
3613- LOG_TARGET_ERROR (target , "DMI keeps being busy in while reading memory"
3614- " just past " TARGET_ADDR_FMT , next_read );
3615- return ERROR_FAIL ;
3616- }
3617- keep_alive ();
3618- dmi_status_t status = dmi_scan (target , NULL , & sbvalue [next_read_j ],
3619- DMI_OP_READ , sbdata [j ] + dm -> base , 0 , false);
3620- /* By reading from sbdata0, we have just initiated another system bus read.
3621- * If necessary add a delay so the read can finish. */
3622- bus_master_read_delay = riscv_scan_get_delay (& info -> learned_delays ,
3623- RISCV_DELAY_SYSBUS_READ );
3624- if (j == 0 && bus_master_read_delay ) {
3625- LOG_TARGET_DEBUG (target , "Waiting %d cycles for bus master read delay" ,
3626- bus_master_read_delay );
3627- jtag_add_runtest (bus_master_read_delay , TAP_IDLE );
3628- if (jtag_execute_queue () != ERROR_OK ) {
3629- LOG_TARGET_ERROR (target , "Failed to scan idle sequence" );
3630- return ERROR_FAIL ;
3631- }
3632- }
3614+ const uint32_t size_in_words = DIV_ROUND_UP (size , 4 );
3615+ struct riscv_batch * batch = riscv_batch_alloc (target , size_in_words );
3616+ /* Read of sbdata0 must be performed as last because it
3617+ * starts the new bus data transfer
3618+ * (in case "sbcs.sbreadondata" was set above).
3619+ * We don't want to start the next bus read before we
3620+ * fetch all the data from the last bus read. */
3621+ for (uint32_t j = size_in_words - 1 ; j > 0 ; -- j )
3622+ riscv_batch_add_dm_read (batch , sbdata [j ], RISCV_DELAY_BASE );
3623+ riscv_batch_add_dm_read (batch , sbdata [0 ], RISCV_DELAY_SYSBUS_READ );
3624+
3625+ int res = batch_run_timeout (target , batch );
3626+ if (res != ERROR_OK ) {
3627+ riscv_batch_free (batch );
3628+ return res ;
3629+ }
36333630
3634- if (status == DMI_STATUS_BUSY )
3635- increase_dmi_busy_delay (target );
3636- else if (status == DMI_STATUS_SUCCESS )
3637- break ;
3638- else
3639- return ERROR_FAIL ;
3640- }
3641- if (next_read != address - 1 ) {
3642- buf_set_u32 (buffer + buffer_offset , 0 , 8 * MIN (size , 4 ), sbvalue [next_read_j ]);
3643- if (next_read_j == 0 ) {
3644- log_memory_access (next_read , sbvalue , size , true);
3645- memset (sbvalue , 0 , size );
3646- }
3647- }
3648- next_read_j = j ;
3649- next_read = address + i * increment + next_read_j * 4 ;
3650- buffer_offset = i * size + next_read_j * 4 ;
3631+ const size_t last_key = batch -> read_keys_used - 1 ;
3632+ for (size_t k = 0 ; k <= last_key ; ++ k ) {
3633+ sbvalue [k ] = riscv_batch_get_dmi_read_data (batch ,
3634+ last_key - k );
3635+ buf_set_u32 (buffer + i * size + k * 4 , 0 , 8 * size , sbvalue [k ]);
36513636 }
3637+ riscv_batch_free (batch );
3638+ const target_addr_t read_addr = address + i * increment ;
3639+ log_memory_access (read_addr , sbvalue , size , true);
36523640 }
36533641
36543642 uint32_t sbcs_read = 0 ;
36553643 if (count > 1 ) {
3656- unsigned attempt = 0 ;
3657- while (1 ) {
3658- if (attempt ++ > 100 ) {
3659- LOG_TARGET_ERROR (target , "DMI keeps being busy in while reading memory"
3660- " just past " TARGET_ADDR_FMT , next_read );
3661- return ERROR_FAIL ;
3662- }
3663- dmi_status_t status = dmi_scan (target , NULL , & sbvalue [0 ], DMI_OP_NOP , 0 , 0 , false);
3664- if (status == DMI_STATUS_BUSY )
3665- increase_dmi_busy_delay (target );
3666- else if (status == DMI_STATUS_SUCCESS )
3667- break ;
3668- else
3669- return ERROR_FAIL ;
3670- }
3671- buf_set_u32 (buffer + buffer_offset , 0 , 8 * MIN (size , 4 ), sbvalue [0 ]);
3672- log_memory_access (next_read , sbvalue , size , true);
3673-
36743644 /* "Writes to sbcs while sbbusy is high result in undefined behavior.
36753645 * A debugger must not write to sbcs until it reads sbbusy as 0." */
36763646 if (read_sbcs_nonbusy (target , & sbcs_read ) != ERROR_OK )
0 commit comments