From de50b4ee54d067aee7b22f098cbf9c12c696d0cd Mon Sep 17 00:00:00 2001 From: Zihao Yu Date: Fri, 13 Sep 2019 20:11:52 +0800 Subject: [PATCH] riscv64: refactor CSR --- src/isa/riscv64/csr.h | 53 +++++++++++++++++++++++++++++++ src/isa/riscv64/exec/system.c | 24 +++++--------- src/isa/riscv64/include/isa/reg.h | 27 ---------------- src/isa/riscv64/init.c | 3 +- src/isa/riscv64/intr.c | 13 ++++---- src/isa/riscv64/mmu.c | 7 ++-- src/isa/riscv64/reg.c | 18 +++++++++++ 7 files changed, 92 insertions(+), 53 deletions(-) create mode 100644 src/isa/riscv64/csr.h diff --git a/src/isa/riscv64/csr.h b/src/isa/riscv64/csr.h new file mode 100644 index 00000000..9628a75b --- /dev/null +++ b/src/isa/riscv64/csr.h @@ -0,0 +1,53 @@ +#ifndef __CSR_H__ +#define __CSR_H__ + +#include "common.h" + +#define CSRS(f) \ + f(mstatus , 0x300) f(mtvec , 0x305) f(mepc , 0x341) f(mcause , 0x342) \ + f(satp , 0x180) + +#define CSR_STRUCT_START(name) \ + typedef union { \ + struct { + +#define CSR_STRUCT_END(name) \ + }; \ + word_t val; \ + } concat(name, _t); + +CSR_STRUCT_START(mstatus) + uint64_t uie : 1; + uint64_t sie : 1; + uint64_t pad0: 1; + uint64_t mie : 1; + uint64_t upie: 1; + uint64_t spie: 1; + uint64_t pad1: 1; + uint64_t mpie: 1; + uint64_t spp : 1; + uint64_t pad2: 2; + uint64_t mpp : 2; +CSR_STRUCT_END(mstatus) + +CSR_STRUCT_START(satp) + uint64_t ppn :44; + uint64_t asid:16; + uint64_t mode: 4; +CSR_STRUCT_END(satp) + +CSR_STRUCT_START(mtvec) +CSR_STRUCT_END(mtvec) + +CSR_STRUCT_START(mcause) +CSR_STRUCT_END(mcause) + +CSR_STRUCT_START(mepc) +CSR_STRUCT_END(mepc) + +#define CSRS_DECL(name, val) extern concat(name, _t)* const name; +MAP(CSRS, CSRS_DECL) + +word_t* csr_decode(uint32_t addr); + +#endif diff --git a/src/isa/riscv64/exec/system.c b/src/isa/riscv64/exec/system.c index 07f751d5..87e6b0df 100644 --- a/src/isa/riscv64/exec/system.c +++ b/src/isa/riscv64/exec/system.c @@ -1,21 +1,13 @@ #include "cpu/exec.h" +#include "../csr.h" -static inline rtlreg_t* csr_decode(uint32_t csr) { +static inline word_t* csr_decode_wrapper(uint32_t addr) { difftest_skip_dut(1, 3); - - switch (csr) { - case 0x180: return &cpu.satp.val; - case 0x300: return &cpu.mstatus.val; - case 0x305: return &cpu.mtvec; - case 0x341: return &cpu.mepc; - case 0x342: return &cpu.mcause; - default: panic("unimplemented CSR 0x%x", csr); - } - return NULL; + return csr_decode(addr); } make_EHelper(csrrw) { - rtlreg_t *csr = csr_decode(id_src2->val); + rtlreg_t *csr = csr_decode_wrapper(id_src2->val); rtl_sr(id_dest->reg, csr, 8); rtl_mv(csr, &id_src->val); @@ -24,7 +16,7 @@ make_EHelper(csrrw) { } make_EHelper(csrrs) { - rtlreg_t *csr = csr_decode(id_src2->val); + rtlreg_t *csr = csr_decode_wrapper(id_src2->val); rtl_sr(id_dest->reg, csr, 8); rtl_or(csr, csr, &id_src->val); @@ -42,9 +34,9 @@ make_EHelper(priv) { print_asm("ecall"); break; case 0x302: - cpu.mstatus.mie = cpu.mstatus.mpie; - cpu.mstatus.mpie = 1; - rtl_li(&s0, cpu.mepc); + mstatus->mie = mstatus->mpie; + mstatus->mpie = 1; + rtl_li(&s0, mepc->val); rtl_jr(&s0); print_asm("mret"); break; diff --git a/src/isa/riscv64/include/isa/reg.h b/src/isa/riscv64/include/isa/reg.h index 576d9c99..04ec34e0 100644 --- a/src/isa/riscv64/include/isa/reg.h +++ b/src/isa/riscv64/include/isa/reg.h @@ -15,33 +15,6 @@ typedef struct { } gpr[32]; vaddr_t pc; - vaddr_t mtvec; - vaddr_t mcause; - vaddr_t mepc; - union { - struct { - uint64_t uie : 1; - uint64_t sie : 1; - uint64_t pad0: 1; - uint64_t mie : 1; - uint64_t upie: 1; - uint64_t spie: 1; - uint64_t pad1: 1; - uint64_t mpie: 1; - uint64_t spp : 1; - uint64_t pad2: 2; - uint64_t mpp : 2; - }; - uint64_t val; - } mstatus; - union { - struct { - uint64_t ppn :44; - uint64_t asid:16; - uint64_t mode: 4; - }; - uint64_t val; - } satp; bool INTR; } CPU_state; diff --git a/src/isa/riscv64/init.c b/src/isa/riscv64/init.c index 03bc72a0..d8ca5a30 100644 --- a/src/isa/riscv64/init.c +++ b/src/isa/riscv64/init.c @@ -1,4 +1,5 @@ #include "nemu.h" +#include "csr.h" // this is not consistent with uint8_t // but it is ok since we do not access the array directly @@ -13,7 +14,7 @@ const long isa_default_img_size = sizeof(isa_default_img); void init_isa(void) { cpu.gpr[0]._64 = 0; cpu.pc = PC_START; - cpu.mstatus.val = 0x000c0100; + mstatus->val = 0x000c0100; register_pmem(0x80000000u); } diff --git a/src/isa/riscv64/intr.c b/src/isa/riscv64/intr.c index 1ced856c..4ee1af74 100644 --- a/src/isa/riscv64/intr.c +++ b/src/isa/riscv64/intr.c @@ -1,20 +1,21 @@ #include "rtl/rtl.h" +#include "csr.h" void raise_intr(uint32_t NO, vaddr_t epc) { /* TODO: Trigger an interrupt/exception with ``NO''. * That is, use ``NO'' to index the IDT. */ - cpu.mcause = NO; - cpu.mepc = epc; - cpu.mstatus.mpie = cpu.mstatus.mie; - cpu.mstatus.mie = 0; - rtl_li(&s0, cpu.mtvec); + mcause->val = NO; + mepc->val = epc; + mstatus->mpie = mstatus->mie; + mstatus->mie = 0; + rtl_li(&s0, mtvec->val); rtl_jr(&s0); } bool isa_query_intr(void) { - if (cpu.INTR && cpu.mstatus.mie) { + if (cpu.INTR && mstatus->mie) { cpu.INTR = false; raise_intr(0x80000005, cpu.pc); return true; diff --git a/src/isa/riscv64/mmu.c b/src/isa/riscv64/mmu.c index 5eec5dc1..30ca5011 100644 --- a/src/isa/riscv64/mmu.c +++ b/src/isa/riscv64/mmu.c @@ -1,5 +1,6 @@ #include "nemu.h" #include "memory/memory.h" +#include "csr.h" /* the 32bit Page Table Entry(second level page table) data structure */ typedef union PageTableEntry { @@ -29,7 +30,7 @@ typedef union { static paddr_t page_walk(vaddr_t vaddr, bool is_write) { PageAddr *addr = (void *)&vaddr; - paddr_t pdir_base = cpu.satp.ppn << 12; + paddr_t pdir_base = satp->ppn << 12; PTE pde; pde.val = paddr_read(pdir_base + addr->pdir_idx * 4, 4); @@ -59,11 +60,11 @@ static inline paddr_t page_translate(vaddr_t addr, bool is_write) { } word_t isa_vaddr_read(vaddr_t addr, int len) { - paddr_t paddr = (cpu.satp.mode ? page_translate(addr, false) : addr); + paddr_t paddr = (satp->mode ? page_translate(addr, false) : addr); return paddr_read(paddr, len); } void isa_vaddr_write(vaddr_t addr, word_t data, int len) { - paddr_t paddr = (cpu.satp.mode ? page_translate(addr, true) : addr); + paddr_t paddr = (satp->mode ? page_translate(addr, true) : addr); paddr_write(paddr, data, len); } diff --git a/src/isa/riscv64/reg.c b/src/isa/riscv64/reg.c index b98abbe0..8826527b 100644 --- a/src/isa/riscv64/reg.c +++ b/src/isa/riscv64/reg.c @@ -1,4 +1,5 @@ #include "nemu.h" +#include "csr.h" const char *regsl[] = { "$0", "ra", "sp", "gp", "tp", "t0", "t1", "t2", @@ -34,3 +35,20 @@ rtlreg_t isa_reg_str2val(const char *s, bool *success) { *success = false; return 0; } + +static word_t csr_array[4096] = {}; + +#define CSRS_DEF(name, val) \ + concat(name, _t)* const name = (void *)&csr_array[val]; +MAP(CSRS, CSRS_DEF) + +#define CSRS_EXIST(name, val) [val] = 1, +static bool csr_exist[4096] = { + MAP(CSRS, CSRS_EXIST) +}; + +word_t* csr_decode(uint32_t addr) { + assert(addr < 4096); + Assert(csr_exist[addr], "unimplemented CSR 0x%x at pc = " FMT_WORD, addr, cpu.pc); + return &csr_array[addr]; +} -- GitLab