From aaceecd5dc64146d8749fdd9220e2643aac23ed8 Mon Sep 17 00:00:00 2001 From: Eyck Jentzsch Date: Mon, 17 May 2021 09:20:09 +0200 Subject: [PATCH] fix mu_p platform features and CSRs --- gen_input/templates/interp/CORENAME.cpp.gtl | 2 - incl/iss/arch/riscv_hart_mu_p.h | 87 +++++++++++++-------- src/main.cpp | 2 +- src/sysc/core_complex.cpp | 2 +- 4 files changed, 55 insertions(+), 38 deletions(-) diff --git a/gen_input/templates/interp/CORENAME.cpp.gtl b/gen_input/templates/interp/CORENAME.cpp.gtl index 4d1e12c..9dea6c7 100644 --- a/gen_input/templates/interp/CORENAME.cpp.gtl +++ b/gen_input/templates/interp/CORENAME.cpp.gtl @@ -147,8 +147,6 @@ protected: inline void leave(unsigned lvl){ this->core.leave_trap(lvl); - auto pc_val = super::template read_mem(traits::CSR, (lvl << 8) + 0x41); - this->template get_reg(traits::NEXT_PC) = pc_val; } inline void wait(unsigned type){ diff --git a/incl/iss/arch/riscv_hart_mu_p.h b/incl/iss/arch/riscv_hart_mu_p.h index bbf9d64..6ca3906 100644 --- a/incl/iss/arch/riscv_hart_mu_p.h +++ b/incl/iss/arch/riscv_hart_mu_p.h @@ -66,7 +66,9 @@ namespace iss { namespace arch { -template class riscv_hart_mu_p : public BASE { +enum features_e{FEAT_NONE, FEAT_PMP, FEAT_EXT_N}; + +template class riscv_hart_mu_p : public BASE { protected: const std::array lvl = {{'U', 'S', 'H', 'M'}}; const std::array trap_str = {{"" @@ -92,7 +94,7 @@ protected: "User external interrupt", "Supervisor external interrupt", "Reserved", "Machine external interrupt"}}; public: using super = BASE; - using this_class = riscv_hart_mu_p; + using this_class = riscv_hart_mu_p; using phys_addr_t = typename super::phys_addr_t; using reg_t = typename super::reg_t; using addr_t = typename super::addr_t; @@ -218,7 +220,7 @@ public: protected: struct riscv_instrumentation_if : public iss::instrumentation_if { - riscv_instrumentation_if(riscv_hart_mu_p &arch) + riscv_instrumentation_if(riscv_hart_mu_p &arch) : arch(arch) {} /** * get the name of this architecture @@ -233,7 +235,7 @@ protected: virtual void set_curr_instr_cycles(unsigned cycles) { arch.cycle_offset += cycles - 1; }; - riscv_hart_mu_p &arch; + riscv_hart_mu_p &arch; }; friend struct riscv_instrumentation_if; @@ -286,8 +288,8 @@ protected: void check_interrupt(); }; -template -riscv_hart_mu_p::riscv_hart_mu_p() +template +riscv_hart_mu_p::riscv_hart_mu_p() : state() , cycle_offset(0) , instr_if(*this) { @@ -326,9 +328,26 @@ riscv_hart_mu_p::riscv_hart_mu_p() // read-only registers csr_rd_cb[misa] = &this_class::read_reg; csr_wr_cb[misa] = nullptr; + + if(FEAT & FEAT_PMP){ + for(size_t i=pmpaddr0; i<=pmpaddr15; ++i){ + csr_rd_cb[i] = &this_class::read_reg; + csr_wr_cb[i] = &this_class::write_reg; + } + for(size_t i=pmpcfg0; i<=pmpcfg3; ++i){ + csr_rd_cb[i] = &this_class::read_reg; + csr_wr_cb[i] = &this_class::write_reg; + } + } + if(FEAT & FEAT_EXT_N){ + csr_rd_cb[mideleg] = &this_class::read_reg; + csr_wr_cb[mideleg] = &this_class::write_reg; + csr_rd_cb[medeleg] = &this_class::read_reg; + csr_wr_cb[medeleg] = &this_class::write_reg; + } } -template std::pair riscv_hart_mu_p::load_file(std::string name, int type) { +template std::pair riscv_hart_mu_p::load_file(std::string name, int type) { FILE *fp = fopen(name.c_str(), "r"); if (fp) { std::array buf; @@ -372,8 +391,8 @@ template std::pair riscv_hart_mu_p -iss::status riscv_hart_mu_p::read(const address_type type, const access_type access, const uint32_t space, +template +iss::status riscv_hart_mu_p::read(const address_type type, const access_type access, const uint32_t space, const uint64_t addr, const unsigned length, uint8_t *const data) { #ifndef NDEBUG if (access && iss::access_type::DEBUG) { @@ -430,8 +449,8 @@ iss::status riscv_hart_mu_p::read(const address_type type, const acce } } -template -iss::status riscv_hart_mu_p::write(const address_type type, const access_type access, const uint32_t space, +template +iss::status riscv_hart_mu_p::write(const address_type type, const access_type access, const uint32_t space, const uint64_t addr, const unsigned length, const uint8_t *const data) { #ifndef NDEBUG const char *prefix = (access && iss::access_type::DEBUG) ? "debug " : ""; @@ -537,7 +556,7 @@ iss::status riscv_hart_mu_p::write(const address_type type, const acc } } -template iss::status riscv_hart_mu_p::read_csr(unsigned addr, reg_t &val) { +template iss::status riscv_hart_mu_p::read_csr(unsigned addr, reg_t &val) { if (addr >= csr.size()) return iss::Err; auto req_priv_lvl = (addr >> 8) & 0x3; if (this->reg.PRIV < req_priv_lvl) // not having required privileges @@ -548,7 +567,7 @@ template iss::status riscv_hart_mu_p::read_ return (this->*(it->second))(addr, val); } -template iss::status riscv_hart_mu_p::write_csr(unsigned addr, reg_t val) { +template iss::status riscv_hart_mu_p::write_csr(unsigned addr, reg_t val) { if (addr >= csr.size()) return iss::Err; auto req_priv_lvl = (addr >> 8) & 0x3; if (this->reg.PRIV < req_priv_lvl) // not having required privileges @@ -561,17 +580,17 @@ template iss::status riscv_hart_mu_p::write return (this->*(it->second))(addr, val); } -template iss::status riscv_hart_mu_p::read_reg(unsigned addr, reg_t &val) { +template iss::status riscv_hart_mu_p::read_reg(unsigned addr, reg_t &val) { val = csr[addr]; return iss::Ok; } -template iss::status riscv_hart_mu_p::write_reg(unsigned addr, reg_t val) { +template iss::status riscv_hart_mu_p::write_reg(unsigned addr, reg_t val) { csr[addr] = val; return iss::Ok; } -template iss::status riscv_hart_mu_p::read_cycle(unsigned addr, reg_t &val) { +template iss::status riscv_hart_mu_p::read_cycle(unsigned addr, reg_t &val) { auto cycle_val = this->reg.icount + cycle_offset; if (addr == mcycle) { val = static_cast(cycle_val); @@ -582,7 +601,7 @@ template iss::status riscv_hart_mu_p::read_ return iss::Ok; } -template iss::status riscv_hart_mu_p::read_time(unsigned addr, reg_t &val) { +template iss::status riscv_hart_mu_p::read_time(unsigned addr, reg_t &val) { uint64_t time_val = (this->reg.icount + cycle_offset) / (100000000 / 32768 - 1); //-> ~3052; if (addr == time) { val = static_cast(time_val); @@ -593,31 +612,31 @@ template iss::status riscv_hart_mu_p::read_ return iss::Ok; } -template iss::status riscv_hart_mu_p::read_status(unsigned addr, reg_t &val) { +template iss::status riscv_hart_mu_p::read_status(unsigned addr, reg_t &val) { auto req_priv_lvl = (addr >> 8) & 0x3; val = state.mstatus & hart_state_type::get_mask(req_priv_lvl); return iss::Ok; } -template iss::status riscv_hart_mu_p::write_status(unsigned addr, reg_t val) { +template iss::status riscv_hart_mu_p::write_status(unsigned addr, reg_t val) { auto req_priv_lvl = (addr >> 8) & 0x3; state.write_mstatus(val, req_priv_lvl); check_interrupt(); return iss::Ok; } -template iss::status riscv_hart_mu_p::read_ie(unsigned addr, reg_t &val) { +template iss::status riscv_hart_mu_p::read_ie(unsigned addr, reg_t &val) { val = csr[mie]; val &= csr[mideleg]; return iss::Ok; } -template iss::status riscv_hart_mu_p::read_hartid(unsigned addr, reg_t &val) { +template iss::status riscv_hart_mu_p::read_hartid(unsigned addr, reg_t &val) { val = mhartid_reg; return iss::Ok; } -template iss::status riscv_hart_mu_p::write_ie(unsigned addr, reg_t val) { +template iss::status riscv_hart_mu_p::write_ie(unsigned addr, reg_t val) { auto req_priv_lvl = (addr >> 8) & 0x3; auto mask = get_irq_mask(req_priv_lvl); csr[mie] = (csr[mie] & ~mask) | (val & mask); @@ -625,13 +644,13 @@ template iss::status riscv_hart_mu_p::write return iss::Ok; } -template iss::status riscv_hart_mu_p::read_ip(unsigned addr, reg_t &val) { +template iss::status riscv_hart_mu_p::read_ip(unsigned addr, reg_t &val) { val = csr[mip]; val &= csr[mideleg]; return iss::Ok; } -template iss::status riscv_hart_mu_p::write_ip(unsigned addr, reg_t val) { +template iss::status riscv_hart_mu_p::write_ip(unsigned addr, reg_t val) { auto req_priv_lvl = (addr >> 8) & 0x3; auto mask = get_irq_mask(req_priv_lvl); mask &= ~(1 << 7); // MTIP is read only @@ -640,8 +659,8 @@ template iss::status riscv_hart_mu_p::write return iss::Ok; } -template -iss::status riscv_hart_mu_p::read_mem(phys_addr_t paddr, unsigned length, uint8_t *const data) { +template +iss::status riscv_hart_mu_p::read_mem(phys_addr_t paddr, unsigned length, uint8_t *const data) { if ((paddr.val + length) > mem.size()) return iss::Err; if(mem_read_cb) return mem_read_cb(paddr, length, data); switch (paddr.val) { @@ -666,8 +685,8 @@ iss::status riscv_hart_mu_p::read_mem(phys_addr_t paddr, unsigned len return iss::Ok; } -template -iss::status riscv_hart_mu_p::write_mem(phys_addr_t paddr, unsigned length, const uint8_t *const data) { +template +iss::status riscv_hart_mu_p::write_mem(phys_addr_t paddr, unsigned length, const uint8_t *const data) { if ((paddr.val + length) > mem.size()) return iss::Err; if(mem_write_cb) return mem_write_cb(paddr, length, data); switch (paddr.val) { @@ -743,12 +762,12 @@ iss::status riscv_hart_mu_p::write_mem(phys_addr_t paddr, unsigned le return iss::Ok; } -template inline void riscv_hart_mu_p::reset(uint64_t address) { +template inline void riscv_hart_mu_p::reset(uint64_t address) { BASE::reset(address); state.mstatus = hart_state_type::mstatus_reset_val; } -template void riscv_hart_mu_p::check_interrupt() { +template void riscv_hart_mu_p::check_interrupt() { auto ideleg = csr[mideleg]; // Multiple simultaneous interrupts and traps at the same privilege level are // handled in the following decreasing priority order: @@ -770,7 +789,7 @@ template void riscv_hart_mu_p::check_interr } } -template uint64_t riscv_hart_mu_p::enter_trap(uint64_t flags, uint64_t addr) { +template uint64_t riscv_hart_mu_p::enter_trap(uint64_t flags, uint64_t addr) { // flags are ACTIVE[31:31], CAUSE[30:16], TRAPID[15:0] // calculate and write mcause val auto trap_id = bit_sub<0, 16>(flags); @@ -840,10 +859,10 @@ template uint64_t riscv_hart_mu_p::enter_tr return this->reg.NEXT_PC; } -template uint64_t riscv_hart_mu_p::leave_trap(uint64_t flags) { +template uint64_t riscv_hart_mu_p::leave_trap(uint64_t flags) { + auto cur_priv = this->reg.PRIV; auto inst_priv = (flags & 0x3)? 3:0; auto status = state.mstatus; - // pop the relevant lower-privilege interrupt enable and privilege mode stack // clear respective yIE switch (inst_priv) { @@ -859,7 +878,7 @@ template uint64_t riscv_hart_mu_p::leave_tr } // sets the pc to the value stored in the x epc register. this->reg.NEXT_PC = csr[uepc | inst_priv << 8]; - CLOG(INFO, disass) << "Executing xRET , changing privilege level from " << lvl[this->reg.PRIV] << " to " + CLOG(INFO, disass) << "Executing xRET , changing privilege level from " << lvl[cur_priv] << " to " << lvl[this->reg.PRIV]; return this->reg.NEXT_PC; } diff --git a/src/main.cpp b/src/main.cpp index 517d9bf..7f5af13 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -47,7 +47,7 @@ using tgc_b_plat_type = iss::arch::riscv_hart_m_p; #ifdef CORE_TGC_D #include "iss/arch/riscv_hart_mu_p.h" #include "iss/arch/tgc_d.h" -using tgc_d_plat_type = iss::arch::riscv_hart_mu_p; +using tgc_d_plat_type = iss::arch::riscv_hart_mu_p; #endif #ifdef WITH_LLVM #include diff --git a/src/sysc/core_complex.cpp b/src/sysc/core_complex.cpp index c2bea42..71edd05 100644 --- a/src/sysc/core_complex.cpp +++ b/src/sysc/core_complex.cpp @@ -44,7 +44,7 @@ using tgc_c_plat_type = iss::arch::riscv_hart_m_p; #ifdef CORE_TGC_D #include "iss/arch/riscv_hart_mu_p.h" #include "iss/arch/tgc_d.h" -using tgc_d_plat_type = iss::arch::riscv_hart_mu_p; +using tgc_d_plat_type = iss::arch::riscv_hart_mu_p; #endif #include "iss/debugger/encoderdecoder.h" #include "iss/debugger/gdb_session.h"