168 lines
4.6 KiB
C
168 lines
4.6 KiB
C
#include "tb_cxxrtl_io.h"
|
|
#include "hazard3_csr.h"
|
|
#include "amo_outline.h"
|
|
|
|
// Check AMOs which are not word-aligned generate exceptions with correct mepc
|
|
// and mcause
|
|
|
|
int main() {
|
|
volatile uint32_t target_word = -1u;
|
|
uint32_t tmp = 0;
|
|
|
|
tb_puts("amoswap.w\n");
|
|
tmp = amoswap(123, (uint32_t*)((uintptr_t)&target_word + 1));
|
|
tb_assert(tmp == 123, "bad");
|
|
tmp = amoswap(123, (uint32_t*)((uintptr_t)&target_word + 2));
|
|
tb_assert(tmp == 123, "bad");
|
|
tmp = amoswap(123, (uint32_t*)((uintptr_t)&target_word + 3));
|
|
tb_assert(tmp == 123, "bad");
|
|
|
|
tb_puts("amoadd.w\n");
|
|
tmp = amoadd(123, (uint32_t*)((uintptr_t)&target_word + 1));
|
|
tb_assert(tmp == 123, "bad");
|
|
tmp = amoadd(123, (uint32_t*)((uintptr_t)&target_word + 2));
|
|
tb_assert(tmp == 123, "bad");
|
|
tmp = amoadd(123, (uint32_t*)((uintptr_t)&target_word + 3));
|
|
tb_assert(tmp == 123, "bad");
|
|
|
|
tb_puts("amoxor.w\n");
|
|
tmp = amoxor(123, (uint32_t*)((uintptr_t)&target_word + 1));
|
|
tb_assert(tmp == 123, "bad");
|
|
tmp = amoxor(123, (uint32_t*)((uintptr_t)&target_word + 2));
|
|
tb_assert(tmp == 123, "bad");
|
|
tmp = amoxor(123, (uint32_t*)((uintptr_t)&target_word + 3));
|
|
tb_assert(tmp == 123, "bad");
|
|
|
|
tb_puts("amoand.w\n");
|
|
tmp = amoand(123, (uint32_t*)((uintptr_t)&target_word + 1));
|
|
tb_assert(tmp == 123, "bad");
|
|
tmp = amoand(123, (uint32_t*)((uintptr_t)&target_word + 2));
|
|
tb_assert(tmp == 123, "bad");
|
|
tmp = amoand(123, (uint32_t*)((uintptr_t)&target_word + 3));
|
|
tb_assert(tmp == 123, "bad");
|
|
|
|
tb_puts("amoor.w\n");
|
|
tmp = amoor(123, (uint32_t*)((uintptr_t)&target_word + 1));
|
|
tb_assert(tmp == 123, "bad");
|
|
tmp = amoor(123, (uint32_t*)((uintptr_t)&target_word + 2));
|
|
tb_assert(tmp == 123, "bad");
|
|
tmp = amoor(123, (uint32_t*)((uintptr_t)&target_word + 3));
|
|
tb_assert(tmp == 123, "bad");
|
|
|
|
tb_puts("amomin.w\n");
|
|
tmp = amomin(123, (uint32_t*)((uintptr_t)&target_word + 1));
|
|
tb_assert(tmp == 123, "bad");
|
|
tmp = amomin(123, (uint32_t*)((uintptr_t)&target_word + 2));
|
|
tb_assert(tmp == 123, "bad");
|
|
tmp = amomin(123, (uint32_t*)((uintptr_t)&target_word + 3));
|
|
tb_assert(tmp == 123, "bad");
|
|
|
|
tb_puts("amomax.w\n");
|
|
tmp = amomax(123, (uint32_t*)((uintptr_t)&target_word + 1));
|
|
tb_assert(tmp == 123, "bad");
|
|
tmp = amomax(123, (uint32_t*)((uintptr_t)&target_word + 2));
|
|
tb_assert(tmp == 123, "bad");
|
|
tmp = amomax(123, (uint32_t*)((uintptr_t)&target_word + 3));
|
|
tb_assert(tmp == 123, "bad");
|
|
|
|
tb_puts("amominu.w\n");
|
|
tmp = amominu(123, (uint32_t*)((uintptr_t)&target_word + 1));
|
|
tb_assert(tmp == 123, "bad");
|
|
tmp = amominu(123, (uint32_t*)((uintptr_t)&target_word + 2));
|
|
tb_assert(tmp == 123, "bad");
|
|
tmp = amominu(123, (uint32_t*)((uintptr_t)&target_word + 3));
|
|
tb_assert(tmp == 123, "bad");
|
|
|
|
tb_puts("amomaxu.w\n");
|
|
tmp = amomaxu(123, (uint32_t*)((uintptr_t)&target_word + 1));
|
|
tb_assert(tmp == 123, "bad");
|
|
tmp = amomaxu(123, (uint32_t*)((uintptr_t)&target_word + 2));
|
|
tb_assert(tmp == 123, "bad");
|
|
tmp = amomaxu(123, (uint32_t*)((uintptr_t)&target_word + 3));
|
|
tb_assert(tmp == 123, "bad");
|
|
|
|
return 0;
|
|
}
|
|
|
|
void __attribute__((interrupt)) handle_exception() {
|
|
tb_printf("-> exception, mcause = %u\n", read_csr(mcause));
|
|
write_csr(mcause, 0);
|
|
uint32_t mepc = read_csr(mepc);
|
|
tb_printf("instr: %04x%04x\n", *(uint16_t*)(mepc + 2), *(uint16_t*)mepc);
|
|
|
|
if ((*(uint16_t*)mepc & 0x3) == 0x3) {
|
|
write_csr(mepc, mepc + 4);
|
|
}
|
|
else {
|
|
write_csr(mepc, mepc + 2);
|
|
}
|
|
}
|
|
|
|
/*EXPECTED-OUTPUT***************************************************************
|
|
|
|
amoswap.w
|
|
-> exception, mcause = 6
|
|
instr: 08a5a52f
|
|
-> exception, mcause = 6
|
|
instr: 08a5a52f
|
|
-> exception, mcause = 6
|
|
instr: 08a5a52f
|
|
amoadd.w
|
|
-> exception, mcause = 6
|
|
instr: 00a5a52f
|
|
-> exception, mcause = 6
|
|
instr: 00a5a52f
|
|
-> exception, mcause = 6
|
|
instr: 00a5a52f
|
|
amoxor.w
|
|
-> exception, mcause = 6
|
|
instr: 20a5a52f
|
|
-> exception, mcause = 6
|
|
instr: 20a5a52f
|
|
-> exception, mcause = 6
|
|
instr: 20a5a52f
|
|
amoand.w
|
|
-> exception, mcause = 6
|
|
instr: 60a5a52f
|
|
-> exception, mcause = 6
|
|
instr: 60a5a52f
|
|
-> exception, mcause = 6
|
|
instr: 60a5a52f
|
|
amoor.w
|
|
-> exception, mcause = 6
|
|
instr: 40a5a52f
|
|
-> exception, mcause = 6
|
|
instr: 40a5a52f
|
|
-> exception, mcause = 6
|
|
instr: 40a5a52f
|
|
amomin.w
|
|
-> exception, mcause = 6
|
|
instr: 80a5a52f
|
|
-> exception, mcause = 6
|
|
instr: 80a5a52f
|
|
-> exception, mcause = 6
|
|
instr: 80a5a52f
|
|
amomax.w
|
|
-> exception, mcause = 6
|
|
instr: a0a5a52f
|
|
-> exception, mcause = 6
|
|
instr: a0a5a52f
|
|
-> exception, mcause = 6
|
|
instr: a0a5a52f
|
|
amominu.w
|
|
-> exception, mcause = 6
|
|
instr: c0a5a52f
|
|
-> exception, mcause = 6
|
|
instr: c0a5a52f
|
|
-> exception, mcause = 6
|
|
instr: c0a5a52f
|
|
amomaxu.w
|
|
-> exception, mcause = 6
|
|
instr: e0a5a52f
|
|
-> exception, mcause = 6
|
|
instr: e0a5a52f
|
|
-> exception, mcause = 6
|
|
instr: e0a5a52f
|
|
|
|
*******************************************************************************/
|