-
-#ifdef _WIN32
-#define FILE_SEP '\\'
-#else
-#define FILE_SEP '/'
-#endif
-#define COMPLIANCE_TEST(b, message) \
-{ \
- const char *last_sep = strrchr(__FILE__, FILE_SEP); \
- const char *fname = (!last_sep ? __FILE__ : last_sep + 1); \
- LOG_INFO("Executing test %d (%s:%d): %s", total_tests, fname, __LINE__, message); \
- int pass = 0; \
- if (b) { \
- pass = 1; \
- passed_tests++; \
- } \
- LOG_INFO(" %s", (pass) ? "PASSED" : "FAILED"); \
- assert(pass); \
- total_tests++; \
-}
-
-#define COMPLIANCE_MUST_PASS(b) COMPLIANCE_TEST(ERROR_OK == (b), "Regular calls must return ERROR_OK")
-
-#define COMPLIANCE_READ(target, addr, value) COMPLIANCE_MUST_PASS(dmi_read(target, addr, value))
-#define COMPLIANCE_WRITE(target, addr, value) COMPLIANCE_MUST_PASS(dmi_write(target, addr, value))
-
-#define COMPLIANCE_CHECK_RO(target, addr) \
-{ \
- uint32_t orig; \
- uint32_t inverse; \
- COMPLIANCE_READ(target, &orig, addr); \
- COMPLIANCE_WRITE(target, addr, ~orig); \
- COMPLIANCE_READ(target, &inverse, addr); \
- COMPLIANCE_TEST(orig == inverse, "Register must be read-only"); \
-}
-
-int riscv013_test_compliance(struct target *target)
-{
- LOG_INFO("Basic compliance test against RISC-V Debug Spec v0.13");
- LOG_INFO("This test is not complete, and not well supported.");
- LOG_INFO("Your core might pass this test without being compliant.");
- LOG_INFO("Your core might fail this test while being compliant.");
- LOG_INFO("Use your judgment, and please contribute improvements.");
-
- if (!riscv_rtos_enabled(target)) {
- LOG_ERROR("Please run with -rtos riscv to run compliance test.");
- return ERROR_FAIL;
- }
-
- if (!target_was_examined(target)) {
- LOG_ERROR("Cannot run compliance test, because target has not yet "
- "been examined, or the examination failed.\n");
- return ERROR_FAIL;
- }
-
- int total_tests = 0;
- int passed_tests = 0;
-
- uint32_t dmcontrol_orig = DM_DMCONTROL_DMACTIVE;
- uint32_t dmcontrol;
- uint32_t testvar;
- uint32_t testvar_read;
- riscv_reg_t value;
- RISCV013_INFO(info);
-
- /* All the bits of HARTSEL are covered by the examine sequence. */
-
- /* hartreset */
- /* This field is optional. Either we can read and write it to 1/0,
- or it is tied to 0. This check doesn't really do anything, but
- it does attempt to set the bit to 1 and then back to 0, which needs to
- work if its implemented. */
- COMPLIANCE_WRITE(target, DM_DMCONTROL, set_field(dmcontrol_orig, DM_DMCONTROL_HARTRESET, 1));
- COMPLIANCE_WRITE(target, DM_DMCONTROL, set_field(dmcontrol_orig, DM_DMCONTROL_HARTRESET, 0));
- COMPLIANCE_READ(target, &dmcontrol, DM_DMCONTROL);
- COMPLIANCE_TEST((get_field(dmcontrol, DM_DMCONTROL_HARTRESET) == 0),
- "DMCONTROL.hartreset can be 0 or RW.");
-
- /* hasel */
- COMPLIANCE_WRITE(target, DM_DMCONTROL, set_field(dmcontrol_orig, DM_DMCONTROL_HASEL, 1));
- COMPLIANCE_WRITE(target, DM_DMCONTROL, set_field(dmcontrol_orig, DM_DMCONTROL_HASEL, 0));
- COMPLIANCE_READ(target, &dmcontrol, DM_DMCONTROL);
- COMPLIANCE_TEST((get_field(dmcontrol, DM_DMCONTROL_HASEL) == 0),
- "DMCONTROL.hasel can be 0 or RW.");
- /* TODO: test that hamask registers exist if hasel does. */
-
- /* haltreq */
- COMPLIANCE_MUST_PASS(riscv_halt(target));
- /* This bit is not actually readable according to the spec, so nothing to check.*/
-
- /* DMSTATUS */
- COMPLIANCE_CHECK_RO(target, DM_DMSTATUS);
-
- /* resumereq */
- /* This bit is not actually readable according to the spec, so nothing to check.*/
- COMPLIANCE_MUST_PASS(riscv_resume(target, true, 0, false, false, false));
-
- /* Halt all harts again so the test can continue.*/
- COMPLIANCE_MUST_PASS(riscv_halt(target));
-
- /* HARTINFO: Read-Only. This is per-hart, so need to adjust hartsel. */
- uint32_t hartinfo;
- COMPLIANCE_READ(target, &hartinfo, DM_HARTINFO);
- for (int hartsel = 0; hartsel < riscv_count_harts(target); hartsel++) {
- COMPLIANCE_MUST_PASS(riscv_set_current_hartid(target, hartsel));
-
- COMPLIANCE_CHECK_RO(target, DM_HARTINFO);
-
- /* $dscratch CSRs */
- uint32_t nscratch = get_field(hartinfo, DM_HARTINFO_NSCRATCH);
- for (unsigned int d = 0; d < nscratch; d++) {
- riscv_reg_t testval, testval_read;
- /* Because DSCRATCH0 is not guaranteed to last across PB executions, need to put
- this all into one PB execution. Which may not be possible on all implementations.*/
- if (info->progbufsize >= 5) {
- for (testval = 0x0011223300112233;
- testval != 0xDEAD;
- testval = testval == 0x0011223300112233 ? ~testval : 0xDEAD) {
- COMPLIANCE_TEST(register_write_direct(target, GDB_REGNO_S0, testval) == ERROR_OK,
- "Need to be able to write S0 in order to test DSCRATCH0.");
- struct riscv_program program32;
- riscv_program_init(&program32, target);
- riscv_program_csrw(&program32, GDB_REGNO_S0, GDB_REGNO_DSCRATCH0 + d);
- riscv_program_csrr(&program32, GDB_REGNO_S1, GDB_REGNO_DSCRATCH0 + d);
- riscv_program_fence(&program32);
- riscv_program_ebreak(&program32);
- COMPLIANCE_TEST(riscv_program_exec(&program32, target) == ERROR_OK,
- "Accessing DSCRATCH0 with program buffer should succeed.");
- COMPLIANCE_TEST(register_read_direct(target, &testval_read, GDB_REGNO_S1) == ERROR_OK,
- "Need to be able to read S1 in order to test DSCRATCH0.");
- if (riscv_xlen(target) > 32) {
- COMPLIANCE_TEST(testval == testval_read,
- "All DSCRATCH0 registers in HARTINFO must be R/W.");
- } else {
- COMPLIANCE_TEST(testval_read == (testval & 0xFFFFFFFF),
- "All DSCRATCH0 registers in HARTINFO must be R/W.");
- }
- }
- }
- }
- /* TODO: dataaccess */
- if (get_field(hartinfo, DM_HARTINFO_DATAACCESS)) {
- /* TODO: Shadowed in memory map. */
- /* TODO: datasize */
- /* TODO: dataaddr */
- } else {
- /* TODO: Shadowed in CSRs. */
- /* TODO: datasize */
- /* TODO: dataaddr */
- }
-
- }
-
- /* HALTSUM -- TODO: More than 32 harts. Would need to loop over this to set hartsel */
- /* TODO: HALTSUM2, HALTSUM3 */
- /* HALTSUM0 */
- uint32_t expected_haltsum0 = 0;
- for (int i = 0; i < MIN(riscv_count_harts(target), 32); i++)
- expected_haltsum0 |= (1 << i);
-
- COMPLIANCE_READ(target, &testvar_read, DM_HALTSUM0);
- COMPLIANCE_TEST(testvar_read == expected_haltsum0,
- "HALTSUM0 should report summary of up to 32 halted harts");
-
- COMPLIANCE_WRITE(target, DM_HALTSUM0, 0xffffffff);
- COMPLIANCE_READ(target, &testvar_read, DM_HALTSUM0);
- COMPLIANCE_TEST(testvar_read == expected_haltsum0, "HALTSUM0 should be R/O");
-
- COMPLIANCE_WRITE(target, DM_HALTSUM0, 0x0);
- COMPLIANCE_READ(target, &testvar_read, DM_HALTSUM0);
- COMPLIANCE_TEST(testvar_read == expected_haltsum0, "HALTSUM0 should be R/O");
-
- /* HALTSUM1 */
- uint32_t expected_haltsum1 = 0;
- for (int i = 0; i < MIN(riscv_count_harts(target), 1024); i += 32)
- expected_haltsum1 |= (1 << (i/32));
-
- COMPLIANCE_READ(target, &testvar_read, DM_HALTSUM1);
- COMPLIANCE_TEST(testvar_read == expected_haltsum1,
- "HALTSUM1 should report summary of up to 1024 halted harts");
-
- COMPLIANCE_WRITE(target, DM_HALTSUM1, 0xffffffff);
- COMPLIANCE_READ(target, &testvar_read, DM_HALTSUM1);
- COMPLIANCE_TEST(testvar_read == expected_haltsum1, "HALTSUM1 should be R/O");
-
- COMPLIANCE_WRITE(target, DM_HALTSUM1, 0x0);
- COMPLIANCE_READ(target, &testvar_read, DM_HALTSUM1);
- COMPLIANCE_TEST(testvar_read == expected_haltsum1, "HALTSUM1 should be R/O");
-
- /* TODO: HAWINDOWSEL */
-
- /* TODO: HAWINDOW */
-
- /* ABSTRACTCS */
-
- uint32_t abstractcs;
- COMPLIANCE_READ(target, &abstractcs, DM_ABSTRACTCS);
-
- /* Check that all reported Data Words are really R/W */
- for (int invert = 0; invert < 2; invert++) {
- for (unsigned int i = 0; i < get_field(abstractcs, DM_ABSTRACTCS_DATACOUNT); i++) {
- testvar = (i + 1) * 0x11111111;
- if (invert)
- testvar = ~testvar;
- COMPLIANCE_WRITE(target, DM_DATA0 + i, testvar);
- }
- for (unsigned int i = 0; i < get_field(abstractcs, DM_ABSTRACTCS_DATACOUNT); i++) {
- testvar = (i + 1) * 0x11111111;
- if (invert)
- testvar = ~testvar;
- COMPLIANCE_READ(target, &testvar_read, DM_DATA0 + i);
- COMPLIANCE_TEST(testvar_read == testvar, "All reported DATA words must be R/W");
- }
- }
-
- /* Check that all reported ProgBuf words are really R/W */
- for (int invert = 0; invert < 2; invert++) {
- for (unsigned int i = 0; i < get_field(abstractcs, DM_ABSTRACTCS_PROGBUFSIZE); i++) {
- testvar = (i + 1) * 0x11111111;
- if (invert)
- testvar = ~testvar;
- COMPLIANCE_WRITE(target, DM_PROGBUF0 + i, testvar);
- }
- for (unsigned int i = 0; i < get_field(abstractcs, DM_ABSTRACTCS_PROGBUFSIZE); i++) {
- testvar = (i + 1) * 0x11111111;
- if (invert)
- testvar = ~testvar;
- COMPLIANCE_READ(target, &testvar_read, DM_PROGBUF0 + i);
- COMPLIANCE_TEST(testvar_read == testvar, "All reported PROGBUF words must be R/W");
- }
- }
-
- /* TODO: Cause and clear all error types */
-
- /* COMMAND
- According to the spec, this register is only W, so can't really check the read result.
- But at any rate, this is not legal and should cause an error. */
- COMPLIANCE_WRITE(target, DM_COMMAND, 0xAAAAAAAA);
- COMPLIANCE_READ(target, &testvar_read, DM_ABSTRACTCS);
- COMPLIANCE_TEST(get_field(testvar_read, DM_ABSTRACTCS_CMDERR) == CMDERR_NOT_SUPPORTED,
- "Illegal COMMAND should result in UNSUPPORTED");
- COMPLIANCE_WRITE(target, DM_ABSTRACTCS, DM_ABSTRACTCS_CMDERR);
-
- COMPLIANCE_WRITE(target, DM_COMMAND, 0x55555555);
- COMPLIANCE_READ(target, &testvar_read, DM_ABSTRACTCS);
- COMPLIANCE_TEST(get_field(testvar_read, DM_ABSTRACTCS_CMDERR) == CMDERR_NOT_SUPPORTED,
- "Illegal COMMAND should result in UNSUPPORTED");
- COMPLIANCE_WRITE(target, DM_ABSTRACTCS, DM_ABSTRACTCS_CMDERR);
-
- /* Basic Abstract Commands */
- for (unsigned int i = 1; i < 32; i = i << 1) {
- riscv_reg_t testval = i | ((i + 1ULL) << 32);
- riscv_reg_t testval_read;
- COMPLIANCE_TEST(register_write_direct(target, GDB_REGNO_ZERO + i, testval) == ERROR_OK,
- "GPR Writes should be supported.");
- COMPLIANCE_MUST_PASS(write_abstract_arg(target, 0, 0xDEADBEEFDEADBEEF, 64));
- COMPLIANCE_TEST(register_read_direct(target, &testval_read, GDB_REGNO_ZERO + i) == ERROR_OK,
- "GPR Reads should be supported.");
- if (riscv_xlen(target) > 32) {
- /* Dummy comment to satisfy linter, since removing the branches here doesn't actually compile. */
- COMPLIANCE_TEST(testval == testval_read, "GPR Reads and writes should be supported.");
- } else {
- /* Dummy comment to satisfy linter, since removing the branches here doesn't actually compile. */
- COMPLIANCE_TEST((testval & 0xFFFFFFFF) == testval_read, "GPR Reads and writes should be supported.");
- }
- }
-
- /* ABSTRACTAUTO
- See which bits are actually writable */
- COMPLIANCE_WRITE(target, DM_ABSTRACTAUTO, 0xFFFFFFFF);
- uint32_t abstractauto;
- uint32_t busy;
- COMPLIANCE_READ(target, &abstractauto, DM_ABSTRACTAUTO);
- COMPLIANCE_WRITE(target, DM_ABSTRACTAUTO, 0x0);
- if (abstractauto > 0) {
- /* This mechanism only works when you have a reasonable sized progbuf, which is not
- a true compliance requirement. */
- if (info->progbufsize >= 3) {
-
- testvar = 0;
- COMPLIANCE_TEST(register_write_direct(target, GDB_REGNO_S0, 0) == ERROR_OK,
- "Need to be able to write S0 to test ABSTRACTAUTO");
- struct riscv_program program;
- COMPLIANCE_MUST_PASS(riscv_program_init(&program, target));
- /* This is also testing that WFI() is a NOP during debug mode. */
- COMPLIANCE_MUST_PASS(riscv_program_insert(&program, wfi()));
- COMPLIANCE_MUST_PASS(riscv_program_addi(&program, GDB_REGNO_S0, GDB_REGNO_S0, 1));
- COMPLIANCE_MUST_PASS(riscv_program_ebreak(&program));
- COMPLIANCE_WRITE(target, DM_ABSTRACTAUTO, 0x0);
- COMPLIANCE_MUST_PASS(riscv_program_exec(&program, target));
- testvar++;
- COMPLIANCE_WRITE(target, DM_ABSTRACTAUTO, 0xFFFFFFFF);
- COMPLIANCE_READ(target, &abstractauto, DM_ABSTRACTAUTO);
- uint32_t autoexec_data = get_field(abstractauto, DM_ABSTRACTAUTO_AUTOEXECDATA);
- uint32_t autoexec_progbuf = get_field(abstractauto, DM_ABSTRACTAUTO_AUTOEXECPROGBUF);
- for (unsigned int i = 0; i < 12; i++) {
- COMPLIANCE_READ(target, &testvar_read, DM_DATA0 + i);
- do {
- COMPLIANCE_READ(target, &testvar_read, DM_ABSTRACTCS);
- busy = get_field(testvar_read, DM_ABSTRACTCS_BUSY);
- } while (busy);
- if (autoexec_data & (1 << i)) {
- COMPLIANCE_TEST(i < get_field(abstractcs, DM_ABSTRACTCS_DATACOUNT),
- "AUTOEXEC may be writable up to DATACOUNT bits.");
- testvar++;
- }
- }
- for (unsigned int i = 0; i < 16; i++) {
- COMPLIANCE_READ(target, &testvar_read, DM_PROGBUF0 + i);
- do {
- COMPLIANCE_READ(target, &testvar_read, DM_ABSTRACTCS);
- busy = get_field(testvar_read, DM_ABSTRACTCS_BUSY);
- } while (busy);
- if (autoexec_progbuf & (1 << i)) {
- COMPLIANCE_TEST(i < get_field(abstractcs, DM_ABSTRACTCS_PROGBUFSIZE),
- "AUTOEXEC may be writable up to PROGBUFSIZE bits.");
- testvar++;
- }
- }
-
- COMPLIANCE_WRITE(target, DM_ABSTRACTAUTO, 0);
- COMPLIANCE_TEST(register_read_direct(target, &value, GDB_REGNO_S0) == ERROR_OK,
- "Need to be able to read S0 to test ABSTRACTAUTO");
-
- COMPLIANCE_TEST(testvar == value,
- "ABSTRACTAUTO should cause COMMAND to run the expected number of times.");
- }
- }
-
- /* Single-Step each hart. */
- for (int hartsel = 0; hartsel < riscv_count_harts(target); hartsel++) {
- COMPLIANCE_MUST_PASS(riscv_set_current_hartid(target, hartsel));
- COMPLIANCE_MUST_PASS(riscv013_on_step(target));
- COMPLIANCE_MUST_PASS(riscv013_step_current_hart(target));
- COMPLIANCE_TEST(riscv_halt_reason(target, hartsel) == RISCV_HALT_SINGLESTEP,
- "Single Step should result in SINGLESTEP");
- }
-
- /* Core Register Tests */
- uint64_t bogus_dpc = 0xdeadbeef;
- for (int hartsel = 0; hartsel < riscv_count_harts(target); hartsel++) {
- COMPLIANCE_MUST_PASS(riscv_set_current_hartid(target, hartsel));
-
- /* DCSR Tests */
- COMPLIANCE_MUST_PASS(register_write_direct(target, GDB_REGNO_DCSR, 0x0));
- COMPLIANCE_MUST_PASS(register_read_direct(target, &value, GDB_REGNO_DCSR));
- COMPLIANCE_TEST(value != 0, "Not all bits in DCSR are writable by Debugger");
- COMPLIANCE_MUST_PASS(register_write_direct(target, GDB_REGNO_DCSR, 0xFFFFFFFF));
- COMPLIANCE_MUST_PASS(register_read_direct(target, &value, GDB_REGNO_DCSR));
- COMPLIANCE_TEST(value != 0, "At least some bits in DCSR must be 1");
-
- /* DPC. Note that DPC is sign-extended. */
- riscv_reg_t dpcmask = 0xFFFFFFFCUL;
- riscv_reg_t dpc;
-
- if (riscv_xlen(target) > 32)
- dpcmask |= (0xFFFFFFFFULL << 32);
-
- if (riscv_supports_extension(target, riscv_current_hartid(target), 'C'))
- dpcmask |= 0x2;
-
- COMPLIANCE_MUST_PASS(register_write_direct(target, GDB_REGNO_DPC, dpcmask));
- COMPLIANCE_MUST_PASS(register_read_direct(target, &dpc, GDB_REGNO_DPC));
- COMPLIANCE_TEST(dpcmask == dpc,
- "DPC must be sign-extended to XLEN and writable to all-1s (except the least significant bits)");
- COMPLIANCE_MUST_PASS(register_write_direct(target, GDB_REGNO_DPC, 0));
- COMPLIANCE_MUST_PASS(register_read_direct(target, &dpc, GDB_REGNO_DPC));
- COMPLIANCE_TEST(dpc == 0, "DPC must be writable to 0.");
- if (hartsel == 0)
- bogus_dpc = dpc; /* For a later test step */
- }
-
- /* NDMRESET
- Asserting non-debug module reset should not reset Debug Module state.
- But it should reset Hart State, e.g. DPC should get a different value.
- Also make sure that DCSR reports cause of 'HALT' even though previously we single-stepped.
- */
-
- /* Write some registers. They should not be impacted by ndmreset. */
- COMPLIANCE_WRITE(target, DM_COMMAND, 0xFFFFFFFF);
-
- for (unsigned int i = 0; i < get_field(abstractcs, DM_ABSTRACTCS_PROGBUFSIZE); i++) {
- testvar = (i + 1) * 0x11111111;
- COMPLIANCE_WRITE(target, DM_PROGBUF0 + i, testvar);
- }
-
- for (unsigned int i = 0; i < get_field(abstractcs, DM_ABSTRACTCS_DATACOUNT); i++) {
- testvar = (i + 1) * 0x11111111;
- COMPLIANCE_WRITE(target, DM_DATA0 + i, testvar);
- }
-
- COMPLIANCE_WRITE(target, DM_ABSTRACTAUTO, 0xFFFFFFFF);
- COMPLIANCE_READ(target, &abstractauto, DM_ABSTRACTAUTO);
-
- /* Pulse reset. */
- target->reset_halt = true;
- COMPLIANCE_MUST_PASS(riscv_set_current_hartid(target, 0));
- COMPLIANCE_TEST(assert_reset(target) == ERROR_OK, "Must be able to assert NDMRESET");
- COMPLIANCE_TEST(deassert_reset(target) == ERROR_OK, "Must be able to deassert NDMRESET");
-
- /* Verify that most stuff is not affected by ndmreset. */
- COMPLIANCE_READ(target, &testvar_read, DM_ABSTRACTCS);
- COMPLIANCE_TEST(get_field(testvar_read, DM_ABSTRACTCS_CMDERR) == CMDERR_NOT_SUPPORTED,
- "NDMRESET should not affect DM_ABSTRACTCS");
- COMPLIANCE_READ(target, &testvar_read, DM_ABSTRACTAUTO);
- COMPLIANCE_TEST(testvar_read == abstractauto, "NDMRESET should not affect DM_ABSTRACTAUTO");
-
- /* Clean up to avoid future test failures */
- COMPLIANCE_WRITE(target, DM_ABSTRACTCS, DM_ABSTRACTCS_CMDERR);
- COMPLIANCE_WRITE(target, DM_ABSTRACTAUTO, 0);
-
- for (unsigned int i = 0; i < get_field(abstractcs, DM_ABSTRACTCS_PROGBUFSIZE); i++) {
- testvar = (i + 1) * 0x11111111;
- COMPLIANCE_READ(target, &testvar_read, DM_PROGBUF0 + i);
- COMPLIANCE_TEST(testvar_read == testvar, "PROGBUF words must not be affected by NDMRESET");
- }
-
- for (unsigned int i = 0; i < get_field(abstractcs, DM_ABSTRACTCS_DATACOUNT); i++) {
- testvar = (i + 1) * 0x11111111;
- COMPLIANCE_READ(target, &testvar_read, DM_DATA0 + i);
- COMPLIANCE_TEST(testvar_read == testvar, "DATA words must not be affected by NDMRESET");
- }
-
- /* Verify that DPC *is* affected by ndmreset. Since we don't know what it *should* be,
- just verify that at least it's not the bogus value anymore. */
-
- COMPLIANCE_TEST(bogus_dpc != 0xdeadbeef, "BOGUS DPC should have been set somehow (bug in compliance test)");
- COMPLIANCE_MUST_PASS(register_read_direct(target, &value, GDB_REGNO_DPC));
- COMPLIANCE_TEST(bogus_dpc != value, "NDMRESET should move DPC to reset value.");
-
- COMPLIANCE_TEST(riscv_halt_reason(target, 0) == RISCV_HALT_INTERRUPT,
- "After NDMRESET halt, DCSR should report cause of halt");
-
- /* DMACTIVE -- deasserting DMACTIVE should reset all the above values. */
-
- /* Toggle dmactive */
- COMPLIANCE_WRITE(target, DM_DMCONTROL, 0);
- COMPLIANCE_WRITE(target, DM_DMCONTROL, DM_DMCONTROL_DMACTIVE);
- COMPLIANCE_READ(target, &testvar_read, DM_ABSTRACTCS);
- COMPLIANCE_TEST(get_field(testvar_read, DM_ABSTRACTCS_CMDERR) == 0, "ABSTRACTCS.cmderr should reset to 0");
- COMPLIANCE_READ(target, &testvar_read, DM_ABSTRACTAUTO);
- COMPLIANCE_TEST(testvar_read == 0, "ABSTRACTAUTO should reset to 0");
-
- for (unsigned int i = 0; i < get_field(abstractcs, DM_ABSTRACTCS_PROGBUFSIZE); i++) {
- COMPLIANCE_READ(target, &testvar_read, DM_PROGBUF0 + i);
- COMPLIANCE_TEST(testvar_read == 0, "PROGBUF words should reset to 0");
- }
-
- for (unsigned int i = 0; i < get_field(abstractcs, DM_ABSTRACTCS_DATACOUNT); i++) {
- COMPLIANCE_READ(target, &testvar_read, DM_DATA0 + i);
- COMPLIANCE_TEST(testvar_read == 0, "DATA words should reset to 0");
- }
-
- /*
- * TODO:
- * DCSR.cause priorities
- * DCSR.stoptime/stopcycle
- * DCSR.stepie
- * DCSR.ebreak
- * DCSR.prv
- */
-
- /* Halt every hart for any follow-up tests*/
- COMPLIANCE_MUST_PASS(riscv_halt(target));
-
- uint32_t failed_tests = total_tests - passed_tests;
- if (total_tests == passed_tests) {
- LOG_INFO("ALL TESTS PASSED\n");
- return ERROR_OK;
- } else {
- LOG_INFO("%d TESTS FAILED\n", failed_tests);
- return ERROR_FAIL;
- }
-}