Allow IRQs to be set/cleared by sw in tb. Add soft IRQ test
This commit is contained in:
parent
a232833d81
commit
9fb2af800f
|
@ -4,6 +4,10 @@
|
|||
#include <stdarg.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Testbench IO hardware layout
|
||||
|
||||
#define IO_BASE 0x80000000
|
||||
|
||||
|
@ -11,6 +15,14 @@ typedef struct {
|
|||
volatile uint32_t print_char;
|
||||
volatile uint32_t print_u32;
|
||||
volatile uint32_t exit;
|
||||
uint32_t _pad0;
|
||||
volatile uint32_t set_softirq;
|
||||
volatile uint32_t clr_softirq;
|
||||
uint32_t _pad1[2];
|
||||
volatile uint32_t set_irq;
|
||||
uint32_t _pad2[3];
|
||||
volatile uint32_t clr_irq;
|
||||
uint32_t _pad3[3];
|
||||
} io_hw_t;
|
||||
|
||||
#define mm_io ((io_hw_t *const)IO_BASE)
|
||||
|
@ -24,6 +36,8 @@ typedef struct {
|
|||
|
||||
#define mm_timer ((timer_hw_t *const)(IO_BASE + 0x100))
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Testbench IO convenience functions
|
||||
|
||||
static inline void tb_putc(char c) {
|
||||
mm_io->print_char = (uint32_t)c;
|
||||
|
@ -57,4 +71,28 @@ static inline void tb_printf(const char *fmt, ...) {
|
|||
|
||||
#define tb_assert(cond, ...) if (!(cond)) {tb_printf(__VA_ARGS__); tb_exit(-1);}
|
||||
|
||||
static inline void tb_set_softirq() {
|
||||
mm_io->set_softirq = 1;
|
||||
}
|
||||
|
||||
static inline void tb_clr_softirq() {
|
||||
mm_io->clr_softirq = 1;
|
||||
}
|
||||
|
||||
static inline bool tb_get_softirq() {
|
||||
return (bool)mm_io->set_softirq;
|
||||
}
|
||||
|
||||
static inline void tb_set_irq_masked(uint32_t mask) {
|
||||
mm_io->set_irq = mask;
|
||||
}
|
||||
|
||||
static inline void tb_clr_irq_masked(uint32_t mask) {
|
||||
mm_io->clr_irq = mask;
|
||||
}
|
||||
|
||||
static inline uint32_t tb_get_irq_mask() {
|
||||
return mm_io->set_irq;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -0,0 +1,64 @@
|
|||
#include "tb_cxxrtl_io.h"
|
||||
#include "hazard3_csr.h"
|
||||
|
||||
/*EXPECTED-OUTPUT***************************************************************
|
||||
|
||||
Dry run
|
||||
Set mie only
|
||||
Then set IRQ
|
||||
-> handle_soft_irq
|
||||
mip = 00000088 // mtip is also set, because mtimecmp is 0
|
||||
mie = 00000008 // only msie is set
|
||||
mcause = 80000003 // MSB indicates IRQ. LSBs are index of mip.
|
||||
mstatus = 00001880 // MPP = 3. mpie = 1, mie = 0, since we just took an IRQ.
|
||||
Returned from IRQ
|
||||
Clear mie, do another dry run
|
||||
|
||||
*******************************************************************************/
|
||||
|
||||
#define mip_msip 0x8u
|
||||
#define mie_msie mip_msip
|
||||
|
||||
int main() {
|
||||
tb_assert(!(read_csr(mip) & mip_msip), "mip.msip should be clear at start of test\n");
|
||||
|
||||
tb_puts("Dry run\n");
|
||||
tb_set_softirq();
|
||||
tb_assert(tb_get_softirq(), "Failed to set soft_irq through tb\n");
|
||||
tb_assert(read_csr(mip) & mip_msip, "soft_irq not reflected in mip\n");
|
||||
|
||||
tb_clr_softirq();
|
||||
tb_assert(!tb_get_softirq(), "Failed to clear soft_irq through tb\n");
|
||||
tb_assert(!(read_csr(mip) & mip_msip), "soft_irq clear not reflected in mip\n");
|
||||
|
||||
tb_puts("Set mie only\n");
|
||||
write_csr(mie, mie_msie);
|
||||
asm volatile ("csrsi mstatus, 0x8");
|
||||
// IRQ should not fire yet.
|
||||
|
||||
tb_puts("Then set IRQ\n");
|
||||
tb_set_softirq();
|
||||
tb_assert(!(read_csr(mip) & mip_msip), "soft_irq should have been cleared by IRQ\n");
|
||||
tb_puts("Returned from IRQ\n");
|
||||
|
||||
tb_puts("Clear mie, do another dry run\n");
|
||||
write_csr(mie, 0);
|
||||
tb_set_softirq();
|
||||
tb_assert(tb_get_softirq(), "Failed to set soft_irq through tb\n");
|
||||
tb_assert(read_csr(mip) & mip_msip, "soft_irq not reflected in mip\n");
|
||||
|
||||
tb_clr_softirq();
|
||||
tb_assert(!tb_get_softirq(), "Failed to clear soft_irq through tb\n");
|
||||
tb_assert(!(read_csr(mip) & mip_msip), "soft_irq clear not reflected in mip\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void __attribute__((interrupt)) isr_machine_softirq() {
|
||||
tb_puts("-> handle_soft_irq\n");
|
||||
tb_printf("mip = %08x\n", read_csr(mip));
|
||||
tb_printf("mie = %08x\n", read_csr(mie));
|
||||
tb_clr_softirq();
|
||||
tb_printf("mcause = %08x\n", read_csr(mcause));
|
||||
tb_printf("mstatus = %08x\n", read_csr(mstatus));
|
||||
}
|
|
@ -18,13 +18,17 @@ uint8_t mem[MEM_SIZE];
|
|||
|
||||
static const unsigned int IO_BASE = 0x80000000;
|
||||
enum {
|
||||
IO_PRINT_CHAR = 0x000,
|
||||
IO_PRINT_U32 = 0x004,
|
||||
IO_EXIT = 0x008,
|
||||
IO_MTIME = 0x100,
|
||||
IO_MTIMEH = 0x104,
|
||||
IO_MTIMECMP = 0x108,
|
||||
IO_MTIMECMPH = 0x10c
|
||||
IO_PRINT_CHAR = 0x000,
|
||||
IO_PRINT_U32 = 0x004,
|
||||
IO_EXIT = 0x008,
|
||||
IO_SET_SOFTIRQ = 0x010,
|
||||
IO_CLR_SOFTIRQ = 0x014,
|
||||
IO_SET_IRQ = 0x020,
|
||||
IO_CLR_IRQ = 0x030,
|
||||
IO_MTIME = 0x100,
|
||||
IO_MTIMEH = 0x104,
|
||||
IO_MTIMECMP = 0x108,
|
||||
IO_MTIMECMPH = 0x10c
|
||||
};
|
||||
|
||||
static const int TCP_BUF_SIZE = 256;
|
||||
|
@ -300,6 +304,18 @@ int main(int argc, char **argv) {
|
|||
printf("Ran for %ld cycles\n", cycle + 1);
|
||||
break;
|
||||
}
|
||||
else if (bus_addr == IO_BASE + IO_SET_SOFTIRQ) {
|
||||
top.p_soft__irq.set<bool>(true);
|
||||
}
|
||||
else if (bus_addr == IO_BASE + IO_CLR_SOFTIRQ) {
|
||||
top.p_soft__irq.set<bool>(false);
|
||||
}
|
||||
else if (bus_addr == IO_BASE + IO_SET_IRQ) {
|
||||
top.p_irq.set<uint32_t>(top.p_irq.get<uint32_t>() | wdata);
|
||||
}
|
||||
else if (bus_addr == IO_BASE + IO_CLR_IRQ) {
|
||||
top.p_irq.set<uint32_t>(top.p_irq.get<uint32_t>() & ~wdata);
|
||||
}
|
||||
else if (bus_addr == IO_BASE + IO_MTIME) {
|
||||
mtime = (mtime & 0xffffffff00000000u) | wdata;
|
||||
}
|
||||
|
@ -325,6 +341,12 @@ int main(int argc, char **argv) {
|
|||
mem[bus_addr + 2] << 16 |
|
||||
mem[bus_addr + 3] << 24;
|
||||
}
|
||||
else if (bus_addr == IO_BASE + IO_SET_SOFTIRQ || bus_addr == IO_BASE + IO_CLR_SOFTIRQ) {
|
||||
rdata = top.p_soft__irq.get<bool>();
|
||||
}
|
||||
else if (bus_addr == IO_BASE + IO_SET_IRQ || bus_addr == IO_BASE + IO_CLR_IRQ) {
|
||||
rdata = top.p_irq.get<uint32_t>();
|
||||
}
|
||||
else if (bus_addr == IO_BASE + IO_MTIME) {
|
||||
rdata = mtime;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue