riscv-compliance: Fix OpenOCD lint checks
This commit is contained in:
parent
bc32aaafa4
commit
fa99b8e3b1
|
@ -2934,7 +2934,8 @@ void riscv013_clear_abstract_error(struct target *target)
|
|||
dmi_write(target, DMI_ABSTRACTCS, abstractcs & DMI_ABSTRACTCS_CMDERR);
|
||||
}
|
||||
|
||||
#define COMPLIANCE_TEST(b, message) { \
|
||||
#define COMPLIANCE_TEST(b, message) \
|
||||
{ \
|
||||
int pass = 0; \
|
||||
if (b) { \
|
||||
pass = 1; \
|
||||
|
@ -2945,7 +2946,8 @@ void riscv013_clear_abstract_error(struct target *target)
|
|||
total_tests++; \
|
||||
}
|
||||
|
||||
int riscv013_test_compliance(struct target *target) {
|
||||
int riscv013_test_compliance(struct target *target)
|
||||
{
|
||||
LOG_INFO("Testing Compliance against RISC-V Debug Spec v0.13");
|
||||
|
||||
if (!riscv_rtos_enabled(target)) {
|
||||
|
@ -2966,14 +2968,15 @@ int riscv013_test_compliance(struct target *target) {
|
|||
dmcontrol = set_field(dmcontrol_orig, hartsel_mask(target), RISCV_MAX_HARTS-1);
|
||||
dmi_write(target, DMI_DMCONTROL, dmcontrol);
|
||||
dmi_read(target, &dmcontrol, DMI_DMCONTROL);
|
||||
COMPLIANCE_TEST(get_field(dmcontrol, hartsel_mask(target)) == (RISCV_MAX_HARTS-1), "DMCONTROL.hartsel should hold all the harts allowed by HARTSELLEN.");
|
||||
COMPLIANCE_TEST(get_field(dmcontrol, hartsel_mask(target)) == (RISCV_MAX_HARTS-1),
|
||||
"DMCONTROL.hartsel should hold all the harts allowed by HARTSELLEN.");
|
||||
|
||||
dmcontrol = set_field(dmcontrol_orig, hartsel_mask(target), 0);
|
||||
dmi_write(target, DMI_DMCONTROL, dmcontrol);
|
||||
dmi_read(target, &dmcontrol, DMI_DMCONTROL);
|
||||
COMPLIANCE_TEST(get_field(dmcontrol, hartsel_mask(target)) == 0, "DMCONTROL.hartsel should hold Hart ID 0");
|
||||
|
||||
// hartreset
|
||||
/* hartreset */
|
||||
dmcontrol = set_field(dmcontrol_orig, DMI_DMCONTROL_HARTRESET, 1);
|
||||
dmi_write(target, DMI_DMCONTROL, dmcontrol);
|
||||
dmi_read(target, &dmcontrol, DMI_DMCONTROL);
|
||||
|
@ -2981,9 +2984,10 @@ int riscv013_test_compliance(struct target *target) {
|
|||
dmcontrol = set_field(dmcontrol_orig, DMI_DMCONTROL_HARTRESET, 1);
|
||||
dmi_write(target, DMI_DMCONTROL, dmcontrol);
|
||||
dmi_read(target, &dmcontrol, DMI_DMCONTROL);
|
||||
COMPLIANCE_TEST(((testvar == 0) || (get_field(dmcontrol, DMI_DMCONTROL_HARTRESET)) == 0), "DMCONTROL.hartreset can be 0 or RW.");
|
||||
COMPLIANCE_TEST(((testvar == 0) || (get_field(dmcontrol, DMI_DMCONTROL_HARTRESET)) == 0),
|
||||
"DMCONTROL.hartreset can be 0 or RW.");
|
||||
|
||||
// hasel
|
||||
/* hasel */
|
||||
dmcontrol = set_field(dmcontrol_orig, DMI_DMCONTROL_HASEL, 1);
|
||||
dmi_write(target, DMI_DMCONTROL, dmcontrol);
|
||||
dmi_read(target, &dmcontrol, DMI_DMCONTROL);
|
||||
|
@ -2991,13 +2995,14 @@ int riscv013_test_compliance(struct target *target) {
|
|||
dmcontrol = set_field(dmcontrol_orig, DMI_DMCONTROL_HASEL, 1);
|
||||
dmi_write(target, DMI_DMCONTROL, dmcontrol);
|
||||
dmi_read(target, &dmcontrol, DMI_DMCONTROL);
|
||||
COMPLIANCE_TEST(((testvar == 0) || (get_field(dmcontrol, DMI_DMCONTROL_HASEL)) == 0), "DMCONTROL.hasel can be 0 or RW.");
|
||||
//TODO: test that hamask registers exist if hasel does.
|
||||
COMPLIANCE_TEST(((testvar == 0) || (get_field(dmcontrol, DMI_DMCONTROL_HASEL)) == 0),
|
||||
"DMCONTROL.hasel can be 0 or RW.");
|
||||
/* TODO: test that hamask registers exist if hasel does. */
|
||||
|
||||
// haltreq
|
||||
/* haltreq */
|
||||
riscv_halt_all_harts(target);
|
||||
// Writing haltreq should not cause any problems for a halted hart, but we
|
||||
// should be able to read and write it.
|
||||
/* Writing haltreq should not cause any problems for a halted hart, but we
|
||||
should be able to read and write it. */
|
||||
dmi_read(target, &dmcontrol, DMI_DMCONTROL);
|
||||
dmcontrol |= DMI_DMCONTROL_HALTREQ;
|
||||
dmi_write(target, DMI_DMCONTROL, dmcontrol);
|
||||
|
@ -3012,18 +3017,19 @@ int riscv013_test_compliance(struct target *target) {
|
|||
dmi_read(target, &dmstatus_read, DMI_DMSTATUS);
|
||||
COMPLIANCE_TEST(dmstatus_read == dmstatus, "DMSTATUS is R/O");
|
||||
|
||||
// resumereq. This will resume the hart but this test is destructive anyway.
|
||||
/* resumereq. This will resume the hart but this test is destructive anyway. */
|
||||
dmcontrol &= ~DMI_DMCONTROL_HALTREQ;
|
||||
dmcontrol = set_field(dmcontrol, DMI_DMCONTROL_RESUMEREQ, 1);
|
||||
dmi_write(target, DMI_DMCONTROL, dmcontrol);
|
||||
dmi_read(target, &dmcontrol, DMI_DMCONTROL);
|
||||
COMPLIANCE_TEST(get_field(dmcontrol, DMI_DMCONTROL_RESUMEREQ) == 1, "DMCONTROL.resumereq should be R/W");
|
||||
COMPLIANCE_TEST(get_field(dmcontrol, DMI_DMCONTROL_RESUMEREQ) == 1,
|
||||
"DMCONTROL.resumereq should be R/W");
|
||||
|
||||
do {
|
||||
dmi_read(target, &dmstatus, DMI_DMSTATUS);
|
||||
} while (get_field(dmstatus, DMI_DMSTATUS_ALLRESUMEACK) == 0);
|
||||
|
||||
// Halt the hart again because the target isn't aware that we resumed it.
|
||||
/* Halt the hart again because the target isn't aware that we resumed it. */
|
||||
dmcontrol = set_field(dmcontrol, DMI_DMCONTROL_RESUMEREQ, 0);
|
||||
dmcontrol |= DMI_DMCONTROL_HALTREQ;
|
||||
dmi_write(target, DMI_DMCONTROL, dmcontrol);
|
||||
|
@ -3032,10 +3038,10 @@ int riscv013_test_compliance(struct target *target) {
|
|||
} while ((dmstatus & DMI_DMSTATUS_ALLHALTED) == 0);
|
||||
dmcontrol &= ~DMI_DMCONTROL_HALTREQ;
|
||||
dmi_write(target, DMI_DMCONTROL, dmcontrol);
|
||||
// Not clear that this read is required according to the spec.
|
||||
/* Not clear that this read is required according to the spec. */
|
||||
dmi_read(target, &dmstatus, DMI_DMSTATUS);
|
||||
|
||||
// HARTINFO: Read-Only. This is per-hart, so need to adjust hartsel.
|
||||
/* HARTINFO: Read-Only. This is per-hart, so need to adjust hartsel. */
|
||||
for (int hartsel = 0; hartsel < riscv_count_harts(target); hartsel++) {
|
||||
riscv_set_current_hartid(target, hartsel);
|
||||
|
||||
|
@ -3047,47 +3053,53 @@ int riscv013_test_compliance(struct target *target) {
|
|||
|
||||
uint32_t nscratch = get_field(hartinfo, DMI_HARTINFO_NSCRATCH);
|
||||
for (unsigned int d = 0; d < nscratch; d++) {
|
||||
|
||||
//TODO: DSCRATCH CSRs should be 64-bit on 64-bit systems.
|
||||
/* TODO: DSCRATCH CSRs should be 64-bit on 64-bit systems. */
|
||||
riscv_reg_t testval;
|
||||
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 DSCRATCH.");
|
||||
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 DSCRATCH.");
|
||||
struct riscv_program program32;
|
||||
riscv_program_init(&program32, target);
|
||||
riscv_program_csrw(&program32, GDB_REGNO_S0, GDB_REGNO_DSCRATCH + d);
|
||||
riscv_program_csrr(&program32, GDB_REGNO_S1, GDB_REGNO_DSCRATCH + d);
|
||||
riscv_program_fence(&program32);
|
||||
riscv_program_ebreak(&program32);
|
||||
COMPLIANCE_TEST(riscv_program_exec(&program32, target) == ERROR_OK, "Accessing DSCRATCH with program buffer should succeed.");
|
||||
COMPLIANCE_TEST(register_read_direct(target, &value, GDB_REGNO_S1) == ERROR_OK, "Need to be able to read S1 in order to test DSCRATCH.");
|
||||
if (riscv_xlen(target) > 32) {
|
||||
COMPLIANCE_TEST(value == testval, "All DSCRATCH registers in HARTINFO must be R/W.");
|
||||
} else {
|
||||
COMPLIANCE_TEST(value == (testval & 0xFFFFFFFF), "All DSCRATCH registers in HARTINFO must be R/W.");
|
||||
COMPLIANCE_TEST(riscv_program_exec(&program32, target) == ERROR_OK,
|
||||
"Accessing DSCRATCH with program buffer should succeed.");
|
||||
COMPLIANCE_TEST(register_read_direct(target, &value, GDB_REGNO_S1) == ERROR_OK,
|
||||
"Need to be able to read S1 in order to test DSCRATCH.");
|
||||
if (riscv_xlen(target) > 32)
|
||||
COMPLIANCE_TEST(value == testval,
|
||||
"All DSCRATCH registers in HARTINFO must be R/W.");
|
||||
else
|
||||
COMPLIANCE_TEST(value == (testval & 0xFFFFFFFF),
|
||||
"All DSCRATCH registers in HARTINFO must be R/W.");
|
||||
}
|
||||
}
|
||||
}
|
||||
// TODO: dataaccess
|
||||
/* TODO: dataaccess */
|
||||
if (get_field(hartinfo, DMI_HARTINFO_DATAACCESS)) {
|
||||
// TODO: Shadowed in memory map.
|
||||
// TODO: datasize
|
||||
// TODO: dataaddr
|
||||
/* TODO: Shadowed in memory map. */
|
||||
/* TODO: datasize */
|
||||
/* TODO: dataaddr */
|
||||
} else {
|
||||
// TODO: Shadowed in CSRs.
|
||||
// TODO: datasize
|
||||
// TODO: dataaddr
|
||||
/* TODO: Shadowed in CSRs. */
|
||||
/* TODO: datasize */
|
||||
/* TODO: dataaddr */
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// HALTSUM -- TODO: More than 32 harts
|
||||
// TODO: HALTSUM2, HALTSUM3
|
||||
/* HALTSUM -- TODO: More than 32 harts */
|
||||
/* TODO: HALTSUM2, HALTSUM3 */
|
||||
uint32_t expected_haltsum0 = 0;
|
||||
for (int i = 0; i < riscv_count_harts(target); i +=32){
|
||||
for (int i = 0; i < riscv_count_harts(target); i += 32)
|
||||
expected_haltsum0 |= (1 << (i / 32));
|
||||
}
|
||||
|
||||
dmi_read(target, &testvar_read, DMI_HALTSUM0);
|
||||
COMPLIANCE_TEST(testvar_read == expected_haltsum0, "HALTSUM0 should report summary of 32 halted harts");
|
||||
COMPLIANCE_TEST(testvar_read == expected_haltsum0,
|
||||
"HALTSUM0 should report summary of 32 halted harts");
|
||||
|
||||
dmi_write(target, DMI_HALTSUM0, 0xffffffff);
|
||||
dmi_read(target, &testvar_read, DMI_HALTSUM0);
|
||||
|
@ -3098,12 +3110,15 @@ int riscv013_test_compliance(struct target *target) {
|
|||
COMPLIANCE_TEST(testvar_read == expected_haltsum0, "HALTSUM0 should be R/O");
|
||||
|
||||
for (int i = 0; i < 32/*TODO: riscv_count_harts(target)*/; i += 32) {
|
||||
//TODO: Set hartsel for i > 32 harts.
|
||||
/* TODO: Set hartsel for i > 32 harts. */
|
||||
dmi_read(target, &testvar_read, DMI_HALTSUM1);
|
||||
uint32_t haltsum1_expected = (((i + 1) * 32) <= riscv_count_harts(target)) ? 0xFFFFFFFFU : ((1U << (riscv_count_harts(target) % 32)) - 1);
|
||||
COMPLIANCE_TEST(testvar_read == haltsum1_expected, "HALTSUM1 should report summary of 1024 halted harts");
|
||||
uint32_t haltsum1_expected = (((i + 1) * 32) <= riscv_count_harts(target)) ?
|
||||
0xFFFFFFFFU :
|
||||
((1U << (riscv_count_harts(target) % 32)) - 1);
|
||||
COMPLIANCE_TEST(testvar_read == haltsum1_expected,
|
||||
"HALTSUM1 should report summary of 1024 halted harts");
|
||||
|
||||
// Just have to check this once
|
||||
/* Just have to check this once */
|
||||
if (i == 0) {
|
||||
dmi_write(target, DMI_HALTSUM1, 0xffffffff);
|
||||
dmi_read(target, &testvar_read, DMI_HALTSUM1);
|
||||
|
@ -3115,50 +3130,54 @@ int riscv013_test_compliance(struct target *target) {
|
|||
}
|
||||
}
|
||||
|
||||
// TODO: HAWINDOWSEL
|
||||
/* TODO: HAWINDOWSEL */
|
||||
|
||||
// TODO: HAWINDOW
|
||||
/* TODO: HAWINDOW */
|
||||
|
||||
// ABSTRACTCS
|
||||
/* ABSTRACTCS */
|
||||
|
||||
uint32_t abstractcs;
|
||||
dmi_read(target, &abstractcs, DMI_ABSTRACTCS);
|
||||
|
||||
// Check that all reported Data Words are really R/W
|
||||
/* 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, DMI_ABSTRACTCS_DATACOUNT); i++) {
|
||||
testvar = (i + 1) * 0x11111111;
|
||||
if (invert) {testvar = ~testvar;}
|
||||
if (invert)
|
||||
testvar = ~testvar;
|
||||
dmi_write(target, DMI_DATA0 + i, testvar);
|
||||
}
|
||||
for (unsigned int i = 0; i < get_field(abstractcs, DMI_ABSTRACTCS_DATACOUNT); i++) {
|
||||
testvar = (i + 1) * 0x11111111;
|
||||
if (invert) {testvar = ~testvar;}
|
||||
if (invert)
|
||||
testvar = ~testvar;
|
||||
dmi_read(target, &testvar_read, DMI_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
|
||||
/*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, DMI_ABSTRACTCS_PROGBUFSIZE); i++) {
|
||||
testvar = (i + 1) * 0x11111111;
|
||||
if (invert) {testvar = ~testvar;}
|
||||
if (invert)
|
||||
testvar = ~testvar;
|
||||
dmi_write(target, DMI_PROGBUF0 + i, testvar);
|
||||
}
|
||||
for (unsigned int i = 0; i < get_field(abstractcs, DMI_ABSTRACTCS_PROGBUFSIZE); i++) {
|
||||
testvar = (i + 1) * 0x11111111;
|
||||
if (invert) {testvar = ~testvar;}
|
||||
if (invert)
|
||||
testvar = ~testvar;
|
||||
dmi_read(target, &testvar_read, DMI_PROGBUF0 + i);
|
||||
COMPLIANCE_TEST(testvar_read == testvar, "All reported PROGBUF words must be R/W");
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Cause and clear all error types
|
||||
/* TODO: Cause and clear all error types */
|
||||
|
||||
// COMMAND
|
||||
// TODO: Unclear from the spec whether all these bits need to truly be R/W.
|
||||
// But at any rate, this is not legal and should cause an error.
|
||||
/* COMMAND
|
||||
TODO: Unclear from the spec whether all these bits need to truly be R/W.
|
||||
But at any rate, this is not legal and should cause an error. */
|
||||
dmi_write(target, DMI_COMMAND, 0xAAAAAAAA);
|
||||
dmi_read(target, &testvar_read, DMI_COMMAND);
|
||||
COMPLIANCE_TEST(testvar_read == 0xAAAAAAAA, "COMMAND register should be R/W");
|
||||
|
@ -3174,7 +3193,7 @@ int riscv013_test_compliance(struct target *target) {
|
|||
"Illegal COMMAND should result in UNSUPPORTED");
|
||||
dmi_write(target, DMI_ABSTRACTCS, DMI_ABSTRACTCS_CMDERR);
|
||||
|
||||
// Basic Abstract Commands
|
||||
/* Basic Abstract Commands */
|
||||
uint32_t command = 0;
|
||||
uint32_t busy;
|
||||
command = set_field(command, AC_ACCESS_REGISTER_SIZE, riscv_xlen(target) > 32 ? 3 : 2);
|
||||
|
@ -3183,20 +3202,19 @@ int riscv013_test_compliance(struct target *target) {
|
|||
command = set_field(command, AC_ACCESS_REGISTER_REGNO, 0x1000 + GDB_REGNO_ZERO + i);
|
||||
command = set_field(command, AC_ACCESS_REGISTER_WRITE, 1);
|
||||
dmi_write(target, DMI_DATA0, i);
|
||||
if (riscv_xlen(target) > 32) {
|
||||
if (riscv_xlen(target) > 32)
|
||||
dmi_write(target, DMI_DATA0 + 1, i + 1);
|
||||
}
|
||||
dmi_write(target, DMI_COMMAND, command);
|
||||
do {
|
||||
dmi_read(target, &testvar_read, DMI_ABSTRACTCS);
|
||||
busy = get_field(testvar_read, DMI_ABSTRACTCS_BUSY);
|
||||
} while (busy);
|
||||
dmi_read(target, &testvar_read, DMI_ABSTRACTCS);
|
||||
COMPLIANCE_TEST(get_field(testvar_read, DMI_ABSTRACTCS_CMDERR) == 0, "GPR Writes should be supported.");
|
||||
COMPLIANCE_TEST(get_field(testvar_read, DMI_ABSTRACTCS_CMDERR) == 0,
|
||||
"GPR Writes should be supported.");
|
||||
dmi_write(target, DMI_DATA0, 0xDEADBEEF);
|
||||
if (riscv_xlen(target) > 32) {
|
||||
if (riscv_xlen(target) > 32)
|
||||
dmi_write(target, DMI_DATA0 + 1, 0xDEADBEEF);
|
||||
}
|
||||
command = set_field(command, AC_ACCESS_REGISTER_WRITE, 0);
|
||||
dmi_write(target, DMI_COMMAND, command);
|
||||
do {
|
||||
|
@ -3204,30 +3222,32 @@ int riscv013_test_compliance(struct target *target) {
|
|||
busy = get_field(testvar_read, DMI_ABSTRACTCS_BUSY);
|
||||
} while (busy);
|
||||
dmi_read(target, &testvar_read, DMI_ABSTRACTCS);
|
||||
COMPLIANCE_TEST(get_field(testvar_read, DMI_ABSTRACTCS_CMDERR) == 0, "GPR Reads should be supported.");
|
||||
COMPLIANCE_TEST(get_field(testvar_read, DMI_ABSTRACTCS_CMDERR) == 0,
|
||||
"GPR Reads should be supported.");
|
||||
dmi_read(target, &testvar_read, DMI_DATA0);
|
||||
COMPLIANCE_TEST(testvar_read == i, "GPR Reads and writes should be supported.");
|
||||
if (riscv_xlen(target) > 32) {
|
||||
dmi_read(target, &testvar_read, DMI_DATA0 + 1);
|
||||
COMPLIANCE_TEST(testvar_read == (i + 1), "GPR Reads and writes should be supported.");
|
||||
COMPLIANCE_TEST(testvar_read == (i + 1),
|
||||
"GPR Reads and writes should be supported.");
|
||||
}
|
||||
}
|
||||
|
||||
// ABSTRACTAUTO
|
||||
// See which bits are actually writable
|
||||
/* ABSTRACTAUTO
|
||||
See which bits are actually writable */
|
||||
dmi_write(target, DMI_ABSTRACTAUTO, 0xFFFFFFFF);
|
||||
uint32_t abstractauto;
|
||||
dmi_read(target, &abstractauto, DMI_ABSTRACTAUTO);
|
||||
dmi_write(target, DMI_ABSTRACTAUTO, 0x0);
|
||||
if (abstractauto > 0) {
|
||||
testvar = 0;
|
||||
// TODO: This mechanism only works when you have a reasonable sized progbuf, which is not
|
||||
// a true compliance requirement.
|
||||
/* TODO: This mechanism only works when you have a reasonable sized progbuf, which is not
|
||||
a true compliance requirement. */
|
||||
uint32_t result = riscv_set_register(target, GDB_REGNO_S0, 0);
|
||||
COMPLIANCE_TEST(result == ERROR_OK, "Need to be able to write S0 to test ABSTRACTAUTO");
|
||||
struct riscv_program program;
|
||||
riscv_program_init(&program, target);
|
||||
// Also testing that WFI() is a NOP during debug mode.
|
||||
/* Also testing that WFI() is a NOP during debug mode. */
|
||||
riscv_program_insert(&program, wfi());
|
||||
riscv_program_addi(&program, GDB_REGNO_S0, GDB_REGNO_S0, 1);
|
||||
riscv_program_ebreak(&program);
|
||||
|
@ -3245,7 +3265,8 @@ int riscv013_test_compliance(struct target *target) {
|
|||
busy = get_field(testvar_read, DMI_ABSTRACTCS_BUSY);
|
||||
} while (busy);
|
||||
if (autoexec_data & (1 << i)) {
|
||||
COMPLIANCE_TEST(i < get_field(abstractcs, DMI_ABSTRACTCS_DATACOUNT), "AUTOEXEC may be writable up to DATACOUNT bits.");
|
||||
COMPLIANCE_TEST(i < get_field(abstractcs, DMI_ABSTRACTCS_DATACOUNT),
|
||||
"AUTOEXEC may be writable up to DATACOUNT bits.");
|
||||
testvar++;
|
||||
}
|
||||
}
|
||||
|
@ -3256,7 +3277,8 @@ int riscv013_test_compliance(struct target *target) {
|
|||
busy = get_field(testvar_read, DMI_ABSTRACTCS_BUSY);
|
||||
} while (busy);
|
||||
if (autoexec_progbuf & (1 << i)) {
|
||||
COMPLIANCE_TEST(i < get_field(abstractcs, DMI_ABSTRACTCS_PROGBUFSIZE), "AUTOEXEC may be writable up to PROGBUFSIZE bits.");
|
||||
COMPLIANCE_TEST(i < get_field(abstractcs, DMI_ABSTRACTCS_PROGBUFSIZE),
|
||||
"AUTOEXEC may be writable up to PROGBUFSIZE bits.");
|
||||
testvar++;
|
||||
}
|
||||
}
|
||||
|
@ -3268,20 +3290,21 @@ int riscv013_test_compliance(struct target *target) {
|
|||
"ABSTRACTAUTO should cause COMMAND to run the expected number of times.");
|
||||
}
|
||||
|
||||
// Single-Step each hart.
|
||||
/* Single-Step each hart. */
|
||||
for (int hartsel = 0; hartsel < riscv_count_harts(target); hartsel++) {
|
||||
riscv_set_current_hartid(target, hartsel);
|
||||
riscv013_on_step(target);
|
||||
riscv013_step_current_hart(target);
|
||||
COMPLIANCE_TEST(riscv_halt_reason(target, hartsel) == RISCV_HALT_SINGLESTEP, "Single Step should result in SINGLESTEP");
|
||||
COMPLIANCE_TEST(riscv_halt_reason(target, hartsel) == RISCV_HALT_SINGLESTEP,
|
||||
"Single Step should result in SINGLESTEP");
|
||||
}
|
||||
|
||||
// Core Register Tests
|
||||
/* Core Register Tests */
|
||||
uint64_t bogus_dpc = 0xdeadbeef;
|
||||
for (int hartsel = 0; hartsel < riscv_count_harts(target); hartsel++) {
|
||||
riscv_set_current_hartid(target, hartsel);
|
||||
|
||||
// DCSR Tests
|
||||
/* DCSR Tests */
|
||||
riscv_set_register(target, GDB_REGNO_DCSR, 0x0);
|
||||
riscv_get_register(target, &value, GDB_REGNO_DCSR);
|
||||
COMPLIANCE_TEST(value != 0, "Not all bits in DCSR are writable by Debugger");
|
||||
|
@ -3289,33 +3312,34 @@ int riscv013_test_compliance(struct target *target) {
|
|||
riscv_get_register(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.
|
||||
/* DPC. Note that DPC is sign-extended. */
|
||||
riscv_reg_t dpcmask = 0xFFFFFFFCUL;
|
||||
riscv_reg_t dpc;
|
||||
|
||||
if (riscv_xlen(target) > 32) {
|
||||
if (riscv_xlen(target) > 32)
|
||||
dpcmask |= (0xFFFFFFFFULL << 32);
|
||||
}
|
||||
if (riscv_supports_extension(target, riscv_current_hartid(target), 'C')){
|
||||
|
||||
if (riscv_supports_extension(target, riscv_current_hartid(target), 'C'))
|
||||
dpcmask |= 0x2;
|
||||
}
|
||||
|
||||
riscv_set_register(target, GDB_REGNO_DPC, dpcmask);
|
||||
riscv_get_register(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_TEST(dpcmask == dpc,
|
||||
"DPC must be sign-extended to XLEN and writable to all-1s (except the least significant bits)");
|
||||
riscv_set_register(target, GDB_REGNO_DPC, 0);
|
||||
riscv_get_register(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
|
||||
if (hartsel == 0)
|
||||
bogus_dpc = dpc; /* For a later test step */
|
||||
}
|
||||
|
||||
//NDMRESET
|
||||
// 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.
|
||||
/* 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.
|
||||
/* Write some registers. They should not be impacted by ndmreset. */
|
||||
dmi_write(target, DMI_COMMAND, 0xFFFFFFFF);
|
||||
|
||||
for (unsigned int i = 0; i < get_field(abstractcs, DMI_ABSTRACTCS_PROGBUFSIZE); i++) {
|
||||
|
@ -3331,7 +3355,7 @@ int riscv013_test_compliance(struct target *target) {
|
|||
dmi_write(target, DMI_ABSTRACTAUTO, 0xFFFFFFFF);
|
||||
dmi_read(target, &abstractauto, DMI_ABSTRACTAUTO);
|
||||
|
||||
// Pulse reset.
|
||||
/* Pulse reset. */
|
||||
|
||||
target->reset_halt = true;
|
||||
dmi_read(target, &dmcontrol, DMI_DMCONTROL);
|
||||
|
@ -3339,15 +3363,16 @@ int riscv013_test_compliance(struct target *target) {
|
|||
assert_reset(target);
|
||||
deassert_reset(target);
|
||||
|
||||
// Verify that most stuff is not affected by ndmreset.
|
||||
/* Verify that most stuff is not affected by ndmreset. */
|
||||
dmi_read(target, &testvar_read, DMI_COMMAND);
|
||||
COMPLIANCE_TEST(testvar_read == 0xFFFFFFFF, "NDMRESET should not affect DMI_COMMAND");
|
||||
dmi_read(target, &testvar_read, DMI_ABSTRACTCS);
|
||||
COMPLIANCE_TEST(get_field(testvar_read, DMI_ABSTRACTCS_CMDERR) == CMDERR_NOT_SUPPORTED, "NDMRESET should not affect DMI_ABSTRACTCS");
|
||||
COMPLIANCE_TEST(get_field(testvar_read, DMI_ABSTRACTCS_CMDERR) == CMDERR_NOT_SUPPORTED,
|
||||
"NDMRESET should not affect DMI_ABSTRACTCS");
|
||||
dmi_read(target, &testvar_read, DMI_ABSTRACTAUTO);
|
||||
COMPLIANCE_TEST(testvar_read == abstractauto, "NDMRESET should not affect DMI_ABSTRACTAUTO");
|
||||
|
||||
// Clean up to avoid future test failures
|
||||
/* Clean up to avoid future test failures */
|
||||
dmi_write(target, DMI_ABSTRACTCS, DMI_ABSTRACTCS_CMDERR);
|
||||
dmi_write(target, DMI_ABSTRACTAUTO, 0);
|
||||
|
||||
|
@ -3363,17 +3388,19 @@ int riscv013_test_compliance(struct target *target) {
|
|||
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.
|
||||
/* 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)");
|
||||
riscv_get_register(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");
|
||||
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.
|
||||
/* DMACTIVE -- deasserting DMACTIVE should reset all the above values. */
|
||||
|
||||
// Toggle dmactive
|
||||
/* Toggle dmactive */
|
||||
dmi_write(target, DMI_DMCONTROL, 0);
|
||||
dmi_write(target, DMI_DMCONTROL, DMI_DMCONTROL_DMACTIVE);
|
||||
dmi_read(target, &testvar_read, DMI_COMMAND);
|
||||
|
@ -3395,21 +3422,22 @@ int riscv013_test_compliance(struct target *target) {
|
|||
COMPLIANCE_TEST(testvar_read == 0, "DATA words should reset to 0");
|
||||
}
|
||||
|
||||
//TODO:
|
||||
// DCSR.cause priorities
|
||||
// DCSR.stoptime/stopcycle
|
||||
// DCSR.stepie
|
||||
// DCSR.ebreak
|
||||
// DCSR.prv
|
||||
/*
|
||||
* TODO:
|
||||
* DCSR.cause priorities
|
||||
* DCSR.stoptime/stopcycle
|
||||
* DCSR.stepie
|
||||
* DCSR.ebreak
|
||||
* DCSR.prv
|
||||
*/
|
||||
|
||||
/* Halt every hart for any follow-up tests*/
|
||||
riscv_halt_all_harts(target);
|
||||
|
||||
LOG_INFO("PASSED %d of %d TESTS\n", passed_tests, total_tests);
|
||||
|
||||
if (total_tests == passed_tests) {
|
||||
if (total_tests == passed_tests)
|
||||
return ERROR_OK;
|
||||
} else {
|
||||
else
|
||||
return ERROR_FAIL;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue