From 06f6b5020c5976b7c67c1617b0600cba33b5a9e8 Mon Sep 17 00:00:00 2001 From: Tim Newsome Date: Sat, 18 Jun 2016 20:49:01 -0700 Subject: [PATCH] Use optimized cache/program write scheme for most operations. --- src/target/riscv/riscv.c | 329 ++++++++++++++++++--------------------- 1 file changed, 154 insertions(+), 175 deletions(-) diff --git a/src/target/riscv/riscv.c b/src/target/riscv/riscv.c index 924a85426..715db6749 100644 --- a/src/target/riscv/riscv.c +++ b/src/target/riscv/riscv.c @@ -130,11 +130,6 @@ typedef struct { uint8_t addrbits; /* Width of a GPR (and many other things) in bits. */ uint8_t xlen; - /* Last value we wrote to DBUS_ADDRESS (eg. the address of the register - * whose value will be read the next time we scan dbus). */ - uint16_t dbus_address; - /* Last op we wrote to dbus. */ - dbus_op_t dbus_op; /* Number of words in Debug RAM. */ unsigned int dramsize; uint32_t dcsr; @@ -233,8 +228,8 @@ static int debug_scan(struct target *target) } #endif -static dbus_status_t dbus_scan(struct target *target, uint64_t *data_in, - dbus_op_t op, uint16_t address, uint64_t data_out) +static dbus_status_t dbus_scan(struct target *target, uint16_t *address_in, + uint64_t *data_in, dbus_op_t op, uint16_t address_out, uint64_t data_out) { riscv_info_t *info = (riscv_info_t *) target->arch_info; uint8_t in[8] = {0}; @@ -249,13 +244,11 @@ static dbus_status_t dbus_scan(struct target *target, uint64_t *data_in, buf_set_u64(out, DBUS_OP_START, DBUS_OP_SIZE, op); buf_set_u64(out, DBUS_DATA_START, DBUS_DATA_SIZE, data_out); - buf_set_u64(out, DBUS_ADDRESS_START, info->addrbits, address); + buf_set_u64(out, DBUS_ADDRESS_START, info->addrbits, address_out); /* Assume dbus is already selected. */ jtag_add_dr_scan(target->tap, 1, &field, TAP_IDLE); jtag_add_runtest(1, TAP_IDLE); - info->dbus_address = address; - info->dbus_op = op; int retval = jtag_execute_queue(); if (retval != ERROR_OK) { @@ -267,8 +260,13 @@ static dbus_status_t dbus_scan(struct target *target, uint64_t *data_in, *data_in = buf_get_u64(in, DBUS_DATA_START, DBUS_DATA_SIZE); } + if (address_in) { + *address_in = buf_get_u32(in, DBUS_ADDRESS_START, info->addrbits); + } + static const char *op_string[] = {"nop", "r", "w", "cw"}; static const char *status_string[] = {"+", "nw", "F", "b"}; + /* LOG_DEBUG("vvv $display(\"hardware: dbus scan %db %s %01x:%08x @%02x -> %s %01x:%08x @%02x\");", field.num_bits, op_string[buf_get_u32(out, 0, 2)], @@ -277,7 +275,7 @@ static dbus_status_t dbus_scan(struct target *target, uint64_t *data_in, status_string[buf_get_u32(in, 0, 2)], buf_get_u32(in, 34, 2), buf_get_u32(in, 2, 32), buf_get_u32(in, 36, info->addrbits)); - /* + */ LOG_DEBUG("dbus scan %db %s %01x:%08x @%02x -> %s %01x:%08x @%02x", field.num_bits, op_string[buf_get_u32(out, 0, 2)], @@ -286,32 +284,24 @@ static dbus_status_t dbus_scan(struct target *target, uint64_t *data_in, status_string[buf_get_u32(in, 0, 2)], buf_get_u32(in, 34, 2), buf_get_u32(in, 2, 32), buf_get_u32(in, 36, info->addrbits)); - */ //debug_scan(target); - return buf_get_u64(in, DBUS_OP_START, DBUS_OP_SIZE); + return buf_get_u32(in, DBUS_OP_START, DBUS_OP_SIZE); } -static uint64_t dbus_read(struct target *target, uint16_t address, - uint16_t next_address) +static uint64_t dbus_read(struct target *target, uint16_t address) { - riscv_info_t *info = (riscv_info_t *) target->arch_info; uint64_t value; + dbus_status_t status; + uint16_t address_in; + + do { + do { + status = dbus_scan(target, &address_in, &value, DBUS_OP_READ, address, 0); + } while (status == DBUS_STATUS_BUSY); + } while (address_in != address); - dbus_status_t status = DBUS_STATUS_BUSY; - if (address != info->dbus_address || info->dbus_op == DBUS_OP_NOP) { - while (status == DBUS_STATUS_BUSY) { - status = dbus_scan(target, NULL, DBUS_OP_READ, address, 0); - } - } - status = DBUS_STATUS_BUSY; - while (status == DBUS_STATUS_BUSY) { - status = dbus_scan(target, &value, DBUS_OP_READ, next_address, 0); - } - if (status != DBUS_STATUS_SUCCESS) { - LOG_ERROR("dbus_read failed read at 0x%x; status=%d\n", address, status); - } return value; } @@ -319,7 +309,7 @@ static void dbus_write(struct target *target, uint16_t address, uint64_t value) { dbus_status_t status = DBUS_STATUS_BUSY; while (status == DBUS_STATUS_BUSY) { - status = dbus_scan(target, NULL, DBUS_OP_WRITE, address, value); + status = dbus_scan(target, NULL, NULL, DBUS_OP_WRITE, address, value); } if (status != DBUS_STATUS_SUCCESS) { LOG_ERROR("dbus_write failed write 0x%" PRIx64 " to 0x%x; status=%d\n", @@ -354,7 +344,7 @@ static uint32_t dtminfo_read(struct target *target) static uint32_t dram_read32(struct target *target, unsigned int index) { uint16_t address = dram_address(index); - uint32_t value = dbus_read(target, address, address); + uint32_t value = dbus_read(target, address); return value; } @@ -370,15 +360,15 @@ static void dram_write32(struct target *target, unsigned int index, uint32_t val /** Read the haltnot and interrupt bits. */ static bits_t read_bits(struct target *target) { - riscv_info_t *info = (riscv_info_t *) target->arch_info; - static int next_address = 0; - uint64_t value; - if (info->dbus_address < 0x10 || info->dbus_address == DMCONTROL) { - value = dbus_read(target, info->dbus_address, next_address); - } else { - value = dbus_read(target, 0, next_address); - } + dbus_status_t status; + uint16_t address_in; + + do { + do { + status = dbus_scan(target, &address_in, &value, DBUS_OP_READ, 0, 0); + } while (status == DBUS_STATUS_BUSY); + } while (address_in > 0x10 && address_in != DMCONTROL); bits_t result = { .haltnot = get_field(value, DMCONTROL_HALTNOT), @@ -437,41 +427,10 @@ static void dump_debug_ram(struct target *target) } } -/** Run the program written to the debug RAM cache. */ -static int cache_run(struct target *target, unsigned int address) +static int cache_run_maybe(struct target *target, unsigned int address, bool run) { LOG_DEBUG("enter"); riscv_info_t *info = (riscv_info_t *) target->arch_info; -#if 0 - unsigned int last = DRAM_CACHE_SIZE; - for (unsigned int i = 0; i < DRAM_CACHE_SIZE; i++) { - if (info->dram_cache[i].dirty) { - last = i; - } - } - - if (last == DRAM_CACHE_SIZE) { - // Nothing needs to be written to RAM. - dram_write32(target, DMCONTROL, 0, true); - - } else { - for (unsigned int i = 0; i < DRAM_CACHE_SIZE; i++) { - - if (i != last && info->dram_cache[i].dirty) { - dram_write32(target, i, info->dram_cache[i].data, false); - info->dram_cache[i].dirty = false; - } - } - dram_write32(target, last, info->dram_cache[last].data, true); - info->dram_cache[last].dirty = false; - } - if (wait_for_debugint_clear(target, true) != ERROR_OK) { - LOG_ERROR("Debug interrupt didn't clear."); - dump_debug_ram(target); - return ERROR_FAIL; - } - -#else uint8_t in[(DRAM_CACHE_SIZE + 2) * 8] = {0}; uint8_t out[(DRAM_CACHE_SIZE + 2) * 8]; struct scan_field field[DRAM_CACHE_SIZE + 2]; @@ -479,6 +438,7 @@ static int cache_run(struct target *target, unsigned int address) unsigned int last = DRAM_CACHE_SIZE; for (unsigned int i = 0; i < DRAM_CACHE_SIZE; i++) { if (info->dram_cache[i].dirty) { + assert(i < info->dramsize); last = i; } } @@ -497,7 +457,7 @@ static int cache_run(struct target *target, unsigned int address) field[scan].in_value = in + 8*scan; buf_set_u64(out + 8*scan, DBUS_OP_START, DBUS_OP_SIZE, DBUS_OP_WRITE); - if (i == last) { + if (i == last && run) { buf_set_u64(out + 8*scan, DBUS_DATA_START, DBUS_DATA_SIZE, DMCONTROL_INTERRUPT | DMCONTROL_HALTNOT | info->dram_cache[i].data); } else { @@ -511,9 +471,9 @@ static int cache_run(struct target *target, unsigned int address) LOG_DEBUG("write scan=%d result=%d data=%09lx address=%02x", scan, - buf_get_u32(out + 8*i, DBUS_OP_START, DBUS_OP_SIZE), - buf_get_u64(out + 8*i, DBUS_DATA_START, DBUS_DATA_SIZE), - buf_get_u32(out + 8*i, DBUS_ADDRESS_START, info->addrbits)); + buf_get_u32(out + 8*scan, DBUS_OP_START, DBUS_OP_SIZE), + buf_get_u64(out + 8*scan, DBUS_DATA_START, DBUS_DATA_SIZE), + buf_get_u32(out + 8*scan, DBUS_ADDRESS_START, info->addrbits)); scan++; } @@ -585,13 +545,13 @@ static int cache_run(struct target *target, unsigned int address) // Try again, using the slow careful code. for (unsigned int i = 0; i < DRAM_CACHE_SIZE; i++) { - if (i != last && info->dram_cache[i].dirty) { + if (i == last && run) { + dram_write32(target, last, info->dram_cache[last].data, true); + } else { dram_write32(target, i, info->dram_cache[i].data, false); - info->dram_cache[i].dirty = false; } + info->dram_cache[i].dirty = false; } - dram_write32(target, last, info->dram_cache[last].data, true); - info->dram_cache[last].dirty = false; if (wait_for_debugint_clear(target, true) != ERROR_OK) { LOG_ERROR("Debug interrupt didn't clear."); @@ -600,10 +560,6 @@ static int cache_run(struct target *target, unsigned int address) } } else { - for (unsigned int i = 0; i < DRAM_CACHE_SIZE; i++) { - info->dram_cache[i].dirty = false; - } - int interrupt = buf_get_u32(in + 8*(scan-1), DBUS_DATA_START + 33, 1); if (interrupt) { info->interrupt_high_count++; @@ -616,12 +572,35 @@ static int cache_run(struct target *target, unsigned int address) } } -#endif + for (unsigned int i = 0; i < DRAM_CACHE_SIZE; i++) { + if (i >= 4) { + info->dram_cache[i].valid = false; + } else { + info->dram_cache[i].dirty = false; + } + } + LOG_DEBUG("exit"); return ERROR_OK; } +/** Run the program written to the debug RAM cache. */ +static int cache_run(struct target *target, unsigned int address) +{ + return cache_run_maybe(target, address, true); +} + +/* Call this if the code you just ran writes to debug RAM entries 0 through 3. */ +static void cache_invalidate(struct target *target) +{ + riscv_info_t *info = (riscv_info_t *) target->arch_info; + for (unsigned int i = 0; i < DRAM_CACHE_SIZE; i++) { + info->dram_cache[i].valid = false; + info->dram_cache[i].dirty = false; + } +} + #if 0 static int dram_check32(struct target *target, unsigned int index, uint32_t expected) @@ -666,15 +645,14 @@ static int wait_for_state(struct target *target, enum target_state state) static int wait_and_read(struct target *target, uint32_t *data, uint16_t address) { - riscv_info_t *info = (riscv_info_t *) target->arch_info; time_t start = time(NULL); // Throw away the results of the first read, since they'll contain the // result of the read that happened just before debugint was set. (Assuming // the last scan before calling this function was one that sets debugint.) - dbus_read(target, info->dbus_address, address); + dbus_scan(target, NULL, NULL, DBUS_OP_READ, address, 0); while (1) { - uint64_t dbus_value = dbus_read(target, info->dbus_address, address); + uint64_t dbus_value = dbus_read(target, address); *data = dbus_value; if (!get_field(dbus_value, DMCONTROL_INTERRUPT)) { return ERROR_OK; @@ -688,12 +666,10 @@ static int wait_and_read(struct target *target, uint32_t *data, uint16_t address static int read_csr(struct target *target, uint32_t *value, uint32_t csr) { - dram_write32(target, 0, csrr(S0, csr), false); - dram_write32(target, 1, sw(S0, ZERO, DEBUG_RAM_START + 16), false); - dram_write_jump(target, 2, true); - - if (wait_for_debugint_clear(target, true) != ERROR_OK) { - LOG_ERROR("Debug interrupt didn't clear."); + cache_set(target, 0, csrr(S0, csr)); + cache_set(target, 1, sw(S0, ZERO, DEBUG_RAM_START + 16)); + cache_set_jump(target, 2); + if (cache_run(target, 4) != ERROR_OK) { return ERROR_FAIL; } *value = dram_read32(target, 4); @@ -703,13 +679,11 @@ static int read_csr(struct target *target, uint32_t *value, uint32_t csr) static int write_csr(struct target *target, uint32_t csr, uint32_t value) { - dram_write32(target, 0, lw(S0, ZERO, DEBUG_RAM_START + 16), false); - dram_write32(target, 1, csrw(S0, csr), false); - dram_write_jump(target, 2, false); - dram_write32(target, 4, value, true); - - if (wait_for_debugint_clear(target, true) != ERROR_OK) { - LOG_ERROR("Debug interrupt didn't clear."); + cache_set(target, 0, lw(S0, ZERO, DEBUG_RAM_START + 16)); + cache_set(target, 1, csrw(S0, csr)); + cache_set_jump(target, 2); + cache_set(target, 4, value); + if (cache_run(target, 4) != ERROR_OK) { return ERROR_FAIL; } @@ -741,10 +715,13 @@ static int resume(struct target *target, int current, uint32_t address, // TODO: check if dpc is dirty (which also is true if an exception was hit // at any time) - dram_write32(target, 0, lw(S0, ZERO, DEBUG_RAM_START + 16), false); - dram_write32(target, 1, csrw(S0, CSR_DPC), false); - dram_write_jump(target, 2, false); - dram_write32(target, 4, info->dpc, true); + cache_set(target, 0, lw(S0, ZERO, DEBUG_RAM_START + 16)); + cache_set(target, 1, csrw(S0, CSR_DPC)); + cache_set_jump(target, 2); + cache_set(target, 4, info->dpc); + if (cache_run(target, 4) != ERROR_OK) { + return ERROR_FAIL; + } info->dcsr |= DCSR_EBREAKM | DCSR_EBREAKH | DCSR_EBREAKS | DCSR_EBREAKU; info->dcsr &= ~DCSR_HALT; @@ -763,6 +740,8 @@ static int resume(struct target *target, int current, uint32_t address, uint64_t dbus_value = DMCONTROL_INTERRUPT | info->dcsr; dbus_write(target, dram_address(4), dbus_value); + cache_invalidate(target); + if (wait_for_debugint_clear(target, true) != ERROR_OK) { LOG_ERROR("Debug interrupt didn't clear."); return ERROR_FAIL; @@ -799,44 +778,44 @@ static int register_get(struct reg *reg) { struct target *target = (struct target *) reg->arch_info; riscv_info_t *info = (riscv_info_t *) target->arch_info; - uint32_t value = 0; if (reg->number == S0) { - dram_write32(target, 0, csrr(S0, CSR_DSCRATCH), false); - dram_write32(target, 1, sw(S0, ZERO, DEBUG_RAM_START), false); - dram_write_jump(target, 2, true); + cache_set(target, 0, csrr(S0, CSR_DSCRATCH)); + cache_set(target, 1, sw(S0, ZERO, DEBUG_RAM_START + 16)); + cache_set_jump(target, 2); } else if (reg->number == S1) { - dram_write32(target, 0, lw(S0, ZERO, DEBUG_RAM_START + 4 * info->dramsize - 4), false); - dram_write32(target, 1, sw(S0, ZERO, DEBUG_RAM_START), false); - dram_write_jump(target, 2, true); + cache_set(target, 0, lw(S0, ZERO, DEBUG_RAM_START + 4 * info->dramsize - 4)); + cache_set(target, 1, sw(S0, ZERO, DEBUG_RAM_START + 16)); + cache_set_jump(target, 2); } else if (reg->number == ZERO) { - buf_set_u64(reg->value, 0, info->xlen, value); - LOG_DEBUG("%s=0x%x", reg->name, value); + buf_set_u64(reg->value, 0, info->xlen, 0); + LOG_DEBUG("%s=0x%x", reg->name, 0); return ERROR_OK; } else if (reg->number <= REG_XPR31) { - dram_write_jump(target, 1, false); - dram_write32(target, 0, sw(reg->number - REG_XPR0, ZERO, DEBUG_RAM_START), true); + cache_set(target, 0, sw(reg->number - REG_XPR0, ZERO, DEBUG_RAM_START + 16)); + cache_set_jump(target, 1); } else if (reg->number == REG_PC) { buf_set_u32(reg->value, 0, 32, info->dpc); - LOG_DEBUG("%s=0x%x (cached)", reg->name, value); + LOG_DEBUG("%s=0x%x (cached)", reg->name, info->dpc); return ERROR_OK; } else if (reg->number >= REG_FPR0 && reg->number <= REG_FPR31) { - dram_write32(target, 0, fsw(reg->number - REG_FPR0, 0, DEBUG_RAM_START), false); - dram_write_jump(target, 1, true); + cache_set(target, 0, fsw(reg->number - REG_FPR0, 0, DEBUG_RAM_START + 16)); + cache_set_jump(target, 1); } else if (reg->number >= REG_CSR0 && reg->number <= REG_CSR4095) { - dram_write32(target, 0, csrr(S0, reg->number - REG_CSR0), false); - dram_write32(target, 1, sw(S0, ZERO, DEBUG_RAM_START), false); - dram_write_jump(target, 2, true); + cache_set(target, 0, csrr(S0, reg->number - REG_CSR0)); + cache_set(target, 1, sw(S0, ZERO, DEBUG_RAM_START + 16)); + cache_set_jump(target, 2); } else { LOG_ERROR("Don't know how to read register %d (%s)", reg->number, reg->name); return ERROR_FAIL; } - if (wait_and_read(target, &value, 0) != ERROR_OK) { - LOG_ERROR("Debug interrupt didn't clear."); + if (cache_run(target, 4) != ERROR_OK) { return ERROR_FAIL; } + uint32_t value = dram_read32(target, 4); + uint32_t exception = dram_read32(target, info->dramsize-1); if (exception) { LOG_ERROR("Got exception 0x%x when reading register %d", exception, @@ -856,35 +835,33 @@ static int register_write(struct target *target, unsigned int number, riscv_info_t *info = (riscv_info_t *) target->arch_info; if (number == S0) { - dram_write32(target, 0, lw(S0, ZERO, DEBUG_RAM_START + 16), false); - dram_write32(target, 1, csrw(S0, CSR_DSCRATCH), false); - dram_write_jump(target, 2, false); + cache_set(target, 0, lw(S0, ZERO, DEBUG_RAM_START + 16)); + cache_set(target, 1, csrw(S0, CSR_DSCRATCH)); + cache_set_jump(target, 2); } else if (number == S1) { - dram_write32(target, 0, lw(S0, ZERO, DEBUG_RAM_START + 16), false); - dram_write32(target, 1, sw(S0, ZERO, DEBUG_RAM_START + 4 * info->dramsize - 4), false); - dram_write_jump(target, 2, false); + cache_set(target, 0, lw(S0, ZERO, DEBUG_RAM_START + 16)); + cache_set(target, 1, sw(S0, ZERO, DEBUG_RAM_START + 4 * info->dramsize - 4)); + cache_set_jump(target, 2); } else if (number <= REG_XPR31) { - dram_write32(target, 0, lw(number - REG_XPR0, ZERO, DEBUG_RAM_START + 16), false); - dram_write_jump(target, 1, false); + cache_set(target, 0, lw(number - REG_XPR0, ZERO, DEBUG_RAM_START + 16)); + cache_set_jump(target, 1); } else if (number == REG_PC) { info->dpc = value; return ERROR_OK; } else if (number >= REG_FPR0 && number <= REG_FPR31) { - dram_write32(target, 0, flw(number - REG_FPR0, 0, DEBUG_RAM_START + 16), false); - dram_write_jump(target, 1, false); + cache_set(target, 0, flw(number - REG_FPR0, 0, DEBUG_RAM_START + 16)); + cache_set_jump(target, 1); } else if (number >= REG_CSR0 && number <= REG_CSR4095) { - dram_write32(target, 0, lw(S0, ZERO, DEBUG_RAM_START + 16), false); - dram_write32(target, 1, csrw(S0, number - REG_CSR0), false); - dram_write_jump(target, 2, false); + cache_set(target, 0, lw(S0, ZERO, DEBUG_RAM_START + 16)); + cache_set(target, 1, csrw(S0, number - REG_CSR0)); + cache_set_jump(target, 2); } else { LOG_ERROR("Don't know how to read register %d", number); return ERROR_FAIL; } - dram_write32(target, 4, value, true); - - if (wait_for_debugint_clear(target, true) != ERROR_OK) { - LOG_ERROR("Debug interrupt didn't clear."); + cache_set(target, 4, value); + if (cache_run(target, 4) != ERROR_OK) { return ERROR_FAIL; } @@ -915,8 +892,6 @@ static int riscv_init_target(struct command_context *cmd_ctx, if (!target->arch_info) return ERROR_FAIL; riscv_info_t *info = (riscv_info_t *) target->arch_info; - info->dbus_address = DBUS_ADDRESS_UNKNOWN; - info->dbus_op = DBUS_OP_NOP; select_dtminfo.num_bits = target->tap->ir_length; select_dbus.num_bits = target->tap->ir_length; @@ -973,13 +948,13 @@ static int riscv_halt(struct target *target) LOG_DEBUG("riscv_halt()"); jtag_add_ir_scan(target->tap, &select_dbus, TAP_IDLE); - dram_write32(target, 0, csrsi(CSR_DCSR, DCSR_HALT), false); - dram_write32(target, 1, csrr(S0, CSR_MHARTID), false); - dram_write32(target, 2, sw(S0, ZERO, SETHALTNOT), false); - dram_write_jump(target, 3, true); + cache_set(target, 0, csrsi(CSR_DCSR, DCSR_HALT)); + cache_set(target, 1, csrr(S0, CSR_MHARTID)); + cache_set(target, 2, sw(S0, ZERO, SETHALTNOT)); + cache_set_jump(target, 3); - if (wait_for_debugint_clear(target, true) != ERROR_OK) { - LOG_ERROR("Debug interrupt didn't clear."); + if (cache_run(target, 4) != ERROR_OK) { + LOG_ERROR("cache_run() failed."); return ERROR_FAIL; } @@ -1112,7 +1087,7 @@ static int riscv_examine(struct target *target) riscv_info_t *info = (riscv_info_t *) target->arch_info; info->addrbits = get_field(dtminfo, DTMINFO_ADDRBITS); - uint32_t dminfo = dbus_read(target, DMINFO, 0); + uint32_t dminfo = dbus_read(target, DMINFO); LOG_DEBUG("dminfo: 0x%08x", dminfo); LOG_DEBUG(" abussize=0x%x", get_field(dminfo, DMINFO_ABUSSIZE)); LOG_DEBUG(" serialcount=0x%x", get_field(dminfo, DMINFO_SERIALCOUNT)); @@ -1153,6 +1128,7 @@ static int riscv_examine(struct target *target) cache_set_jump(target, 5); cache_run(target, 0); + cache_invalidate(target); #if 0 // TODO @@ -1295,6 +1271,7 @@ static int riscv_assert_reset(struct target *target) // We shouldn't actually need the jump because a reset should happen. dram_write_jump(target, 2, false); dram_write32(target, 4, info->dcsr, true); + cache_invalidate(target); target->state = TARGET_RESET; @@ -1376,25 +1353,26 @@ static int riscv_read_memory(struct target *target, uint32_t address, } } #else - dram_write32(target, 0, lw(S0, ZERO, DEBUG_RAM_START + 16), false); + cache_set(target, 0, lw(S0, ZERO, DEBUG_RAM_START + 16)); switch (size) { case 1: - dram_write32(target, 1, lb(S1, S0, 0), false); - dram_write32(target, 2, sw(S1, ZERO, DEBUG_RAM_START + 16), false); + cache_set(target, 1, lb(S1, S0, 0)); + cache_set(target, 2, sw(S1, ZERO, DEBUG_RAM_START + 16)); break; case 2: - dram_write32(target, 1, lh(S1, S0, 0), false); - dram_write32(target, 2, sw(S1, ZERO, DEBUG_RAM_START + 16), false); + cache_set(target, 1, lh(S1, S0, 0)); + cache_set(target, 2, sw(S1, ZERO, DEBUG_RAM_START + 16)); break; case 4: - dram_write32(target, 1, lw(S1, S0, 0), false); - dram_write32(target, 2, sw(S1, ZERO, DEBUG_RAM_START + 16), false); + cache_set(target, 1, lw(S1, S0, 0)); + cache_set(target, 2, sw(S1, ZERO, DEBUG_RAM_START + 16)); break; default: LOG_ERROR("Unsupported size: %d", size); return ERROR_FAIL; } - dram_write_jump(target, 3, false); + cache_set_jump(target, 3); + cache_run_maybe(target, 4, false); for (unsigned int i = 0; i < count; i++) { dram_write32(target, 4, address + i * size, true); @@ -1434,36 +1412,36 @@ static int riscv_write_memory(struct target *target, uint32_t address, jtag_add_ir_scan(target->tap, &select_dbus, TAP_IDLE); // Set up the address. - dram_write32(target, 0, sw(T0, ZERO, DEBUG_RAM_START + 20), false); - dram_write32(target, 1, lw(T0, ZERO, DEBUG_RAM_START + 16), false); - dram_write_jump(target, 2, false); - dram_write32(target, 4, address, true); - - uint32_t t0; - if (wait_and_read(target, &t0, 5) != ERROR_OK) { - LOG_ERROR("Debug interrupt didn't clear."); + cache_set(target, 0, sw(T0, ZERO, DEBUG_RAM_START + 20)); + cache_set(target, 1, lw(T0, ZERO, DEBUG_RAM_START + 16)); + cache_set_jump(target, 2); + cache_set(target, 4, address); + if (cache_run(target, 5) != ERROR_OK) { return ERROR_FAIL; } + uint32_t t0 = dram_read32(target, 5); + switch (size) { case 1: - dram_write32(target, 0, lb(S0, ZERO, DEBUG_RAM_START + 16), false); - dram_write32(target, 1, sb(S0, T0, 0), false); + cache_set(target, 0, lb(S0, ZERO, DEBUG_RAM_START + 16)); + cache_set(target, 1, sb(S0, T0, 0)); break; case 2: - dram_write32(target, 0, lh(S0, ZERO, DEBUG_RAM_START + 16), false); - dram_write32(target, 1, sh(S0, T0, 0), false); + cache_set(target, 0, lh(S0, ZERO, DEBUG_RAM_START + 16)); + cache_set(target, 1, sh(S0, T0, 0)); break; case 4: - dram_write32(target, 0, lw(S0, ZERO, DEBUG_RAM_START + 16), false); - dram_write32(target, 1, sw(S0, T0, 0), false); + cache_set(target, 0, lw(S0, ZERO, DEBUG_RAM_START + 16)); + cache_set(target, 1, sw(S0, T0, 0)); break; default: LOG_ERROR("Unsupported size: %d", size); return ERROR_FAIL; } - dram_write32(target, 2, addi(T0, T0, size), false); - dram_write_jump(target, 3, false); + cache_set(target, 2, addi(T0, T0, size)); + cache_set_jump(target, 3); + cache_run_maybe(target, 4, false); uint32_t i = 0; while (i < count) { @@ -1488,8 +1466,9 @@ static int riscv_write_memory(struct target *target, uint32_t address, return ERROR_FAIL; } - dbus_status_t status = dbus_scan(target, NULL, DBUS_OP_CONDITIONAL_WRITE, - 4, DMCONTROL_HALTNOT | DMCONTROL_INTERRUPT | value); + dbus_status_t status = dbus_scan(target, NULL, NULL, + DBUS_OP_CONDITIONAL_WRITE, 4, + DMCONTROL_HALTNOT | DMCONTROL_INTERRUPT | value); if (status == DBUS_STATUS_SUCCESS) { i++; } else if (status == DBUS_STATUS_NO_WRITE) {