uint32_t size, uint32_t count, uint8_t *buffer, uint32_t increment);
static int write_memory(struct target *target, target_addr_t address,
uint32_t size, uint32_t count, const uint8_t *buffer);
-static int riscv013_test_sba_config_reg(struct target *target, target_addr_t legal_address,
- uint32_t num_words, target_addr_t illegal_address, bool run_sbbusyerror_test);
-static void write_memory_sba_simple(struct target *target, target_addr_t addr, uint32_t *write_data,
- uint32_t write_size, uint32_t sbcs);
-static void read_memory_sba_simple(struct target *target, target_addr_t addr,
- uint32_t *rd_buf, uint32_t read_size, uint32_t sbcs);
/**
* Since almost everything can be accomplish by scanning the dbus register, all
generic_info->dmi_read = &dmi_read;
generic_info->dmi_write = &dmi_write;
generic_info->read_memory = read_memory;
- generic_info->test_sba_config_reg = &riscv013_test_sba_config_reg;
generic_info->hart_count = &riscv013_hart_count;
generic_info->data_bits = &riscv013_data_bits;
generic_info->print_info = &riscv013_print_info;
buf_set_u64((unsigned char *)buf, DTM_DMI_ADDRESS_OFFSET, info->abits, 0);
}
-/* Helper function for riscv013_test_sba_config_reg */
-static int get_max_sbaccess(struct target *target)
-{
- RISCV013_INFO(info);
-
- uint32_t sbaccess128 = get_field(info->sbcs, DM_SBCS_SBACCESS128);
- uint32_t sbaccess64 = get_field(info->sbcs, DM_SBCS_SBACCESS64);
- uint32_t sbaccess32 = get_field(info->sbcs, DM_SBCS_SBACCESS32);
- uint32_t sbaccess16 = get_field(info->sbcs, DM_SBCS_SBACCESS16);
- uint32_t sbaccess8 = get_field(info->sbcs, DM_SBCS_SBACCESS8);
-
- if (sbaccess128)
- return 4;
- else if (sbaccess64)
- return 3;
- else if (sbaccess32)
- return 2;
- else if (sbaccess16)
- return 1;
- else if (sbaccess8)
- return 0;
- else
- return -1;
-}
-
-static uint32_t get_num_sbdata_regs(struct target *target)
-{
- RISCV013_INFO(info);
-
- uint32_t sbaccess128 = get_field(info->sbcs, DM_SBCS_SBACCESS128);
- uint32_t sbaccess64 = get_field(info->sbcs, DM_SBCS_SBACCESS64);
- uint32_t sbaccess32 = get_field(info->sbcs, DM_SBCS_SBACCESS32);
-
- if (sbaccess128)
- return 4;
- else if (sbaccess64)
- return 2;
- else if (sbaccess32)
- return 1;
- else
- return 0;
-}
-
-static int riscv013_test_sba_config_reg(struct target *target,
- target_addr_t legal_address, uint32_t num_words,
- target_addr_t illegal_address, bool run_sbbusyerror_test)
-{
- LOG_INFO("Testing System Bus Access as defined by RISC-V Debug Spec v0.13");
-
- uint32_t tests_failed = 0;
-
- uint32_t rd_val;
- uint32_t sbcs_orig;
- int retval = dmi_read(target, &sbcs_orig, DM_SBCS);
- if (retval != ERROR_OK)
- return retval;
-
- uint32_t sbcs = sbcs_orig;
- bool test_passed;
-
- int max_sbaccess = get_max_sbaccess(target);
-
- if (max_sbaccess == -1) {
- LOG_ERROR("System Bus Access not supported in this config.");
- return ERROR_FAIL;
- }
-
- if (get_field(sbcs, DM_SBCS_SBVERSION) != 1) {
- LOG_ERROR("System Bus Access unsupported SBVERSION (%d). Only version 1 is supported.",
- get_field(sbcs, DM_SBCS_SBVERSION));
- return ERROR_FAIL;
- }
-
- uint32_t num_sbdata_regs = get_num_sbdata_regs(target);
- assert(num_sbdata_regs);
-
- uint32_t rd_buf[num_sbdata_regs];
-
- /* Test 1: Simple write/read test */
- test_passed = true;
- sbcs = set_field(sbcs_orig, DM_SBCS_SBAUTOINCREMENT, 0);
- dmi_write(target, DM_SBCS, sbcs);
-
- uint32_t test_patterns[4] = {0xdeadbeef, 0xfeedbabe, 0x12345678, 0x08675309};
- for (uint32_t sbaccess = 0; sbaccess <= (uint32_t)max_sbaccess; sbaccess++) {
- sbcs = set_field(sbcs, DM_SBCS_SBACCESS, sbaccess);
- dmi_write(target, DM_SBCS, sbcs);
-
- uint32_t compare_mask = (sbaccess == 0) ? 0xff : (sbaccess == 1) ? 0xffff : 0xffffffff;
-
- for (uint32_t i = 0; i < num_words; i++) {
- uint32_t addr = legal_address + (i << sbaccess);
- uint32_t wr_data[num_sbdata_regs];
- for (uint32_t j = 0; j < num_sbdata_regs; j++)
- wr_data[j] = test_patterns[j] + i;
- write_memory_sba_simple(target, addr, wr_data, num_sbdata_regs, sbcs);
- }
-
- for (uint32_t i = 0; i < num_words; i++) {
- uint32_t addr = legal_address + (i << sbaccess);
- read_memory_sba_simple(target, addr, rd_buf, num_sbdata_regs, sbcs);
- for (uint32_t j = 0; j < num_sbdata_regs; j++) {
- if (((test_patterns[j]+i)&compare_mask) != (rd_buf[j]&compare_mask)) {
- LOG_ERROR("System Bus Access Test 1: Error reading non-autoincremented address %x,"
- "expected val = %x, read val = %x", addr, test_patterns[j]+i, rd_buf[j]);
- test_passed = false;
- tests_failed++;
- }
- }
- }
- }
- if (test_passed)
- LOG_INFO("System Bus Access Test 1: Simple write/read test PASSED.");
-
- /* Test 2: Address autoincrement test */
- target_addr_t curr_addr;
- target_addr_t prev_addr;
- test_passed = true;
- sbcs = set_field(sbcs_orig, DM_SBCS_SBAUTOINCREMENT, 1);
- dmi_write(target, DM_SBCS, sbcs);
-
- for (uint32_t sbaccess = 0; sbaccess <= (uint32_t)max_sbaccess; sbaccess++) {
- sbcs = set_field(sbcs, DM_SBCS_SBACCESS, sbaccess);
- dmi_write(target, DM_SBCS, sbcs);
-
- dmi_write(target, DM_SBADDRESS0, legal_address);
- read_sbcs_nonbusy(target, &sbcs);
- curr_addr = legal_address;
- for (uint32_t i = 0; i < num_words; i++) {
- prev_addr = curr_addr;
- read_sbcs_nonbusy(target, &sbcs);
- curr_addr = sb_read_address(target);
- if ((curr_addr - prev_addr != (uint32_t)(1 << sbaccess)) && (i != 0)) {
- LOG_ERROR("System Bus Access Test 2: Error with address auto-increment, sbaccess = %x.", sbaccess);
- test_passed = false;
- tests_failed++;
- }
- dmi_write(target, DM_SBDATA0, i);
- }
-
- read_sbcs_nonbusy(target, &sbcs);
-
- dmi_write(target, DM_SBADDRESS0, legal_address);
-
- uint32_t val;
- sbcs = set_field(sbcs, DM_SBCS_SBREADONDATA, 1);
- dmi_write(target, DM_SBCS, sbcs);
- dmi_read(target, &val, DM_SBDATA0); /* Dummy read to trigger first system bus read */
- curr_addr = legal_address;
- for (uint32_t i = 0; i < num_words; i++) {
- prev_addr = curr_addr;
- read_sbcs_nonbusy(target, &sbcs);
- curr_addr = sb_read_address(target);
- if ((curr_addr - prev_addr != (uint32_t)(1 << sbaccess)) && (i != 0)) {
- LOG_ERROR("System Bus Access Test 2: Error with address auto-increment, sbaccess = %x", sbaccess);
- test_passed = false;
- tests_failed++;
- }
- dmi_read(target, &val, DM_SBDATA0);
- read_sbcs_nonbusy(target, &sbcs);
- if (i != val) {
- LOG_ERROR("System Bus Access Test 2: Error reading auto-incremented address,"
- "expected val = %x, read val = %x.", i, val);
- test_passed = false;
- tests_failed++;
- }
- }
- }
- if (test_passed)
- LOG_INFO("System Bus Access Test 2: Address auto-increment test PASSED.");
-
- /* Test 3: Read from illegal address */
- read_memory_sba_simple(target, illegal_address, rd_buf, 1, sbcs_orig);
-
- dmi_read(target, &rd_val, DM_SBCS);
- if (get_field(rd_val, DM_SBCS_SBERROR) == 2) {
- sbcs = set_field(sbcs_orig, DM_SBCS_SBERROR, 2);
- dmi_write(target, DM_SBCS, sbcs);
- dmi_read(target, &rd_val, DM_SBCS);
- if (get_field(rd_val, DM_SBCS_SBERROR) == 0)
- LOG_INFO("System Bus Access Test 3: Illegal address read test PASSED.");
- else
- LOG_ERROR("System Bus Access Test 3: Illegal address read test FAILED, unable to clear to 0.");
- } else {
- LOG_ERROR("System Bus Access Test 3: Illegal address read test FAILED, unable to set error code.");
- }
-
- /* Test 4: Write to illegal address */
- write_memory_sba_simple(target, illegal_address, test_patterns, 1, sbcs_orig);
-
- dmi_read(target, &rd_val, DM_SBCS);
- if (get_field(rd_val, DM_SBCS_SBERROR) == 2) {
- sbcs = set_field(sbcs_orig, DM_SBCS_SBERROR, 2);
- dmi_write(target, DM_SBCS, sbcs);
- dmi_read(target, &rd_val, DM_SBCS);
- if (get_field(rd_val, DM_SBCS_SBERROR) == 0)
- LOG_INFO("System Bus Access Test 4: Illegal address write test PASSED.");
- else {
- LOG_ERROR("System Bus Access Test 4: Illegal address write test FAILED, unable to clear to 0.");
- tests_failed++;
- }
- } else {
- LOG_ERROR("System Bus Access Test 4: Illegal address write test FAILED, unable to set error code.");
- tests_failed++;
- }
-
- /* Test 5: Write with unsupported sbaccess size */
- uint32_t sbaccess128 = get_field(sbcs_orig, DM_SBCS_SBACCESS128);
-
- if (sbaccess128) {
- LOG_INFO("System Bus Access Test 5: SBCS sbaccess error test PASSED, all sbaccess sizes supported.");
- } else {
- sbcs = set_field(sbcs_orig, DM_SBCS_SBACCESS, 4);
-
- write_memory_sba_simple(target, legal_address, test_patterns, 1, sbcs);
-
- dmi_read(target, &rd_val, DM_SBCS);
- if (get_field(rd_val, DM_SBCS_SBERROR) == 4) {
- sbcs = set_field(sbcs_orig, DM_SBCS_SBERROR, 4);
- dmi_write(target, DM_SBCS, sbcs);
- dmi_read(target, &rd_val, DM_SBCS);
- if (get_field(rd_val, DM_SBCS_SBERROR) == 0)
- LOG_INFO("System Bus Access Test 5: SBCS sbaccess error test PASSED.");
- else {
- LOG_ERROR("System Bus Access Test 5: SBCS sbaccess error test FAILED, unable to clear to 0.");
- tests_failed++;
- }
- } else {
- LOG_ERROR("System Bus Access Test 5: SBCS sbaccess error test FAILED, unable to set error code.");
- tests_failed++;
- }
- }
-
- /* Test 6: Write to misaligned address */
- sbcs = set_field(sbcs_orig, DM_SBCS_SBACCESS, 1);
-
- write_memory_sba_simple(target, legal_address+1, test_patterns, 1, sbcs);
-
- dmi_read(target, &rd_val, DM_SBCS);
- if (get_field(rd_val, DM_SBCS_SBERROR) == 3) {
- sbcs = set_field(sbcs_orig, DM_SBCS_SBERROR, 3);
- dmi_write(target, DM_SBCS, sbcs);
- dmi_read(target, &rd_val, DM_SBCS);
- if (get_field(rd_val, DM_SBCS_SBERROR) == 0)
- LOG_INFO("System Bus Access Test 6: SBCS address alignment error test PASSED");
- else {
- LOG_ERROR("System Bus Access Test 6: SBCS address alignment error test FAILED, unable to clear to 0.");
- tests_failed++;
- }
- } else {
- LOG_ERROR("System Bus Access Test 6: SBCS address alignment error test FAILED, unable to set error code.");
- tests_failed++;
- }
-
- /* Test 7: Set sbbusyerror, only run this case in simulation as it is likely
- * impossible to hit otherwise */
- if (run_sbbusyerror_test) {
- sbcs = set_field(sbcs_orig, DM_SBCS_SBREADONADDR, 1);
- dmi_write(target, DM_SBCS, sbcs);
-
- for (int i = 0; i < 16; i++)
- dmi_write(target, DM_SBDATA0, 0xdeadbeef);
-
- for (int i = 0; i < 16; i++)
- dmi_write(target, DM_SBADDRESS0, legal_address);
-
- dmi_read(target, &rd_val, DM_SBCS);
- if (get_field(rd_val, DM_SBCS_SBBUSYERROR)) {
- sbcs = set_field(sbcs_orig, DM_SBCS_SBBUSYERROR, 1);
- dmi_write(target, DM_SBCS, sbcs);
- dmi_read(target, &rd_val, DM_SBCS);
- if (get_field(rd_val, DM_SBCS_SBBUSYERROR) == 0)
- LOG_INFO("System Bus Access Test 7: SBCS sbbusyerror test PASSED.");
- else {
- LOG_ERROR("System Bus Access Test 7: SBCS sbbusyerror test FAILED, unable to clear to 0.");
- tests_failed++;
- }
- } else {
- LOG_ERROR("System Bus Access Test 7: SBCS sbbusyerror test FAILED, unable to set error code.");
- tests_failed++;
- }
- }
-
- if (tests_failed == 0) {
- LOG_INFO("ALL TESTS PASSED");
- return ERROR_OK;
- } else {
- LOG_ERROR("%d TESTS FAILED", tests_failed);
- return ERROR_FAIL;
- }
-
-}
-
-static void write_memory_sba_simple(struct target *target, target_addr_t addr,
- uint32_t *write_data, uint32_t write_size, uint32_t sbcs)
-{
- RISCV013_INFO(info);
-
- uint32_t rd_sbcs;
- uint32_t masked_addr;
-
- uint32_t sba_size = get_field(info->sbcs, DM_SBCS_SBASIZE);
-
- read_sbcs_nonbusy(target, &rd_sbcs);
-
- uint32_t sbcs_no_readonaddr = set_field(sbcs, DM_SBCS_SBREADONADDR, 0);
- dmi_write(target, DM_SBCS, sbcs_no_readonaddr);
-
- for (uint32_t i = 0; i < sba_size/32; i++) {
- masked_addr = (addr >> 32*i) & 0xffffffff;
-
- if (i != 3)
- dmi_write(target, DM_SBADDRESS0+i, masked_addr);
- else
- dmi_write(target, DM_SBADDRESS3, masked_addr);
- }
-
- /* Write SBDATA registers starting with highest address, since write to
- * SBDATA0 triggers write */
- for (int i = write_size-1; i >= 0; i--)
- dmi_write(target, DM_SBDATA0+i, write_data[i]);
-}
-
-static void read_memory_sba_simple(struct target *target, target_addr_t addr,
- uint32_t *rd_buf, uint32_t read_size, uint32_t sbcs)
-{
- RISCV013_INFO(info);
-
- uint32_t rd_sbcs;
- uint32_t masked_addr;
-
- uint32_t sba_size = get_field(info->sbcs, DM_SBCS_SBASIZE);
-
- read_sbcs_nonbusy(target, &rd_sbcs);
-
- uint32_t sbcs_readonaddr = set_field(sbcs, DM_SBCS_SBREADONADDR, 1);
- dmi_write(target, DM_SBCS, sbcs_readonaddr);
-
- /* Write addresses starting with highest address register */
- for (int i = sba_size/32-1; i >= 0; i--) {
- masked_addr = (addr >> 32*i) & 0xffffffff;
-
- if (i != 3)
- dmi_write(target, DM_SBADDRESS0+i, masked_addr);
- else
- dmi_write(target, DM_SBADDRESS3, masked_addr);
- }
-
- read_sbcs_nonbusy(target, &rd_sbcs);
-
- for (uint32_t i = 0; i < read_size; i++)
- dmi_read(target, &(rd_buf[i]), DM_SBDATA0+i);
-}
-
int riscv013_dmi_write_u64_bits(struct target *target)
{
RISCV013_INFO(info);