fix mu_p platform features and CSRs
This commit is contained in:
parent
4b3f5a6b0c
commit
aaceecd5dc
@ -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){
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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>
|
||||
|
@ -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"
|
||||
|
Loading…
Reference in New Issue
Block a user