countertest: support tests for all *counteren
This commit is contained in:
parent
8e2aa1de33
commit
6f4db8e1f7
|
@ -0,0 +1,38 @@
|
|||
#ifndef __COUNTERTEST_H__
|
||||
#define __COUNTERTEST_H__
|
||||
|
||||
#define MSG_ERROR "\33[1;31mERROR\033[0m"
|
||||
|
||||
#define MAP(c, f) c(f)
|
||||
|
||||
#define MACHINE_COUNTER_BASE 0xB00
|
||||
#define UNPRIV_COUNTER_BASE 0xC00
|
||||
#define COUNTER_NUM 32
|
||||
|
||||
#define CSRS_UNPRIV_CNTR(f) \
|
||||
f(cycle , 0xC00) \
|
||||
f(time , 0xC01) \
|
||||
f(instret , 0xC02)
|
||||
|
||||
#define CSRS_UNPRIV_HPM(f) \
|
||||
f(hpmcounter3 , 0xC03) \
|
||||
f(hpmcounter4 , 0xC04) f(hpmcounter5 , 0xC05) f(hpmcounter6 , 0xC06) f(hpmcounter7 , 0xC07) \
|
||||
f(hpmcounter8 , 0xC08) f(hpmcounter9 , 0xC09) f(hpmcounter10 , 0xC0A) f(hpmcounter11 , 0xC0B) \
|
||||
f(hpmcounter12 , 0xC0C) f(hpmcounter13 , 0xC0D) f(hpmcounter14 , 0xC0E) f(hpmcounter15 , 0xC0F) \
|
||||
f(hpmcounter16 , 0xC10) f(hpmcounter17 , 0xC11) f(hpmcounter18 , 0xC12) f(hpmcounter19 , 0xC13) \
|
||||
f(hpmcounter20 , 0xC14) f(hpmcounter21 , 0xC15) f(hpmcounter22 , 0xC16) f(hpmcounter23 , 0xC17) \
|
||||
f(hpmcounter24 , 0xC18) f(hpmcounter25 , 0xC19) f(hpmcounter26 , 0xC1A) f(hpmcounter27 , 0xC1B) \
|
||||
f(hpmcounter28 , 0xC1C) f(hpmcounter29 , 0xC1D) f(hpmcounter30 , 0xC1E) f(hpmcounter31 , 0xC1F)
|
||||
|
||||
#define CSR_ALL_UNPRIV_COUNTER(f) \
|
||||
CSRS_UNPRIV_CNTR(f) \
|
||||
CSRS_UNPRIV_HPM(f)
|
||||
|
||||
#define ACCESSIBLE 0
|
||||
#define EX_II 2
|
||||
#define EX_VI 22
|
||||
|
||||
extern int error;
|
||||
|
||||
|
||||
#endif // __COUNTERTEST_H__
|
|
@ -0,0 +1,102 @@
|
|||
#ifndef __ENABLE_H__
|
||||
#define __ENABLE_H__
|
||||
|
||||
typedef void (*func_void_t)();
|
||||
extern func_void_t check_enable_func_arr[32];
|
||||
|
||||
#define check_enable_detail(csr, addr, m, h, s, mode, res) \
|
||||
do { \
|
||||
goto_priv_mode(MODE_M); \
|
||||
this_mcounteren = m << (addr - UNPRIV_COUNTER_BASE); \
|
||||
this_hcounteren = h << (addr - UNPRIV_COUNTER_BASE); \
|
||||
this_scounteren = s << (addr - UNPRIV_COUNTER_BASE); \
|
||||
csr_write(mcounteren, this_mcounteren); \
|
||||
csr_write(hcounteren, this_hcounteren); \
|
||||
csr_write(scounteren, this_scounteren); \
|
||||
goto_priv_mode(mode); \
|
||||
setup_expected_exception(); \
|
||||
csr_read_res = csr_read(csr); \
|
||||
csr_read_res &= csr_read_res; \
|
||||
if (res) { /* should trap */ \
|
||||
if (!last_exception.actual_trap) { \
|
||||
printf(MSG_ERROR ": checking " #csr ", "); \
|
||||
printf("m/h/scounteren: %d/%d/%d, mode: " #mode "\n", m, h, s); \
|
||||
printf("reading " #csr " shoule trap into " #res ", but not.\n"); \
|
||||
error += 1; \
|
||||
} else if (last_exception.cause != res) { \
|
||||
printf(MSG_ERROR ": checking " #csr ", "); \
|
||||
printf("m/h/scounteren: %d/%d/%d, mode: " #mode "\n", m, h, s); \
|
||||
printf("reading " #csr " shoule trap into " #res ", but trapped into %d.\n", last_exception.cause); \
|
||||
error += 1; \
|
||||
} \
|
||||
} else { /* should be accessible */\
|
||||
if (last_exception.actual_trap) { \
|
||||
printf(MSG_ERROR ": checking " #csr ", "); \
|
||||
printf("m/h/scounteren: %d/%d/%d, mode: " #mode "\n", m, h, s); \
|
||||
printf(#csr " shoule be accessible, but not.\n"); \
|
||||
error += 1; \
|
||||
} \
|
||||
} \
|
||||
clear_last_exception(); \
|
||||
} while (0)
|
||||
|
||||
#define def_func_check_enable(csr, addr) \
|
||||
void check_enable_##csr() { \
|
||||
int this_mcounteren; \
|
||||
int this_hcounteren; \
|
||||
int this_scounteren; \
|
||||
uint64_t csr_read_res; \
|
||||
/* m/h/scounteren: 0/0/0 */ \
|
||||
check_enable_detail(csr, addr, 0, 0, 0, MODE_M, ACCESSIBLE); \
|
||||
check_enable_detail(csr, addr, 0, 0, 0, MODE_S, EX_II); \
|
||||
check_enable_detail(csr, addr, 0, 0, 0, MODE_U, EX_II); \
|
||||
check_enable_detail(csr, addr, 0, 0, 0, MODE_VS, EX_II); \
|
||||
check_enable_detail(csr, addr, 0, 0, 0, MODE_VU, EX_II); \
|
||||
/* m/h/scounteren: 0/0/1 */ \
|
||||
check_enable_detail(csr, addr, 0, 0, 1, MODE_M, ACCESSIBLE); \
|
||||
check_enable_detail(csr, addr, 0, 0, 1, MODE_S, EX_II); \
|
||||
check_enable_detail(csr, addr, 0, 0, 1, MODE_U, EX_II); \
|
||||
check_enable_detail(csr, addr, 0, 0, 1, MODE_VS, EX_II); \
|
||||
check_enable_detail(csr, addr, 0, 0, 1, MODE_VU, EX_II); \
|
||||
/* m/h/scounteren: 0/1/0 */ \
|
||||
check_enable_detail(csr, addr, 0, 1, 0, MODE_M, ACCESSIBLE); \
|
||||
check_enable_detail(csr, addr, 0, 1, 0, MODE_S, EX_II); \
|
||||
check_enable_detail(csr, addr, 0, 1, 0, MODE_U, EX_II); \
|
||||
check_enable_detail(csr, addr, 0, 1, 0, MODE_VS, EX_II); \
|
||||
check_enable_detail(csr, addr, 0, 1, 0, MODE_VU, EX_II); \
|
||||
/* m/h/scounteren: 0/1/1 */ \
|
||||
check_enable_detail(csr, addr, 0, 1, 1, MODE_M, ACCESSIBLE); \
|
||||
check_enable_detail(csr, addr, 0, 1, 1, MODE_S, EX_II); \
|
||||
check_enable_detail(csr, addr, 0, 1, 1, MODE_U, EX_II); \
|
||||
check_enable_detail(csr, addr, 0, 1, 1, MODE_VS, EX_II); \
|
||||
check_enable_detail(csr, addr, 0, 1, 1, MODE_VU, EX_II); \
|
||||
/* m/h/scounteren: 1/0/0 */ \
|
||||
check_enable_detail(csr, addr, 1, 0, 0, MODE_M, ACCESSIBLE); \
|
||||
check_enable_detail(csr, addr, 1, 0, 0, MODE_S, ACCESSIBLE); \
|
||||
check_enable_detail(csr, addr, 1, 0, 0, MODE_U, EX_II); \
|
||||
check_enable_detail(csr, addr, 1, 0, 0, MODE_VS, EX_VI); \
|
||||
check_enable_detail(csr, addr, 1, 0, 0, MODE_VU, EX_VI); \
|
||||
/* m/h/scounteren: 1/0/1 */ \
|
||||
check_enable_detail(csr, addr, 1, 0, 1, MODE_M, ACCESSIBLE); \
|
||||
check_enable_detail(csr, addr, 1, 0, 1, MODE_S, ACCESSIBLE); \
|
||||
check_enable_detail(csr, addr, 1, 0, 1, MODE_U, ACCESSIBLE); \
|
||||
check_enable_detail(csr, addr, 1, 0, 1, MODE_VS, EX_VI); \
|
||||
check_enable_detail(csr, addr, 1, 0, 1, MODE_VU, EX_VI); \
|
||||
/* m/h/scounteren: 1/1/0 */ \
|
||||
check_enable_detail(csr, addr, 1, 1, 0, MODE_M, ACCESSIBLE); \
|
||||
check_enable_detail(csr, addr, 1, 1, 0, MODE_S, ACCESSIBLE); \
|
||||
check_enable_detail(csr, addr, 1, 1, 0, MODE_U, EX_II); \
|
||||
check_enable_detail(csr, addr, 1, 1, 0, MODE_VS, ACCESSIBLE); \
|
||||
check_enable_detail(csr, addr, 1, 1, 0, MODE_VU, EX_VI); \
|
||||
/* m/h/scounteren: 1/1/1 */ \
|
||||
check_enable_detail(csr, addr, 1, 1, 1, MODE_M, ACCESSIBLE); \
|
||||
check_enable_detail(csr, addr, 1, 1, 1, MODE_S, ACCESSIBLE); \
|
||||
check_enable_detail(csr, addr, 1, 1, 1, MODE_U, ACCESSIBLE); \
|
||||
check_enable_detail(csr, addr, 1, 1, 1, MODE_VS, ACCESSIBLE); \
|
||||
check_enable_detail(csr, addr, 1, 1, 1, MODE_VU, ACCESSIBLE); \
|
||||
}
|
||||
|
||||
#define list_func_check_enable(csr, addr) \
|
||||
check_enable_##csr,
|
||||
|
||||
#endif // __ENABLE_H__
|
|
@ -18,7 +18,8 @@ enum {
|
|||
|
||||
typedef struct
|
||||
{
|
||||
uint64_t expected;
|
||||
uint64_t expected_trap;
|
||||
uint64_t actual_trap;
|
||||
uint64_t cause;
|
||||
uint64_t epc;
|
||||
} exception_t;
|
||||
|
@ -75,4 +76,7 @@ void do_ecall(
|
|||
uint64_t arg4, uint64_t arg5, uint64_t arg6, uint64_t ecall_num
|
||||
);
|
||||
|
||||
#endif // __PRIV_H__
|
||||
void setup_expected_exception();
|
||||
void clear_last_exception();
|
||||
|
||||
#endif // __PRIV_H__
|
||||
|
|
|
@ -6,34 +6,24 @@
|
|||
#include <klib-macros.h>
|
||||
|
||||
#include "priv.h"
|
||||
#include "countertest.h"
|
||||
#include "enable.h"
|
||||
|
||||
extern void m_trap_entry();
|
||||
|
||||
int error = 0;
|
||||
|
||||
int main() {
|
||||
// setup
|
||||
// setup trap vector
|
||||
csr_write(mtvec, m_trap_entry);
|
||||
|
||||
goto_priv_mode(MODE_M);
|
||||
csr_write(mcounteren, 0);
|
||||
csr_write(scounteren, 0);
|
||||
csr_write(hcounteren, 0);
|
||||
check_enable_func_arr[1] = 0;
|
||||
|
||||
goto_priv_mode(MODE_VU);
|
||||
|
||||
last_exception.expected = 1;
|
||||
last_exception.cause = 0;
|
||||
last_exception.epc = 0;
|
||||
|
||||
int this_cycle = csr_read(cycle);
|
||||
printf("cycle: %d\n", this_cycle);
|
||||
|
||||
if (last_exception.cause == 2) {
|
||||
printf("good exception!\n");
|
||||
_halt(0);
|
||||
} else {
|
||||
printf("bad no exception!\n");
|
||||
_halt(1);
|
||||
for (int i = 0; i < COUNTER_NUM; i++) {
|
||||
if (check_enable_func_arr[i]) {
|
||||
check_enable_func_arr[i]();
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
|
||||
#include <am.h>
|
||||
#include <csr.h>
|
||||
#include <xsextra.h>
|
||||
#include <klib.h>
|
||||
#include <klib-macros.h>
|
||||
|
||||
#include "priv.h"
|
||||
#include "countertest.h"
|
||||
#include "enable.h"
|
||||
|
||||
// define all check_enable_* function
|
||||
MAP(CSR_ALL_UNPRIV_COUNTER, def_func_check_enable)
|
||||
|
||||
// link all check_enable_* function to array of function pointers
|
||||
func_void_t check_enable_func_arr[32] = {
|
||||
MAP(CSR_ALL_UNPRIV_COUNTER, list_func_check_enable)
|
||||
};
|
|
@ -32,8 +32,8 @@ volatile int m_exception_handler(
|
|||
}
|
||||
|
||||
// other exceptions should be expected by main program
|
||||
assert(last_exception.expected);
|
||||
last_exception.expected = 0;
|
||||
assert(last_exception.expected_trap);
|
||||
last_exception.actual_trap = 1;
|
||||
|
||||
// epc to next
|
||||
uint64_t this_mepc = csr_read(mepc);
|
||||
|
@ -98,3 +98,16 @@ void do_ecall(
|
|||
"+r" (a4), "+r" (a5), "+r" (a6), "+r" (a7));
|
||||
}
|
||||
|
||||
void setup_expected_exception() {
|
||||
last_exception.expected_trap = 1;
|
||||
last_exception.actual_trap = 0;
|
||||
last_exception.cause = 0;
|
||||
last_exception.epc = 0;
|
||||
}
|
||||
|
||||
void clear_last_exception() {
|
||||
last_exception.expected_trap = 0;
|
||||
last_exception.actual_trap = 0;
|
||||
last_exception.cause = 0;
|
||||
last_exception.epc = 0;
|
||||
}
|
||||
|
|
|
@ -81,7 +81,8 @@
|
|||
.endm
|
||||
|
||||
# entry to trap into M-mode
|
||||
.balign 0x4
|
||||
.text
|
||||
.align 4
|
||||
.global m_trap_entry
|
||||
m_trap_entry:
|
||||
SAVE_CONTEXT
|
||||
|
|
Loading…
Reference in New Issue