fix mu_p platform features and CSRs

This commit is contained in:
Eyck Jentzsch 2021-05-17 09:20:09 +02:00
parent 4b3f5a6b0c
commit aaceecd5dc
4 changed files with 55 additions and 38 deletions

View File

@ -147,8 +147,6 @@ protected:
inline void leave(unsigned lvl){
this->core.leave_trap(lvl);
auto pc_val = super::template read_mem<reg_t>(traits::CSR, (lvl << 8) + 0x41);
this->template get_reg<reg_t>(traits::NEXT_PC) = pc_val;
}
inline void wait(unsigned type){

View File

@ -66,7 +66,9 @@
namespace iss {
namespace arch {
template <typename BASE, bool PMP=false> class riscv_hart_mu_p : public BASE {
enum features_e{FEAT_NONE, FEAT_PMP, FEAT_EXT_N};
template <typename BASE, features_e FEAT=FEAT_NONE> class riscv_hart_mu_p : public BASE {
protected:
const std::array<const char, 4> lvl = {{'U', 'S', 'H', 'M'}};
const std::array<const char *, 16> 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<BASE, PMP>;
using this_class = riscv_hart_mu_p<BASE, FEAT>;
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<BASE, PMP> &arch)
riscv_instrumentation_if(riscv_hart_mu_p<BASE, FEAT> &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<BASE, PMP> &arch;
riscv_hart_mu_p<BASE, FEAT> &arch;
};
friend struct riscv_instrumentation_if;
@ -286,8 +288,8 @@ protected:
void check_interrupt();
};
template <typename BASE, bool PMP>
riscv_hart_mu_p<BASE, PMP>::riscv_hart_mu_p()
template <typename BASE, features_e FEAT>
riscv_hart_mu_p<BASE, FEAT>::riscv_hart_mu_p()
: state()
, cycle_offset(0)
, instr_if(*this) {
@ -326,9 +328,26 @@ riscv_hart_mu_p<BASE, PMP>::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 <typename BASE, bool PMP> std::pair<uint64_t, bool> riscv_hart_mu_p<BASE, PMP>::load_file(std::string name, int type) {
template <typename BASE, features_e FEAT> std::pair<uint64_t, bool> riscv_hart_mu_p<BASE, FEAT>::load_file(std::string name, int type) {
FILE *fp = fopen(name.c_str(), "r");
if (fp) {
std::array<char, 5> buf;
@ -372,8 +391,8 @@ template <typename BASE, bool PMP> std::pair<uint64_t, bool> riscv_hart_mu_p<BAS
throw std::runtime_error("memory load file not found");
}
template <typename BASE, bool PMP>
iss::status riscv_hart_mu_p<BASE, PMP>::read(const address_type type, const access_type access, const uint32_t space,
template <typename BASE, features_e FEAT>
iss::status riscv_hart_mu_p<BASE, FEAT>::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<BASE, PMP>::read(const address_type type, const acce
}
}
template <typename BASE, bool PMP>
iss::status riscv_hart_mu_p<BASE, PMP>::write(const address_type type, const access_type access, const uint32_t space,
template <typename BASE, features_e FEAT>
iss::status riscv_hart_mu_p<BASE, FEAT>::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<BASE, PMP>::write(const address_type type, const acc
}
}
template <typename BASE, bool PMP> iss::status riscv_hart_mu_p<BASE, PMP>::read_csr(unsigned addr, reg_t &val) {
template <typename BASE, features_e FEAT> iss::status riscv_hart_mu_p<BASE, FEAT>::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 <typename BASE, bool PMP> iss::status riscv_hart_mu_p<BASE, PMP>::read_
return (this->*(it->second))(addr, val);
}
template <typename BASE, bool PMP> iss::status riscv_hart_mu_p<BASE, PMP>::write_csr(unsigned addr, reg_t val) {
template <typename BASE, features_e FEAT> iss::status riscv_hart_mu_p<BASE, FEAT>::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 <typename BASE, bool PMP> iss::status riscv_hart_mu_p<BASE, PMP>::write
return (this->*(it->second))(addr, val);
}
template <typename BASE, bool PMP> iss::status riscv_hart_mu_p<BASE, PMP>::read_reg(unsigned addr, reg_t &val) {
template <typename BASE, features_e FEAT> iss::status riscv_hart_mu_p<BASE, FEAT>::read_reg(unsigned addr, reg_t &val) {
val = csr[addr];
return iss::Ok;
}
template <typename BASE, bool PMP> iss::status riscv_hart_mu_p<BASE, PMP>::write_reg(unsigned addr, reg_t val) {
template <typename BASE, features_e FEAT> iss::status riscv_hart_mu_p<BASE, FEAT>::write_reg(unsigned addr, reg_t val) {
csr[addr] = val;
return iss::Ok;
}
template <typename BASE, bool PMP> iss::status riscv_hart_mu_p<BASE, PMP>::read_cycle(unsigned addr, reg_t &val) {
template <typename BASE, features_e FEAT> iss::status riscv_hart_mu_p<BASE, FEAT>::read_cycle(unsigned addr, reg_t &val) {
auto cycle_val = this->reg.icount + cycle_offset;
if (addr == mcycle) {
val = static_cast<reg_t>(cycle_val);
@ -582,7 +601,7 @@ template <typename BASE, bool PMP> iss::status riscv_hart_mu_p<BASE, PMP>::read_
return iss::Ok;
}
template <typename BASE, bool PMP> iss::status riscv_hart_mu_p<BASE, PMP>::read_time(unsigned addr, reg_t &val) {
template <typename BASE, features_e FEAT> iss::status riscv_hart_mu_p<BASE, FEAT>::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<reg_t>(time_val);
@ -593,31 +612,31 @@ template <typename BASE, bool PMP> iss::status riscv_hart_mu_p<BASE, PMP>::read_
return iss::Ok;
}
template <typename BASE, bool PMP> iss::status riscv_hart_mu_p<BASE, PMP>::read_status(unsigned addr, reg_t &val) {
template <typename BASE, features_e FEAT> iss::status riscv_hart_mu_p<BASE, FEAT>::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 <typename BASE, bool PMP> iss::status riscv_hart_mu_p<BASE, PMP>::write_status(unsigned addr, reg_t val) {
template <typename BASE, features_e FEAT> iss::status riscv_hart_mu_p<BASE, FEAT>::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 <typename BASE, bool PMP> iss::status riscv_hart_mu_p<BASE, PMP>::read_ie(unsigned addr, reg_t &val) {
template <typename BASE, features_e FEAT> iss::status riscv_hart_mu_p<BASE, FEAT>::read_ie(unsigned addr, reg_t &val) {
val = csr[mie];
val &= csr[mideleg];
return iss::Ok;
}
template <typename BASE, bool PMP> iss::status riscv_hart_mu_p<BASE, PMP>::read_hartid(unsigned addr, reg_t &val) {
template <typename BASE, features_e FEAT> iss::status riscv_hart_mu_p<BASE, FEAT>::read_hartid(unsigned addr, reg_t &val) {
val = mhartid_reg;
return iss::Ok;
}
template <typename BASE, bool PMP> iss::status riscv_hart_mu_p<BASE, PMP>::write_ie(unsigned addr, reg_t val) {
template <typename BASE, features_e FEAT> iss::status riscv_hart_mu_p<BASE, FEAT>::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 <typename BASE, bool PMP> iss::status riscv_hart_mu_p<BASE, PMP>::write
return iss::Ok;
}
template <typename BASE, bool PMP> iss::status riscv_hart_mu_p<BASE, PMP>::read_ip(unsigned addr, reg_t &val) {
template <typename BASE, features_e FEAT> iss::status riscv_hart_mu_p<BASE, FEAT>::read_ip(unsigned addr, reg_t &val) {
val = csr[mip];
val &= csr[mideleg];
return iss::Ok;
}
template <typename BASE, bool PMP> iss::status riscv_hart_mu_p<BASE, PMP>::write_ip(unsigned addr, reg_t val) {
template <typename BASE, features_e FEAT> iss::status riscv_hart_mu_p<BASE, FEAT>::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 <typename BASE, bool PMP> iss::status riscv_hart_mu_p<BASE, PMP>::write
return iss::Ok;
}
template <typename BASE, bool PMP>
iss::status riscv_hart_mu_p<BASE, PMP>::read_mem(phys_addr_t paddr, unsigned length, uint8_t *const data) {
template <typename BASE, features_e FEAT>
iss::status riscv_hart_mu_p<BASE, FEAT>::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<BASE, PMP>::read_mem(phys_addr_t paddr, unsigned len
return iss::Ok;
}
template <typename BASE, bool PMP>
iss::status riscv_hart_mu_p<BASE, PMP>::write_mem(phys_addr_t paddr, unsigned length, const uint8_t *const data) {
template <typename BASE, features_e FEAT>
iss::status riscv_hart_mu_p<BASE, FEAT>::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<BASE, PMP>::write_mem(phys_addr_t paddr, unsigned le
return iss::Ok;
}
template <typename BASE, bool PMP> inline void riscv_hart_mu_p<BASE, PMP>::reset(uint64_t address) {
template <typename BASE, features_e FEAT> inline void riscv_hart_mu_p<BASE, FEAT>::reset(uint64_t address) {
BASE::reset(address);
state.mstatus = hart_state_type::mstatus_reset_val;
}
template <typename BASE, bool PMP> void riscv_hart_mu_p<BASE, PMP>::check_interrupt() {
template <typename BASE, features_e FEAT> void riscv_hart_mu_p<BASE, FEAT>::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 <typename BASE, bool PMP> void riscv_hart_mu_p<BASE, PMP>::check_interr
}
}
template <typename BASE, bool PMP> uint64_t riscv_hart_mu_p<BASE, PMP>::enter_trap(uint64_t flags, uint64_t addr) {
template <typename BASE, features_e FEAT> uint64_t riscv_hart_mu_p<BASE, FEAT>::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 <typename BASE, bool PMP> uint64_t riscv_hart_mu_p<BASE, PMP>::enter_tr
return this->reg.NEXT_PC;
}
template <typename BASE, bool PMP> uint64_t riscv_hart_mu_p<BASE, PMP>::leave_trap(uint64_t flags) {
template <typename BASE, features_e FEAT> uint64_t riscv_hart_mu_p<BASE, FEAT>::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 <typename BASE, bool PMP> uint64_t riscv_hart_mu_p<BASE, PMP>::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;
}

View File

@ -47,7 +47,7 @@ using tgc_b_plat_type = iss::arch::riscv_hart_m_p<iss::arch::tgc_b>;
#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<iss::arch::tgc_d>;
using tgc_d_plat_type = iss::arch::riscv_hart_mu_p<iss::arch::tgc_d, iss::arch::FEAT_PMP>;
#endif
#ifdef WITH_LLVM
#include <iss/llvm/jit_helper.h>

View File

@ -44,7 +44,7 @@ using tgc_c_plat_type = iss::arch::riscv_hart_m_p<iss::arch::tgc_c>;
#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<iss::arch::tgc_d>;
using tgc_d_plat_type = iss::arch::riscv_hart_mu_p<iss::arch::tgc_d, iss::arch::FEAT_PMP>;
#endif
#include "iss/debugger/encoderdecoder.h"
#include "iss/debugger/gdb_session.h"