Skip to content

Commit aa4fcee

Browse files
committed
target/riscv: use batch interface in read_memory_bus_v1()
Fixes riscv-collab#1080 Change-Id: Ifc1a48fcd0b28f7cdb1e5ad3cbd20d53ea3560a5 Signed-off-by: Evgeniy Naydanov <[email protected]>
1 parent 4b5668b commit aa4fcee

File tree

1 file changed

+32
-62
lines changed

1 file changed

+32
-62
lines changed

src/target/riscv/riscv-013.c

Lines changed: 32 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)