Line 215... |
Line 215... |
neorv32_cpu_csr_write(CSR_MIE, 0);
|
neorv32_cpu_csr_write(CSR_MIE, 0);
|
|
|
// test intro
|
// test intro
|
PRINT_STANDARD("\nStarting tests.\n\n");
|
PRINT_STANDARD("\nStarting tests.\n\n");
|
|
|
// sync (test)
|
|
asm volatile ("fence.i");
|
|
|
|
// enable global interrupts
|
// enable global interrupts
|
neorv32_cpu_eint();
|
neorv32_cpu_eint();
|
|
|
|
|
// **********************************************************************************************
|
// **********************************************************************************************
|
// Run CPU and SoC tests
|
// Run CPU and SoC tests
|
// **********************************************************************************************
|
// **********************************************************************************************
|
|
|
|
|
// ----------------------------------------------------------
|
// ----------------------------------------------------------
|
// Test fence instructions (just make sure CPU does not crash)
|
// Test fence instructions
|
// ----------------------------------------------------------
|
// ----------------------------------------------------------
|
|
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
|
|
PRINT_STANDARD("[%i] FENCE(.I): ", cnt_test);
|
|
|
|
cnt_test++;
|
|
|
|
asm volatile ("fence");
|
|
asm volatile ("fence.i");
|
asm volatile ("fence");
|
asm volatile ("fence");
|
asm volatile ("fence.i");
|
asm volatile ("fence.i");
|
|
|
|
if (neorv32_cpu_csr_read(CSR_MCAUSE) == 0) {
|
|
test_ok();
|
|
}
|
|
else {
|
|
test_fail();
|
|
}
|
|
|
|
|
// ----------------------------------------------------------
|
// ----------------------------------------------------------
|
// Test performance counter: setup as many events and counter as feasible
|
// Test performance counter: setup as many events and counter as feasible
|
// ----------------------------------------------------------
|
// ----------------------------------------------------------
|
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
|
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
|
Line 273... |
Line 284... |
else {
|
else {
|
PRINT_STANDARD("skipped (n.a.)\n");
|
PRINT_STANDARD("skipped (n.a.)\n");
|
}
|
}
|
|
|
|
|
//// ----------------------------------------------------------
|
// ----------------------------------------------------------
|
//// Test standard RISC-V performance counter [m]cycle[h]
|
// Test standard RISC-V performance counter [m]cycle[h]
|
//// ----------------------------------------------------------
|
// ----------------------------------------------------------
|
//neorv32_cpu_csr_write(CSR_MCAUSE, 0);
|
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
|
//PRINT_STANDARD("[%i] cycle counter: ", cnt_test);
|
PRINT_STANDARD("[%i] cycle counter: ", cnt_test);
|
//
|
|
//cnt_test++;
|
|
//
|
|
//// make sure counter is enabled
|
|
//asm volatile ("csrci %[addr], %[imm]" : : [addr] "i" (CSR_MCOUNTINHIBIT), [imm] "i" (1<<CSR_MCOUNTINHIBIT_CY));
|
|
//
|
|
//// prepare overflow
|
|
//neorv32_cpu_set_mcycle(0x00000000FFFFFFFFULL);
|
|
//
|
|
//// get current cycle counter HIGH
|
|
//tmp_a = neorv32_cpu_csr_read(CSR_MCYCLEH);
|
|
//
|
|
//// make sure cycle counter high has incremented and there was no exception during access
|
|
//if ((tmp_a == 1) && (neorv32_cpu_csr_read(CSR_MCAUSE) == 0)) {
|
|
// test_ok();
|
|
//}
|
|
//else {
|
|
// test_fail();
|
|
//}
|
|
|
|
|
cnt_test++;
|
|
|
//// ----------------------------------------------------------
|
// make sure counter is enabled
|
//// Test standard RISC-V performance counter [m]instret[h]
|
asm volatile ("csrci %[addr], %[imm]" : : [addr] "i" (CSR_MCOUNTINHIBIT), [imm] "i" (1<<CSR_MCOUNTINHIBIT_CY));
|
//// ----------------------------------------------------------
|
|
//neorv32_cpu_csr_write(CSR_MCAUSE, 0);
|
// prepare overflow
|
//PRINT_STANDARD("[%i] instret counter: ", cnt_test);
|
neorv32_cpu_set_mcycle(0x00000000FFFFFFFFULL);
|
//
|
|
//cnt_test++;
|
// get current cycle counter HIGH
|
//
|
tmp_a = neorv32_cpu_csr_read(CSR_MCYCLEH);
|
//// make sure counter is enabled
|
|
//asm volatile ("csrci %[addr], %[imm]" : : [addr] "i" (CSR_MCOUNTINHIBIT), [imm] "i" (1<<CSR_MCOUNTINHIBIT_IR));
|
// make sure cycle counter high has incremented and there was no exception during access
|
//
|
if ((tmp_a == 1) && (neorv32_cpu_csr_read(CSR_MCAUSE) == 0)) {
|
//// prepare overflow
|
test_ok();
|
//neorv32_cpu_set_minstret(0x00000000FFFFFFFFULL);
|
}
|
//
|
else {
|
//// get instruction counter HIGH
|
test_fail();
|
//tmp_a = neorv32_cpu_csr_read(CSR_INSTRETH);
|
}
|
//
|
|
//// make sure instruction counter high has incremented and there was no exception during access
|
|
//if ((tmp_a == 1) && (neorv32_cpu_csr_read(CSR_MCAUSE) == 0)) {
|
// ----------------------------------------------------------
|
// test_ok();
|
// Test standard RISC-V performance counter [m]instret[h]
|
//}
|
// ----------------------------------------------------------
|
//else {
|
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
|
// test_fail();
|
PRINT_STANDARD("[%i] instret counter: ", cnt_test);
|
//}
|
|
|
cnt_test++;
|
|
|
|
// make sure counter is enabled
|
|
asm volatile ("csrci %[addr], %[imm]" : : [addr] "i" (CSR_MCOUNTINHIBIT), [imm] "i" (1<<CSR_MCOUNTINHIBIT_IR));
|
|
|
|
// prepare overflow
|
|
neorv32_cpu_set_minstret(0x00000000FFFFFFFFULL);
|
|
|
|
// get instruction counter HIGH
|
|
tmp_a = neorv32_cpu_csr_read(CSR_INSTRETH);
|
|
|
|
// make sure instruction counter high has incremented and there was no exception during access
|
|
if ((tmp_a == 1) && (neorv32_cpu_csr_read(CSR_MCAUSE) == 0)) {
|
|
test_ok();
|
|
}
|
|
else {
|
|
test_fail();
|
|
}
|
|
|
|
|
// ----------------------------------------------------------
|
// ----------------------------------------------------------
|
// Test mcountinhibt: inhibit auto-inc of [m]cycle
|
// Test mcountinhibt: inhibit auto-inc of [m]cycle
|
// ----------------------------------------------------------
|
// ----------------------------------------------------------
|
Line 374... |
Line 385... |
// do not allow user-level code to access cycle[h] CSRs
|
// do not allow user-level code to access cycle[h] CSRs
|
tmp_a = neorv32_cpu_csr_read(CSR_MCOUNTEREN);
|
tmp_a = neorv32_cpu_csr_read(CSR_MCOUNTEREN);
|
tmp_a &= ~(1<<CSR_MCOUNTEREN_CY); // clear access right
|
tmp_a &= ~(1<<CSR_MCOUNTEREN_CY); // clear access right
|
neorv32_cpu_csr_write(CSR_MCOUNTEREN, tmp_a);
|
neorv32_cpu_csr_write(CSR_MCOUNTEREN, tmp_a);
|
|
|
neorv32_cpu_csr_write(CSR_CYCLEH, 1); // make sure CSR is != 0 for this test
|
neorv32_cpu_csr_write(CSR_MCYCLE, 0);
|
|
neorv32_cpu_csr_write(CSR_MCYCLEH, 123); // make sure CSR is != 0 for this test
|
|
|
// switch to user mode (hart will be back in MACHINE mode when trap handler returns)
|
// switch to user mode (hart will be back in MACHINE mode when trap handler returns)
|
goto_user_mode();
|
goto_user_mode();
|
{
|
{
|
// access to cycle CSR is no longer allowed
|
// access to cycle CSR is no longer allowed
|
asm volatile (" li %[result], 0xcc11aa22 \n" // initialize
|
asm volatile (" li %[result], 0xcc11aa22 \n" // initialize
|
" rdcycleh %[result] " // read CSR_CYCLE, is not allowed and should not alter [result]
|
" csrrw %[result], cycleh, %[input] " // read and write CSR_CYCLE, not allowed and should not alter [result] nor CSR
|
: [result] "=r" (tmp_a) : );
|
: [result] "=r" (tmp_a) : [input] "r" (tmp_a) );
|
}
|
}
|
|
|
// make sure there was an illegal instruction trap
|
// make sure there was an illegal instruction trap
|
if ((neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_I_ILLEGAL) &&
|
if ((neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_I_ILLEGAL) &&
|
|
(neorv32_cpu_csr_read(CSR_CYCLEH) == 123) && // csr not altered
|
(tmp_a == 0xcc11aa22)) { // destination register not altered
|
(tmp_a == 0xcc11aa22)) { // destination register not altered
|
test_ok();
|
test_ok();
|
}
|
}
|
else {
|
else {
|
test_fail();
|
test_fail();
|
Line 497... |
Line 510... |
else {
|
else {
|
test_fail();
|
test_fail();
|
}
|
}
|
|
|
|
|
//// ----------------------------------------------------------
|
// ----------------------------------------------------------
|
//// No "real" CSR write access (because rs1 = r0)
|
// No "real" CSR write access (because rs1 = r0)
|
//// ----------------------------------------------------------
|
// ----------------------------------------------------------
|
//neorv32_cpu_csr_write(CSR_MCAUSE, 0);
|
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
|
//PRINT_STANDARD("[%i] Read-only CSR 'no-write' (rs1=0) access: ", cnt_test);
|
PRINT_STANDARD("[%i] Read-only CSR 'no-write' (rs1=0) access: ", cnt_test);
|
//
|
|
//cnt_test++;
|
cnt_test++;
|
//
|
|
//// time CSR is read-only, but no actual write is performed because rs1=r0
|
// time CSR is read-only, but no actual write is performed because rs1=r0
|
//// -> should cause no exception
|
// -> should cause no exception
|
//asm volatile("csrrs zero, time, zero");
|
asm volatile("csrrs zero, time, zero");
|
//
|
|
//if (neorv32_cpu_csr_read(CSR_MCAUSE) == 0) {
|
if (neorv32_cpu_csr_read(CSR_MCAUSE) == 0) {
|
// test_ok();
|
test_ok();
|
//}
|
}
|
//else {
|
else {
|
// test_fail();
|
test_fail();
|
//}
|
}
|
|
|
|
|
// ----------------------------------------------------------
|
// ----------------------------------------------------------
|
// Unaligned instruction address
|
// Unaligned instruction address
|
// ----------------------------------------------------------
|
// ----------------------------------------------------------
|
Line 571... |
Line 584... |
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
|
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
|
PRINT_STANDARD("[%i] I_ILLEG (illegal instr.) EXC: ", cnt_test);
|
PRINT_STANDARD("[%i] I_ILLEG (illegal instr.) EXC: ", cnt_test);
|
|
|
cnt_test++;
|
cnt_test++;
|
|
|
// illegal 32-bit instruction (malformed SRA)
|
// clear mstatus.mie and set mstatus.mpie
|
|
tmp_a = neorv32_cpu_csr_read(CSR_MSTATUS);
|
|
tmp_a &= ~(1 << CSR_MSTATUS_MIE);
|
|
tmp_a |= (1 << CSR_MSTATUS_MPIE);
|
|
neorv32_cpu_csr_write(CSR_MSTATUS, tmp_a);
|
|
|
|
// illegal 32-bit instruction (MRET with incorrect opcode)
|
asm volatile (".align 4 \n"
|
asm volatile (".align 4 \n"
|
".word 0xC0000033");
|
".word 0x3020007f");
|
|
|
// make sure this has cause an illegal exception
|
// make sure this has cause an illegal exception
|
if (neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_I_ILLEGAL) {
|
if ((neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_I_ILLEGAL) && // illegal instruction exception
|
// make sure this is really the instruction that caused the exception
|
(neorv32_cpu_csr_read(CSR_MTVAL) == 0x3020007f) && // correct instruction word
|
// -> for illegal instructions MTVAL contains the faulting instruction word
|
((neorv32_cpu_csr_read(CSR_MSTATUS) & (1 << CSR_MSTATUS_MIE)) == 0)) { // MIE should still be cleared
|
if (neorv32_cpu_csr_read(CSR_MTVAL) == 0xC0000033) {
|
|
test_ok();
|
test_ok();
|
}
|
}
|
else {
|
else {
|
test_fail();
|
test_fail();
|
}
|
}
|
}
|
|
else {
|
// clear mstatus.mie
|
test_fail();
|
neorv32_cpu_dint();
|
}
|
|
|
|
|
|
// ----------------------------------------------------------
|
// ----------------------------------------------------------
|
// Illegal compressed instruction
|
// Illegal compressed instruction
|
// ----------------------------------------------------------
|
// ----------------------------------------------------------
|
Line 1437... |
Line 1454... |
|
|
// ----------------------------------------------------------
|
// ----------------------------------------------------------
|
// Test WFI ("sleep") instruction (executed in user mode), wakeup via MTIME
|
// Test WFI ("sleep") instruction (executed in user mode), wakeup via MTIME
|
// ----------------------------------------------------------
|
// ----------------------------------------------------------
|
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
|
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
|
PRINT_STANDARD("[%i] WFI (sleep instruction, wake-up via MTIME): ", cnt_test);
|
PRINT_STANDARD("[%i] WFI (wake-up via MTIME): ", cnt_test);
|
|
|
cnt_test++;
|
cnt_test++;
|
|
|
// program wake-up timer
|
// program wake-up timer
|
neorv32_mtime_set_timecmp(neorv32_mtime_get_time() + 500);
|
neorv32_mtime_set_timecmp(neorv32_mtime_get_time() + 500);
|
Line 1469... |
Line 1486... |
test_ok();
|
test_ok();
|
}
|
}
|
|
|
|
|
// ----------------------------------------------------------
|
// ----------------------------------------------------------
|
|
// Test unallowed WFI ("sleep") instruction (executed in user mode)
|
|
// ----------------------------------------------------------
|
|
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
|
|
PRINT_STANDARD("[%i] WFI (not allowed in u-mode): ", cnt_test);
|
|
|
|
cnt_test++;
|
|
|
|
// set mstatus.TW to disallow execution of WFI in user-mode
|
|
neorv32_cpu_csr_write(CSR_MSTATUS, neorv32_cpu_csr_read(CSR_MSTATUS) | (1<<CSR_MSTATUS_TW));
|
|
|
|
// put CPU into sleep mode (from user mode)
|
|
goto_user_mode();
|
|
{
|
|
asm volatile ("wfi"); // this has to fail
|
|
}
|
|
|
|
if (neorv32_cpu_csr_read(CSR_MCAUSE) == TRAP_CODE_I_ILLEGAL) {
|
|
test_ok();
|
|
}
|
|
else {
|
|
test_fail();
|
|
}
|
|
|
|
|
|
// ----------------------------------------------------------
|
// Test invalid CSR access in user mode
|
// Test invalid CSR access in user mode
|
// ----------------------------------------------------------
|
// ----------------------------------------------------------
|
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
|
neorv32_cpu_csr_write(CSR_MCAUSE, 0);
|
PRINT_STANDARD("[%i] Invalid CSR access (mstatus) from user mode: ", cnt_test);
|
PRINT_STANDARD("[%i] Invalid CSR access (mstatus) from user mode: ", cnt_test);
|
|
|