adds logging categories for ISS
This commit is contained in:
parent
c6b99cd155
commit
5a2b96ef3e
|
@ -61,7 +61,7 @@
|
||||||
namespace iss {
|
namespace iss {
|
||||||
namespace arch {
|
namespace arch {
|
||||||
|
|
||||||
template <typename BASE, features_e FEAT = FEAT_NONE> class riscv_hart_m_p : public BASE, public riscv_hart_common {
|
template <typename BASE, features_e FEAT = FEAT_NONE, typename LOGCAT=logging::disass> class riscv_hart_m_p : public BASE, public riscv_hart_common {
|
||||||
protected:
|
protected:
|
||||||
const std::array<const char, 4> lvl = {{'U', 'S', 'H', 'M'}};
|
const std::array<const char, 4> lvl = {{'U', 'S', 'H', 'M'}};
|
||||||
const std::array<const char*, 16> trap_str = {{""
|
const std::array<const char*, 16> trap_str = {{""
|
||||||
|
@ -88,7 +88,7 @@ protected:
|
||||||
|
|
||||||
public:
|
public:
|
||||||
using core = BASE;
|
using core = BASE;
|
||||||
using this_class = riscv_hart_m_p<BASE, FEAT>;
|
using this_class = riscv_hart_m_p<BASE, FEAT, LOGCAT>;
|
||||||
using phys_addr_t = typename core::phys_addr_t;
|
using phys_addr_t = typename core::phys_addr_t;
|
||||||
using reg_t = typename core::reg_t;
|
using reg_t = typename core::reg_t;
|
||||||
using addr_t = typename core::addr_t;
|
using addr_t = typename core::addr_t;
|
||||||
|
@ -275,7 +275,7 @@ public:
|
||||||
void set_mhartid(reg_t mhartid) { mhartid_reg = mhartid; };
|
void set_mhartid(reg_t mhartid) { mhartid_reg = mhartid; };
|
||||||
|
|
||||||
void disass_output(uint64_t pc, const std::string instr) override {
|
void disass_output(uint64_t pc, const std::string instr) override {
|
||||||
CLOG(INFO, disass) << fmt::format("0x{:016x} {:40} [s:0x{:x};c:{}]", pc, instr, (reg_t)state.mstatus,
|
NSCLOG(INFO, LOGCAT) << fmt::format("0x{:016x} {:40} [s:0x{:x};c:{}]", pc, instr, (reg_t)state.mstatus,
|
||||||
this->reg.icount + cycle_offset);
|
this->reg.icount + cycle_offset);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -290,7 +290,7 @@ public:
|
||||||
protected:
|
protected:
|
||||||
struct riscv_instrumentation_if : public iss::instrumentation_if {
|
struct riscv_instrumentation_if : public iss::instrumentation_if {
|
||||||
|
|
||||||
riscv_instrumentation_if(riscv_hart_m_p<BASE, FEAT>& arch)
|
riscv_instrumentation_if(riscv_hart_m_p<BASE, FEAT, LOGCAT>& arch)
|
||||||
: arch(arch) {}
|
: arch(arch) {}
|
||||||
/**
|
/**
|
||||||
* get the name of this architecture
|
* get the name of this architecture
|
||||||
|
@ -321,7 +321,7 @@ protected:
|
||||||
|
|
||||||
std::unordered_map<std::string, uint64_t> get_symbol_table(std::string name) override { return arch.get_sym_table(name); }
|
std::unordered_map<std::string, uint64_t> get_symbol_table(std::string name) override { return arch.get_sym_table(name); }
|
||||||
|
|
||||||
riscv_hart_m_p<BASE, FEAT>& arch;
|
riscv_hart_m_p<BASE, FEAT, LOGCAT>& arch;
|
||||||
};
|
};
|
||||||
|
|
||||||
friend struct riscv_instrumentation_if;
|
friend struct riscv_instrumentation_if;
|
||||||
|
@ -432,8 +432,8 @@ protected:
|
||||||
std::function<mem_write_f> hart_mem_wr_delegate;
|
std::function<mem_write_f> hart_mem_wr_delegate;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename BASE, features_e FEAT>
|
template <typename BASE, features_e FEAT, typename LOGCAT>
|
||||||
riscv_hart_m_p<BASE, FEAT>::riscv_hart_m_p(feature_config cfg)
|
riscv_hart_m_p<BASE, FEAT, LOGCAT>::riscv_hart_m_p(feature_config cfg)
|
||||||
: state()
|
: state()
|
||||||
, instr_if(*this)
|
, instr_if(*this)
|
||||||
, cfg(cfg) {
|
, cfg(cfg) {
|
||||||
|
@ -564,7 +564,7 @@ riscv_hart_m_p<BASE, FEAT>::riscv_hart_m_p(feature_config cfg)
|
||||||
hart_mem_wr_delegate = [this](phys_addr_t a, unsigned l, uint8_t const* const d) -> iss::status { return this->write_mem(a, l, d); };
|
hart_mem_wr_delegate = [this](phys_addr_t a, unsigned l, uint8_t const* const d) -> iss::status { return this->write_mem(a, l, d); };
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename BASE, features_e FEAT> std::pair<uint64_t, bool> riscv_hart_m_p<BASE, FEAT>::load_file(std::string name, int type) {
|
template <typename BASE, features_e FEAT, typename LOGCAT> std::pair<uint64_t, bool> riscv_hart_m_p<BASE, FEAT, LOGCAT>::load_file(std::string name, int type) {
|
||||||
get_sym_table(name);
|
get_sym_table(name);
|
||||||
try {
|
try {
|
||||||
tohost = symbol_table.at("tohost");
|
tohost = symbol_table.at("tohost");
|
||||||
|
@ -618,8 +618,8 @@ template <typename BASE, features_e FEAT> std::pair<uint64_t, bool> riscv_hart_m
|
||||||
throw std::runtime_error(fmt::format("memory load file not found, check if {} is a valid file", name));
|
throw std::runtime_error(fmt::format("memory load file not found, check if {} is a valid file", name));
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename BASE, features_e FEAT>
|
template <typename BASE, features_e FEAT, typename LOGCAT>
|
||||||
inline void riscv_hart_m_p<BASE, FEAT>::insert_mem_range(uint64_t base, uint64_t size, std::function<mem_read_f> rd_f,
|
inline void riscv_hart_m_p<BASE, FEAT, LOGCAT>::insert_mem_range(uint64_t base, uint64_t size, std::function<mem_read_f> rd_f,
|
||||||
std::function<mem_write_f> wr_fn) {
|
std::function<mem_write_f> wr_fn) {
|
||||||
std::tuple<uint64_t, uint64_t> entry{base, size};
|
std::tuple<uint64_t, uint64_t> entry{base, size};
|
||||||
auto it = std::upper_bound(
|
auto it = std::upper_bound(
|
||||||
|
@ -631,8 +631,8 @@ inline void riscv_hart_m_p<BASE, FEAT>::insert_mem_range(uint64_t base, uint64_t
|
||||||
memfn_write.insert(std::begin(memfn_write) + idx, wr_fn);
|
memfn_write.insert(std::begin(memfn_write) + idx, wr_fn);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename BASE, features_e FEAT>
|
template <typename BASE, features_e FEAT, typename LOGCAT>
|
||||||
iss::status riscv_hart_m_p<BASE, FEAT>::read(const address_type type, const access_type access, const uint32_t space, const uint64_t addr,
|
iss::status riscv_hart_m_p<BASE, FEAT, LOGCAT>::read(const address_type type, const access_type access, const uint32_t space, const uint64_t addr,
|
||||||
const unsigned length, uint8_t* const data) {
|
const unsigned length, uint8_t* const data) {
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
if(access && iss::access_type::DEBUG) {
|
if(access && iss::access_type::DEBUG) {
|
||||||
|
@ -715,8 +715,8 @@ iss::status riscv_hart_m_p<BASE, FEAT>::read(const address_type type, const acce
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename BASE, features_e FEAT>
|
template <typename BASE, features_e FEAT, typename LOGCAT>
|
||||||
iss::status riscv_hart_m_p<BASE, FEAT>::write(const address_type type, const access_type access, const uint32_t space, const uint64_t addr,
|
iss::status riscv_hart_m_p<BASE, FEAT, LOGCAT>::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) {
|
const unsigned length, const uint8_t* const data) {
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
const char* prefix = (access && iss::access_type::DEBUG) ? "debug " : "";
|
const char* prefix = (access && iss::access_type::DEBUG) ? "debug " : "";
|
||||||
|
@ -848,7 +848,7 @@ iss::status riscv_hart_m_p<BASE, FEAT>::write(const address_type type, const acc
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename BASE, features_e FEAT> iss::status riscv_hart_m_p<BASE, FEAT>::read_csr(unsigned addr, reg_t& val) {
|
template <typename BASE, features_e FEAT, typename LOGCAT> iss::status riscv_hart_m_p<BASE, FEAT, LOGCAT>::read_csr(unsigned addr, reg_t& val) {
|
||||||
if(addr >= csr.size())
|
if(addr >= csr.size())
|
||||||
return iss::Err;
|
return iss::Err;
|
||||||
auto req_priv_lvl = (addr >> 8) & 0x3;
|
auto req_priv_lvl = (addr >> 8) & 0x3;
|
||||||
|
@ -860,7 +860,7 @@ template <typename BASE, features_e FEAT> iss::status riscv_hart_m_p<BASE, FEAT>
|
||||||
return (this->*(it->second))(addr, val);
|
return (this->*(it->second))(addr, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename BASE, features_e FEAT> iss::status riscv_hart_m_p<BASE, FEAT>::write_csr(unsigned addr, reg_t val) {
|
template <typename BASE, features_e FEAT, typename LOGCAT> iss::status riscv_hart_m_p<BASE, FEAT, LOGCAT>::write_csr(unsigned addr, reg_t val) {
|
||||||
if(addr >= csr.size())
|
if(addr >= csr.size())
|
||||||
return iss::Err;
|
return iss::Err;
|
||||||
auto req_priv_lvl = (addr >> 8) & 0x3;
|
auto req_priv_lvl = (addr >> 8) & 0x3;
|
||||||
|
@ -874,22 +874,22 @@ template <typename BASE, features_e FEAT> iss::status riscv_hart_m_p<BASE, FEAT>
|
||||||
return (this->*(it->second))(addr, val);
|
return (this->*(it->second))(addr, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename BASE, features_e FEAT> iss::status riscv_hart_m_p<BASE, FEAT>::read_csr_reg(unsigned addr, reg_t& val) {
|
template <typename BASE, features_e FEAT, typename LOGCAT> iss::status riscv_hart_m_p<BASE, FEAT, LOGCAT>::read_csr_reg(unsigned addr, reg_t& val) {
|
||||||
val = csr[addr];
|
val = csr[addr];
|
||||||
return iss::Ok;
|
return iss::Ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename BASE, features_e FEAT> iss::status riscv_hart_m_p<BASE, FEAT>::read_null(unsigned addr, reg_t& val) {
|
template <typename BASE, features_e FEAT, typename LOGCAT> iss::status riscv_hart_m_p<BASE, FEAT, LOGCAT>::read_null(unsigned addr, reg_t& val) {
|
||||||
val = 0;
|
val = 0;
|
||||||
return iss::Ok;
|
return iss::Ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename BASE, features_e FEAT> iss::status riscv_hart_m_p<BASE, FEAT>::write_csr_reg(unsigned addr, reg_t val) {
|
template <typename BASE, features_e FEAT, typename LOGCAT> iss::status riscv_hart_m_p<BASE, FEAT, LOGCAT>::write_csr_reg(unsigned addr, reg_t val) {
|
||||||
csr[addr] = val;
|
csr[addr] = val;
|
||||||
return iss::Ok;
|
return iss::Ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename BASE, features_e FEAT> iss::status riscv_hart_m_p<BASE, FEAT>::read_cycle(unsigned addr, reg_t& val) {
|
template <typename BASE, features_e FEAT, typename LOGCAT> iss::status riscv_hart_m_p<BASE, FEAT, LOGCAT>::read_cycle(unsigned addr, reg_t& val) {
|
||||||
auto cycle_val = this->reg.icount + cycle_offset;
|
auto cycle_val = this->reg.icount + cycle_offset;
|
||||||
if(addr == mcycle) {
|
if(addr == mcycle) {
|
||||||
val = static_cast<reg_t>(cycle_val);
|
val = static_cast<reg_t>(cycle_val);
|
||||||
|
@ -899,7 +899,7 @@ template <typename BASE, features_e FEAT> iss::status riscv_hart_m_p<BASE, FEAT>
|
||||||
return iss::Ok;
|
return iss::Ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename BASE, features_e FEAT> iss::status riscv_hart_m_p<BASE, FEAT>::write_cycle(unsigned addr, reg_t val) {
|
template <typename BASE, features_e FEAT, typename LOGCAT> iss::status riscv_hart_m_p<BASE, FEAT, LOGCAT>::write_cycle(unsigned addr, reg_t val) {
|
||||||
if(sizeof(typename traits<BASE>::reg_t) != 4) {
|
if(sizeof(typename traits<BASE>::reg_t) != 4) {
|
||||||
mcycle_csr = static_cast<uint64_t>(val);
|
mcycle_csr = static_cast<uint64_t>(val);
|
||||||
} else {
|
} else {
|
||||||
|
@ -913,7 +913,7 @@ template <typename BASE, features_e FEAT> iss::status riscv_hart_m_p<BASE, FEAT>
|
||||||
return iss::Ok;
|
return iss::Ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename BASE, features_e FEAT> iss::status riscv_hart_m_p<BASE, FEAT>::read_instret(unsigned addr, reg_t& val) {
|
template <typename BASE, features_e FEAT, typename LOGCAT> iss::status riscv_hart_m_p<BASE, FEAT, LOGCAT>::read_instret(unsigned addr, reg_t& val) {
|
||||||
if((addr & 0xff) == (minstret & 0xff)) {
|
if((addr & 0xff) == (minstret & 0xff)) {
|
||||||
val = static_cast<reg_t>(this->reg.instret);
|
val = static_cast<reg_t>(this->reg.instret);
|
||||||
} else if((addr & 0xff) == (minstreth & 0xff)) {
|
} else if((addr & 0xff) == (minstreth & 0xff)) {
|
||||||
|
@ -922,7 +922,7 @@ template <typename BASE, features_e FEAT> iss::status riscv_hart_m_p<BASE, FEAT>
|
||||||
return iss::Ok;
|
return iss::Ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename BASE, features_e FEAT> iss::status riscv_hart_m_p<BASE, FEAT>::write_instret(unsigned addr, reg_t val) {
|
template <typename BASE, features_e FEAT, typename LOGCAT> iss::status riscv_hart_m_p<BASE, FEAT, LOGCAT>::write_instret(unsigned addr, reg_t val) {
|
||||||
if(sizeof(typename traits<BASE>::reg_t) != 4) {
|
if(sizeof(typename traits<BASE>::reg_t) != 4) {
|
||||||
this->reg.instret = static_cast<uint64_t>(val);
|
this->reg.instret = static_cast<uint64_t>(val);
|
||||||
} else {
|
} else {
|
||||||
|
@ -936,7 +936,7 @@ template <typename BASE, features_e FEAT> iss::status riscv_hart_m_p<BASE, FEAT>
|
||||||
return iss::Ok;
|
return iss::Ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename BASE, features_e FEAT> iss::status riscv_hart_m_p<BASE, FEAT>::read_time(unsigned addr, reg_t& val) {
|
template <typename BASE, features_e FEAT, typename LOGCAT> iss::status riscv_hart_m_p<BASE, FEAT, LOGCAT>::read_time(unsigned addr, reg_t& val) {
|
||||||
uint64_t time_val = this->reg.icount / (100000000 / 32768 - 1); //-> ~3052;
|
uint64_t time_val = this->reg.icount / (100000000 / 32768 - 1); //-> ~3052;
|
||||||
if(addr == time) {
|
if(addr == time) {
|
||||||
val = static_cast<reg_t>(time_val);
|
val = static_cast<reg_t>(time_val);
|
||||||
|
@ -948,23 +948,23 @@ template <typename BASE, features_e FEAT> iss::status riscv_hart_m_p<BASE, FEAT>
|
||||||
return iss::Ok;
|
return iss::Ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename BASE, features_e FEAT> iss::status riscv_hart_m_p<BASE, FEAT>::read_tvec(unsigned addr, reg_t& val) {
|
template <typename BASE, features_e FEAT, typename LOGCAT> iss::status riscv_hart_m_p<BASE, FEAT, LOGCAT>::read_tvec(unsigned addr, reg_t& val) {
|
||||||
val = FEAT & features_e::FEAT_CLIC ? csr[addr] : csr[addr] & ~2;
|
val = FEAT & features_e::FEAT_CLIC ? csr[addr] : csr[addr] & ~2;
|
||||||
return iss::Ok;
|
return iss::Ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename BASE, features_e FEAT> iss::status riscv_hart_m_p<BASE, FEAT>::read_status(unsigned addr, reg_t& val) {
|
template <typename BASE, features_e FEAT, typename LOGCAT> iss::status riscv_hart_m_p<BASE, FEAT, LOGCAT>::read_status(unsigned addr, reg_t& val) {
|
||||||
val = state.mstatus & hart_state_type::get_mask();
|
val = state.mstatus & hart_state_type::get_mask();
|
||||||
return iss::Ok;
|
return iss::Ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename BASE, features_e FEAT> iss::status riscv_hart_m_p<BASE, FEAT>::write_status(unsigned addr, reg_t val) {
|
template <typename BASE, features_e FEAT, typename LOGCAT> iss::status riscv_hart_m_p<BASE, FEAT, LOGCAT>::write_status(unsigned addr, reg_t val) {
|
||||||
state.write_mstatus(val);
|
state.write_mstatus(val);
|
||||||
check_interrupt();
|
check_interrupt();
|
||||||
return iss::Ok;
|
return iss::Ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename BASE, features_e FEAT> iss::status riscv_hart_m_p<BASE, FEAT>::read_cause(unsigned addr, reg_t& val) {
|
template <typename BASE, features_e FEAT, typename LOGCAT> iss::status riscv_hart_m_p<BASE, FEAT, LOGCAT>::read_cause(unsigned addr, reg_t& val) {
|
||||||
if((FEAT & features_e::FEAT_CLIC) && (csr[mtvec] & 0x3) == 3) {
|
if((FEAT & features_e::FEAT_CLIC) && (csr[mtvec] & 0x3) == 3) {
|
||||||
val = csr[addr] & ((1UL << (traits<BASE>::XLEN - 1)) | (mcause_max_irq - 1) | (0xfUL << 16));
|
val = csr[addr] & ((1UL << (traits<BASE>::XLEN - 1)) | (mcause_max_irq - 1) | (0xfUL << 16));
|
||||||
val |= clic_mprev_lvl << 16;
|
val |= clic_mprev_lvl << 16;
|
||||||
|
@ -975,7 +975,7 @@ template <typename BASE, features_e FEAT> iss::status riscv_hart_m_p<BASE, FEAT>
|
||||||
return iss::Ok;
|
return iss::Ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename BASE, features_e FEAT> iss::status riscv_hart_m_p<BASE, FEAT>::write_cause(unsigned addr, reg_t val) {
|
template <typename BASE, features_e FEAT, typename LOGCAT> iss::status riscv_hart_m_p<BASE, FEAT, LOGCAT>::write_cause(unsigned addr, reg_t val) {
|
||||||
if((FEAT & features_e::FEAT_CLIC) && (csr[mtvec] & 0x3) == 3) {
|
if((FEAT & features_e::FEAT_CLIC) && (csr[mtvec] & 0x3) == 3) {
|
||||||
auto mask = ((1UL << (traits<BASE>::XLEN - 1)) | (mcause_max_irq - 1) | (0xfUL << 16));
|
auto mask = ((1UL << (traits<BASE>::XLEN - 1)) | (mcause_max_irq - 1) | (0xfUL << 16));
|
||||||
csr[addr] = (val & mask) | (csr[addr] & ~mask);
|
csr[addr] = (val & mask) | (csr[addr] & ~mask);
|
||||||
|
@ -989,36 +989,36 @@ template <typename BASE, features_e FEAT> iss::status riscv_hart_m_p<BASE, FEAT>
|
||||||
return iss::Ok;
|
return iss::Ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename BASE, features_e FEAT> iss::status riscv_hart_m_p<BASE, FEAT>::read_hartid(unsigned addr, reg_t& val) {
|
template <typename BASE, features_e FEAT, typename LOGCAT> iss::status riscv_hart_m_p<BASE, FEAT, LOGCAT>::read_hartid(unsigned addr, reg_t& val) {
|
||||||
val = mhartid_reg;
|
val = mhartid_reg;
|
||||||
return iss::Ok;
|
return iss::Ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename BASE, features_e FEAT> iss::status riscv_hart_m_p<BASE, FEAT>::read_ie(unsigned addr, reg_t& val) {
|
template <typename BASE, features_e FEAT, typename LOGCAT> iss::status riscv_hart_m_p<BASE, FEAT, LOGCAT>::read_ie(unsigned addr, reg_t& val) {
|
||||||
auto mask = get_irq_mask();
|
auto mask = get_irq_mask();
|
||||||
val = csr[mie] & mask;
|
val = csr[mie] & mask;
|
||||||
return iss::Ok;
|
return iss::Ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename BASE, features_e FEAT> iss::status riscv_hart_m_p<BASE, FEAT>::write_ie(unsigned addr, reg_t val) {
|
template <typename BASE, features_e FEAT, typename LOGCAT> iss::status riscv_hart_m_p<BASE, FEAT, LOGCAT>::write_ie(unsigned addr, reg_t val) {
|
||||||
auto mask = get_irq_mask();
|
auto mask = get_irq_mask();
|
||||||
csr[mie] = (csr[mie] & ~mask) | (val & mask);
|
csr[mie] = (csr[mie] & ~mask) | (val & mask);
|
||||||
check_interrupt();
|
check_interrupt();
|
||||||
return iss::Ok;
|
return iss::Ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename BASE, features_e FEAT> iss::status riscv_hart_m_p<BASE, FEAT>::read_ip(unsigned addr, reg_t& val) {
|
template <typename BASE, features_e FEAT, typename LOGCAT> iss::status riscv_hart_m_p<BASE, FEAT, LOGCAT>::read_ip(unsigned addr, reg_t& val) {
|
||||||
auto mask = get_irq_mask();
|
auto mask = get_irq_mask();
|
||||||
val = csr[mip] & mask;
|
val = csr[mip] & mask;
|
||||||
return iss::Ok;
|
return iss::Ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename BASE, features_e FEAT> iss::status riscv_hart_m_p<BASE, FEAT>::write_epc(unsigned addr, reg_t val) {
|
template <typename BASE, features_e FEAT, typename LOGCAT> iss::status riscv_hart_m_p<BASE, FEAT, LOGCAT>::write_epc(unsigned addr, reg_t val) {
|
||||||
csr[addr] = val & get_pc_mask();
|
csr[addr] = val & get_pc_mask();
|
||||||
return iss::Ok;
|
return iss::Ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename BASE, features_e FEAT> iss::status riscv_hart_m_p<BASE, FEAT>::write_dcsr_dcsr(unsigned addr, reg_t val) {
|
template <typename BASE, features_e FEAT, typename LOGCAT> iss::status riscv_hart_m_p<BASE, FEAT, LOGCAT>::write_dcsr_dcsr(unsigned addr, reg_t val) {
|
||||||
if(!debug_mode_active())
|
if(!debug_mode_active())
|
||||||
throw illegal_instruction_fault(this->fault_data);
|
throw illegal_instruction_fault(this->fault_data);
|
||||||
// +-------------- ebreakm
|
// +-------------- ebreakm
|
||||||
|
@ -1029,51 +1029,51 @@ template <typename BASE, features_e FEAT> iss::status riscv_hart_m_p<BASE, FEAT>
|
||||||
return iss::Ok;
|
return iss::Ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename BASE, features_e FEAT> iss::status riscv_hart_m_p<BASE, FEAT>::read_dcsr_reg(unsigned addr, reg_t& val) {
|
template <typename BASE, features_e FEAT, typename LOGCAT> iss::status riscv_hart_m_p<BASE, FEAT, LOGCAT>::read_dcsr_reg(unsigned addr, reg_t& val) {
|
||||||
if(!debug_mode_active())
|
if(!debug_mode_active())
|
||||||
throw illegal_instruction_fault(this->fault_data);
|
throw illegal_instruction_fault(this->fault_data);
|
||||||
val = csr[addr];
|
val = csr[addr];
|
||||||
return iss::Ok;
|
return iss::Ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename BASE, features_e FEAT> iss::status riscv_hart_m_p<BASE, FEAT>::write_dcsr_reg(unsigned addr, reg_t val) {
|
template <typename BASE, features_e FEAT, typename LOGCAT> iss::status riscv_hart_m_p<BASE, FEAT, LOGCAT>::write_dcsr_reg(unsigned addr, reg_t val) {
|
||||||
if(!debug_mode_active())
|
if(!debug_mode_active())
|
||||||
throw illegal_instruction_fault(this->fault_data);
|
throw illegal_instruction_fault(this->fault_data);
|
||||||
csr[addr] = val;
|
csr[addr] = val;
|
||||||
return iss::Ok;
|
return iss::Ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename BASE, features_e FEAT> iss::status riscv_hart_m_p<BASE, FEAT>::read_dpc_reg(unsigned addr, reg_t& val) {
|
template <typename BASE, features_e FEAT, typename LOGCAT> iss::status riscv_hart_m_p<BASE, FEAT, LOGCAT>::read_dpc_reg(unsigned addr, reg_t& val) {
|
||||||
if(!debug_mode_active())
|
if(!debug_mode_active())
|
||||||
throw illegal_instruction_fault(this->fault_data);
|
throw illegal_instruction_fault(this->fault_data);
|
||||||
val = this->reg.DPC;
|
val = this->reg.DPC;
|
||||||
return iss::Ok;
|
return iss::Ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename BASE, features_e FEAT> iss::status riscv_hart_m_p<BASE, FEAT>::write_dpc_reg(unsigned addr, reg_t val) {
|
template <typename BASE, features_e FEAT, typename LOGCAT> iss::status riscv_hart_m_p<BASE, FEAT, LOGCAT>::write_dpc_reg(unsigned addr, reg_t val) {
|
||||||
if(!debug_mode_active())
|
if(!debug_mode_active())
|
||||||
throw illegal_instruction_fault(this->fault_data);
|
throw illegal_instruction_fault(this->fault_data);
|
||||||
this->reg.DPC = val;
|
this->reg.DPC = val;
|
||||||
return iss::Ok;
|
return iss::Ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename BASE, features_e FEAT> iss::status riscv_hart_m_p<BASE, FEAT>::read_intstatus(unsigned addr, reg_t& val) {
|
template <typename BASE, features_e FEAT, typename LOGCAT> iss::status riscv_hart_m_p<BASE, FEAT, LOGCAT>::read_intstatus(unsigned addr, reg_t& val) {
|
||||||
val = (clic_mact_lvl & 0xff) << 24;
|
val = (clic_mact_lvl & 0xff) << 24;
|
||||||
return iss::Ok;
|
return iss::Ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename BASE, features_e FEAT> iss::status riscv_hart_m_p<BASE, FEAT>::write_intthresh(unsigned addr, reg_t val) {
|
template <typename BASE, features_e FEAT, typename LOGCAT> iss::status riscv_hart_m_p<BASE, FEAT, LOGCAT>::write_intthresh(unsigned addr, reg_t val) {
|
||||||
csr[addr] = (val & 0xff) | (1 << (cfg.clic_int_ctl_bits)) - 1;
|
csr[addr] = (val & 0xff) | (1 << (cfg.clic_int_ctl_bits)) - 1;
|
||||||
return iss::Ok;
|
return iss::Ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename BASE, features_e FEAT> iss::status riscv_hart_m_p<BASE, FEAT>::write_xtvt(unsigned addr, reg_t val) {
|
template <typename BASE, features_e FEAT, typename LOGCAT> iss::status riscv_hart_m_p<BASE, FEAT, LOGCAT>::write_xtvt(unsigned addr, reg_t val) {
|
||||||
csr[addr] = val & ~0x3fULL;
|
csr[addr] = val & ~0x3fULL;
|
||||||
return iss::Ok;
|
return iss::Ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename BASE, features_e FEAT>
|
template <typename BASE, features_e FEAT, typename LOGCAT>
|
||||||
iss::status riscv_hart_m_p<BASE, FEAT>::read_mem(phys_addr_t paddr, unsigned length, uint8_t* const data) {
|
iss::status riscv_hart_m_p<BASE, FEAT, LOGCAT>::read_mem(phys_addr_t paddr, unsigned length, uint8_t* const data) {
|
||||||
switch(paddr.val) {
|
switch(paddr.val) {
|
||||||
default: {
|
default: {
|
||||||
for(auto offs = 0U; offs < length; ++offs) {
|
for(auto offs = 0U; offs < length; ++offs) {
|
||||||
|
@ -1084,8 +1084,8 @@ iss::status riscv_hart_m_p<BASE, FEAT>::read_mem(phys_addr_t paddr, unsigned len
|
||||||
return iss::Ok;
|
return iss::Ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename BASE, features_e FEAT>
|
template <typename BASE, features_e FEAT, typename LOGCAT>
|
||||||
iss::status riscv_hart_m_p<BASE, FEAT>::write_mem(phys_addr_t paddr, unsigned length, const uint8_t* const data) {
|
iss::status riscv_hart_m_p<BASE, FEAT, LOGCAT>::write_mem(phys_addr_t paddr, unsigned length, const uint8_t* const data) {
|
||||||
switch(paddr.val) {
|
switch(paddr.val) {
|
||||||
// TODO remove UART, Peripherals should not be part of the ISS
|
// TODO remove UART, Peripherals should not be part of the ISS
|
||||||
case 0xFFFF0000: // UART0 base, TXFIFO reg
|
case 0xFFFF0000: // UART0 base, TXFIFO reg
|
||||||
|
@ -1143,8 +1143,8 @@ iss::status riscv_hart_m_p<BASE, FEAT>::write_mem(phys_addr_t paddr, unsigned le
|
||||||
return iss::Ok;
|
return iss::Ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename BASE, features_e FEAT>
|
template <typename BASE, features_e FEAT, typename LOGCAT>
|
||||||
iss::status riscv_hart_m_p<BASE, FEAT>::read_clic(uint64_t addr, unsigned length, uint8_t* const data) {
|
iss::status riscv_hart_m_p<BASE, FEAT, LOGCAT>::read_clic(uint64_t addr, unsigned length, uint8_t* const data) {
|
||||||
if(addr == cfg.clic_base) { // cliccfg
|
if(addr == cfg.clic_base) { // cliccfg
|
||||||
*data = clic_cfg_reg;
|
*data = clic_cfg_reg;
|
||||||
for(auto i = 1; i < length; ++i)
|
for(auto i = 1; i < length; ++i)
|
||||||
|
@ -1163,8 +1163,8 @@ iss::status riscv_hart_m_p<BASE, FEAT>::read_clic(uint64_t addr, unsigned length
|
||||||
return iss::Ok;
|
return iss::Ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename BASE, features_e FEAT>
|
template <typename BASE, features_e FEAT, typename LOGCAT>
|
||||||
iss::status riscv_hart_m_p<BASE, FEAT>::write_clic(uint64_t addr, unsigned length, const uint8_t* const data) {
|
iss::status riscv_hart_m_p<BASE, FEAT, LOGCAT>::write_clic(uint64_t addr, unsigned length, const uint8_t* const data) {
|
||||||
if(addr == cfg.clic_base) { // cliccfg
|
if(addr == cfg.clic_base) { // cliccfg
|
||||||
clic_cfg_reg = (clic_cfg_reg & ~0x1e) | (*data & 0x1e);
|
clic_cfg_reg = (clic_cfg_reg & ~0x1e) | (*data & 0x1e);
|
||||||
} else if(addr >= (cfg.clic_base + 0x40) && (addr + length) <= (cfg.clic_base + 0x40 + cfg.clic_num_trigger * 4)) { // clicinttrig
|
} else if(addr >= (cfg.clic_base + 0x40) && (addr + length) <= (cfg.clic_base + 0x40 + cfg.clic_num_trigger * 4)) { // clicinttrig
|
||||||
|
@ -1179,12 +1179,12 @@ iss::status riscv_hart_m_p<BASE, FEAT>::write_clic(uint64_t addr, unsigned lengt
|
||||||
return iss::Ok;
|
return iss::Ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename BASE, features_e FEAT> inline void riscv_hart_m_p<BASE, FEAT>::reset(uint64_t address) {
|
template <typename BASE, features_e FEAT, typename LOGCAT> inline void riscv_hart_m_p<BASE, FEAT, LOGCAT>::reset(uint64_t address) {
|
||||||
BASE::reset(address);
|
BASE::reset(address);
|
||||||
state.mstatus = hart_state_type::mstatus_reset_val;
|
state.mstatus = hart_state_type::mstatus_reset_val;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename BASE, features_e FEAT> void riscv_hart_m_p<BASE, FEAT>::check_interrupt() {
|
template <typename BASE, features_e FEAT, typename LOGCAT> void riscv_hart_m_p<BASE, FEAT, LOGCAT>::check_interrupt() {
|
||||||
// TODO: Implement CLIC functionality
|
// TODO: Implement CLIC functionality
|
||||||
// auto ideleg = csr[mideleg];
|
// auto ideleg = csr[mideleg];
|
||||||
// Multiple simultaneous interrupts and traps at the same privilege level are
|
// Multiple simultaneous interrupts and traps at the same privilege level are
|
||||||
|
@ -1207,7 +1207,7 @@ template <typename BASE, features_e FEAT> void riscv_hart_m_p<BASE, FEAT>::check
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename BASE, features_e FEAT> uint64_t riscv_hart_m_p<BASE, FEAT>::enter_trap(uint64_t flags, uint64_t addr, uint64_t tval) {
|
template <typename BASE, features_e FEAT, typename LOGCAT> uint64_t riscv_hart_m_p<BASE, FEAT, LOGCAT>::enter_trap(uint64_t flags, uint64_t addr, uint64_t tval) {
|
||||||
// flags are ACTIVE[31:31], CAUSE[30:16], TRAPID[15:0]
|
// flags are ACTIVE[31:31], CAUSE[30:16], TRAPID[15:0]
|
||||||
// calculate and write mcause val
|
// calculate and write mcause val
|
||||||
auto const trap_id = bit_sub<0, 16>(flags);
|
auto const trap_id = bit_sub<0, 16>(flags);
|
||||||
|
@ -1260,7 +1260,7 @@ template <typename BASE, features_e FEAT> uint64_t riscv_hart_m_p<BASE, FEAT>::e
|
||||||
#else
|
#else
|
||||||
sprintf(buffer.data(), "0x%016lx", addr);
|
sprintf(buffer.data(), "0x%016lx", addr);
|
||||||
#endif
|
#endif
|
||||||
CLOG(INFO, disass) << "Semihosting call at address " << buffer.data() << " occurred ";
|
NSCLOG(INFO, LOGCAT) << "Semihosting call at address " << buffer.data() << " occurred ";
|
||||||
|
|
||||||
semihosting_cb(this, &(this->reg.X10) /*a0*/, &(this->reg.X11) /*a1*/);
|
semihosting_cb(this, &(this->reg.X10) /*a0*/, &(this->reg.X11) /*a1*/);
|
||||||
return this->reg.NEXT_PC;
|
return this->reg.NEXT_PC;
|
||||||
|
@ -1316,18 +1316,18 @@ template <typename BASE, features_e FEAT> uint64_t riscv_hart_m_p<BASE, FEAT>::e
|
||||||
sprintf(buffer.data(), "0x%016lx", addr);
|
sprintf(buffer.data(), "0x%016lx", addr);
|
||||||
#endif
|
#endif
|
||||||
if((flags & 0xffffffff) != 0xffffffff)
|
if((flags & 0xffffffff) != 0xffffffff)
|
||||||
CLOG(INFO, disass) << (trap_id ? "Interrupt" : "Trap") << " with cause '" << (trap_id ? irq_str[cause] : trap_str[cause]) << "' ("
|
NSCLOG(INFO, LOGCAT) << (trap_id ? "Interrupt" : "Trap") << " with cause '" << (trap_id ? irq_str[cause] : trap_str[cause]) << "' ("
|
||||||
<< cause << ")"
|
<< cause << ")"
|
||||||
<< " at address " << buffer.data() << " occurred";
|
<< " at address " << buffer.data() << " occurred";
|
||||||
return this->reg.NEXT_PC;
|
return this->reg.NEXT_PC;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename BASE, features_e FEAT> uint64_t riscv_hart_m_p<BASE, FEAT>::leave_trap(uint64_t flags) {
|
template <typename BASE, features_e FEAT, typename LOGCAT> uint64_t riscv_hart_m_p<BASE, FEAT, LOGCAT>::leave_trap(uint64_t flags) {
|
||||||
state.mstatus.MIE = state.mstatus.MPIE;
|
state.mstatus.MIE = state.mstatus.MPIE;
|
||||||
state.mstatus.MPIE = 1;
|
state.mstatus.MPIE = 1;
|
||||||
// sets the pc to the value stored in the x epc register.
|
// sets the pc to the value stored in the x epc register.
|
||||||
this->reg.NEXT_PC = csr[mepc] & get_pc_mask();
|
this->reg.NEXT_PC = csr[mepc] & get_pc_mask();
|
||||||
CLOG(INFO, disass) << "Executing xRET";
|
NSCLOG(INFO, LOGCAT) << "Executing xRET";
|
||||||
check_interrupt();
|
check_interrupt();
|
||||||
this->reg.trap_state = this->reg.pending_trap;
|
this->reg.trap_state = this->reg.pending_trap;
|
||||||
return this->reg.NEXT_PC;
|
return this->reg.NEXT_PC;
|
||||||
|
|
|
@ -60,7 +60,7 @@
|
||||||
namespace iss {
|
namespace iss {
|
||||||
namespace arch {
|
namespace arch {
|
||||||
|
|
||||||
template <typename BASE, features_e FEAT = FEAT_NONE> class riscv_hart_mu_p : public BASE, public riscv_hart_common {
|
template <typename BASE, features_e FEAT = FEAT_NONE, typename LOGCAT=logging::disass> class riscv_hart_mu_p : public BASE, public riscv_hart_common {
|
||||||
protected:
|
protected:
|
||||||
const std::array<const char, 4> lvl = {{'U', 'S', 'H', 'M'}};
|
const std::array<const char, 4> lvl = {{'U', 'S', 'H', 'M'}};
|
||||||
const std::array<const char*, 16> trap_str = {{""
|
const std::array<const char*, 16> trap_str = {{""
|
||||||
|
@ -87,7 +87,7 @@ protected:
|
||||||
|
|
||||||
public:
|
public:
|
||||||
using core = BASE;
|
using core = BASE;
|
||||||
using this_class = riscv_hart_mu_p<BASE, FEAT>;
|
using this_class = riscv_hart_mu_p<BASE, FEAT, LOGCAT>;
|
||||||
using phys_addr_t = typename core::phys_addr_t;
|
using phys_addr_t = typename core::phys_addr_t;
|
||||||
using reg_t = typename core::reg_t;
|
using reg_t = typename core::reg_t;
|
||||||
using addr_t = typename core::addr_t;
|
using addr_t = typename core::addr_t;
|
||||||
|
@ -316,7 +316,7 @@ public:
|
||||||
protected:
|
protected:
|
||||||
struct riscv_instrumentation_if : public iss::instrumentation_if {
|
struct riscv_instrumentation_if : public iss::instrumentation_if {
|
||||||
|
|
||||||
riscv_instrumentation_if(riscv_hart_mu_p<BASE, FEAT>& arch)
|
riscv_instrumentation_if(riscv_hart_mu_p<BASE, FEAT, LOGCAT>& arch)
|
||||||
: arch(arch) {}
|
: arch(arch) {}
|
||||||
/**
|
/**
|
||||||
* get the name of this architecture
|
* get the name of this architecture
|
||||||
|
@ -347,7 +347,7 @@ protected:
|
||||||
|
|
||||||
std::unordered_map<std::string, uint64_t> get_symbol_table(std::string name) override { return arch.get_sym_table(name); }
|
std::unordered_map<std::string, uint64_t> get_symbol_table(std::string name) override { return arch.get_sym_table(name); }
|
||||||
|
|
||||||
riscv_hart_mu_p<BASE, FEAT>& arch;
|
riscv_hart_mu_p<BASE, FEAT, LOGCAT>& arch;
|
||||||
};
|
};
|
||||||
|
|
||||||
friend struct riscv_instrumentation_if;
|
friend struct riscv_instrumentation_if;
|
||||||
|
@ -461,8 +461,8 @@ protected:
|
||||||
std::function<mem_write_f> hart_mem_wr_delegate;
|
std::function<mem_write_f> hart_mem_wr_delegate;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename BASE, features_e FEAT>
|
template <typename BASE, features_e FEAT, typename LOGCAT>
|
||||||
riscv_hart_mu_p<BASE, FEAT>::riscv_hart_mu_p(feature_config cfg)
|
riscv_hart_mu_p<BASE, FEAT, LOGCAT>::riscv_hart_mu_p(feature_config cfg)
|
||||||
: state()
|
: state()
|
||||||
, instr_if(*this)
|
, instr_if(*this)
|
||||||
, cfg(cfg) {
|
, cfg(cfg) {
|
||||||
|
@ -641,7 +641,7 @@ riscv_hart_mu_p<BASE, FEAT>::riscv_hart_mu_p(feature_config cfg)
|
||||||
hart_mem_wr_delegate = [this](phys_addr_t a, unsigned l, uint8_t const* const d) -> iss::status { return this->write_mem(a, l, d); };
|
hart_mem_wr_delegate = [this](phys_addr_t a, unsigned l, uint8_t const* const d) -> iss::status { return this->write_mem(a, l, d); };
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename BASE, features_e FEAT> std::pair<uint64_t, bool> riscv_hart_mu_p<BASE, FEAT>::load_file(std::string name, int type) {
|
template <typename BASE, features_e FEAT, typename LOGCAT> std::pair<uint64_t, bool> riscv_hart_mu_p<BASE, FEAT, LOGCAT>::load_file(std::string name, int type) {
|
||||||
FILE* fp = fopen(name.c_str(), "r");
|
FILE* fp = fopen(name.c_str(), "r");
|
||||||
if(fp) {
|
if(fp) {
|
||||||
std::array<char, 5> buf;
|
std::array<char, 5> buf;
|
||||||
|
@ -709,8 +709,8 @@ template <typename BASE, features_e FEAT> std::pair<uint64_t, bool> riscv_hart_m
|
||||||
throw std::runtime_error(fmt::format("memory load file not found, check if {} is a valid file", name));
|
throw std::runtime_error(fmt::format("memory load file not found, check if {} is a valid file", name));
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename BASE, features_e FEAT>
|
template <typename BASE, features_e FEAT, typename LOGCAT>
|
||||||
inline void riscv_hart_mu_p<BASE, FEAT>::insert_mem_range(uint64_t base, uint64_t size, std::function<mem_read_f> rd_f,
|
inline void riscv_hart_mu_p<BASE, FEAT, LOGCAT>::insert_mem_range(uint64_t base, uint64_t size, std::function<mem_read_f> rd_f,
|
||||||
std::function<mem_write_f> wr_fn) {
|
std::function<mem_write_f> wr_fn) {
|
||||||
std::tuple<uint64_t, uint64_t> entry{base, size};
|
std::tuple<uint64_t, uint64_t> entry{base, size};
|
||||||
auto it = std::upper_bound(
|
auto it = std::upper_bound(
|
||||||
|
@ -722,13 +722,13 @@ inline void riscv_hart_mu_p<BASE, FEAT>::insert_mem_range(uint64_t base, uint64_
|
||||||
memfn_write.insert(std::begin(memfn_write) + idx, wr_fn);
|
memfn_write.insert(std::begin(memfn_write) + idx, wr_fn);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename BASE, features_e FEAT> inline iss::status riscv_hart_mu_p<BASE, FEAT>::write_pmpcfg_reg(unsigned addr, reg_t val) {
|
template <typename BASE, features_e FEAT, typename LOGCAT> inline iss::status riscv_hart_mu_p<BASE, FEAT, LOGCAT>::write_pmpcfg_reg(unsigned addr, reg_t val) {
|
||||||
csr[addr] = val & 0x9f9f9f9f;
|
csr[addr] = val & 0x9f9f9f9f;
|
||||||
return iss::Ok;
|
return iss::Ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename BASE, features_e FEAT>
|
template <typename BASE, features_e FEAT, typename LOGCAT>
|
||||||
bool riscv_hart_mu_p<BASE, FEAT>::pmp_check(const access_type type, const uint64_t addr, const unsigned len) {
|
bool riscv_hart_mu_p<BASE, FEAT, LOGCAT>::pmp_check(const access_type type, const uint64_t addr, const unsigned len) {
|
||||||
constexpr auto PMP_SHIFT = 2U;
|
constexpr auto PMP_SHIFT = 2U;
|
||||||
constexpr auto PMP_R = 0x1U;
|
constexpr auto PMP_R = 0x1U;
|
||||||
constexpr auto PMP_W = 0x2U;
|
constexpr auto PMP_W = 0x2U;
|
||||||
|
@ -808,8 +808,8 @@ bool riscv_hart_mu_p<BASE, FEAT>::pmp_check(const access_type type, const uint64
|
||||||
return !any_active || this->reg.PRIV == PRIV_M;
|
return !any_active || this->reg.PRIV == PRIV_M;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename BASE, features_e FEAT>
|
template <typename BASE, features_e FEAT, typename LOGCAT>
|
||||||
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,
|
iss::status riscv_hart_mu_p<BASE, FEAT, LOGCAT>::read(const address_type type, const access_type access, const uint32_t space, const uint64_t addr,
|
||||||
const unsigned length, uint8_t* const data) {
|
const unsigned length, uint8_t* const data) {
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
if(access && iss::access_type::DEBUG) {
|
if(access && iss::access_type::DEBUG) {
|
||||||
|
@ -901,8 +901,8 @@ iss::status riscv_hart_mu_p<BASE, FEAT>::read(const address_type type, const acc
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename BASE, features_e FEAT>
|
template <typename BASE, features_e FEAT, typename LOGCAT>
|
||||||
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,
|
iss::status riscv_hart_mu_p<BASE, FEAT, LOGCAT>::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) {
|
const unsigned length, const uint8_t* const data) {
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
const char* prefix = (access && iss::access_type::DEBUG) ? "debug " : "";
|
const char* prefix = (access && iss::access_type::DEBUG) ? "debug " : "";
|
||||||
|
@ -1043,7 +1043,7 @@ iss::status riscv_hart_mu_p<BASE, FEAT>::write(const address_type type, const ac
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename BASE, features_e FEAT> iss::status riscv_hart_mu_p<BASE, FEAT>::read_csr(unsigned addr, reg_t& val) {
|
template <typename BASE, features_e FEAT, typename LOGCAT> iss::status riscv_hart_mu_p<BASE, FEAT, LOGCAT>::read_csr(unsigned addr, reg_t& val) {
|
||||||
if(addr >= csr.size())
|
if(addr >= csr.size())
|
||||||
return iss::Err;
|
return iss::Err;
|
||||||
auto req_priv_lvl = (addr >> 8) & 0x3;
|
auto req_priv_lvl = (addr >> 8) & 0x3;
|
||||||
|
@ -1055,7 +1055,7 @@ template <typename BASE, features_e FEAT> iss::status riscv_hart_mu_p<BASE, FEAT
|
||||||
return (this->*(it->second))(addr, val);
|
return (this->*(it->second))(addr, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename BASE, features_e FEAT> iss::status riscv_hart_mu_p<BASE, FEAT>::write_csr(unsigned addr, reg_t val) {
|
template <typename BASE, features_e FEAT, typename LOGCAT> iss::status riscv_hart_mu_p<BASE, FEAT, LOGCAT>::write_csr(unsigned addr, reg_t val) {
|
||||||
if(addr >= csr.size())
|
if(addr >= csr.size())
|
||||||
return iss::Err;
|
return iss::Err;
|
||||||
auto req_priv_lvl = (addr >> 8) & 0x3;
|
auto req_priv_lvl = (addr >> 8) & 0x3;
|
||||||
|
@ -1069,22 +1069,22 @@ template <typename BASE, features_e FEAT> iss::status riscv_hart_mu_p<BASE, FEAT
|
||||||
return (this->*(it->second))(addr, val);
|
return (this->*(it->second))(addr, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename BASE, features_e FEAT> iss::status riscv_hart_mu_p<BASE, FEAT>::read_csr_reg(unsigned addr, reg_t& val) {
|
template <typename BASE, features_e FEAT, typename LOGCAT> iss::status riscv_hart_mu_p<BASE, FEAT, LOGCAT>::read_csr_reg(unsigned addr, reg_t& val) {
|
||||||
val = csr[addr];
|
val = csr[addr];
|
||||||
return iss::Ok;
|
return iss::Ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename BASE, features_e FEAT> iss::status riscv_hart_mu_p<BASE, FEAT>::read_null(unsigned addr, reg_t& val) {
|
template <typename BASE, features_e FEAT, typename LOGCAT> iss::status riscv_hart_mu_p<BASE, FEAT, LOGCAT>::read_null(unsigned addr, reg_t& val) {
|
||||||
val = 0;
|
val = 0;
|
||||||
return iss::Ok;
|
return iss::Ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename BASE, features_e FEAT> iss::status riscv_hart_mu_p<BASE, FEAT>::write_csr_reg(unsigned addr, reg_t val) {
|
template <typename BASE, features_e FEAT, typename LOGCAT> iss::status riscv_hart_mu_p<BASE, FEAT, LOGCAT>::write_csr_reg(unsigned addr, reg_t val) {
|
||||||
csr[addr] = val;
|
csr[addr] = val;
|
||||||
return iss::Ok;
|
return iss::Ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename BASE, features_e FEAT> iss::status riscv_hart_mu_p<BASE, FEAT>::read_cycle(unsigned addr, reg_t& val) {
|
template <typename BASE, features_e FEAT, typename LOGCAT> iss::status riscv_hart_mu_p<BASE, FEAT, LOGCAT>::read_cycle(unsigned addr, reg_t& val) {
|
||||||
auto cycle_val = this->reg.icount + cycle_offset;
|
auto cycle_val = this->reg.icount + cycle_offset;
|
||||||
if(addr == mcycle) {
|
if(addr == mcycle) {
|
||||||
val = static_cast<reg_t>(cycle_val);
|
val = static_cast<reg_t>(cycle_val);
|
||||||
|
@ -1094,7 +1094,7 @@ template <typename BASE, features_e FEAT> iss::status riscv_hart_mu_p<BASE, FEAT
|
||||||
return iss::Ok;
|
return iss::Ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename BASE, features_e FEAT> iss::status riscv_hart_mu_p<BASE, FEAT>::write_cycle(unsigned addr, reg_t val) {
|
template <typename BASE, features_e FEAT, typename LOGCAT> iss::status riscv_hart_mu_p<BASE, FEAT, LOGCAT>::write_cycle(unsigned addr, reg_t val) {
|
||||||
if(sizeof(typename traits<BASE>::reg_t) != 4) {
|
if(sizeof(typename traits<BASE>::reg_t) != 4) {
|
||||||
mcycle_csr = static_cast<uint64_t>(val);
|
mcycle_csr = static_cast<uint64_t>(val);
|
||||||
} else {
|
} else {
|
||||||
|
@ -1108,7 +1108,7 @@ template <typename BASE, features_e FEAT> iss::status riscv_hart_mu_p<BASE, FEAT
|
||||||
return iss::Ok;
|
return iss::Ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename BASE, features_e FEAT> iss::status riscv_hart_mu_p<BASE, FEAT>::read_instret(unsigned addr, reg_t& val) {
|
template <typename BASE, features_e FEAT, typename LOGCAT> iss::status riscv_hart_mu_p<BASE, FEAT, LOGCAT>::read_instret(unsigned addr, reg_t& val) {
|
||||||
if((addr & 0xff) == (minstret & 0xff)) {
|
if((addr & 0xff) == (minstret & 0xff)) {
|
||||||
val = static_cast<reg_t>(this->reg.instret);
|
val = static_cast<reg_t>(this->reg.instret);
|
||||||
} else if((addr & 0xff) == (minstreth & 0xff)) {
|
} else if((addr & 0xff) == (minstreth & 0xff)) {
|
||||||
|
@ -1117,7 +1117,7 @@ template <typename BASE, features_e FEAT> iss::status riscv_hart_mu_p<BASE, FEAT
|
||||||
return iss::Ok;
|
return iss::Ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename BASE, features_e FEAT> iss::status riscv_hart_mu_p<BASE, FEAT>::write_instret(unsigned addr, reg_t val) {
|
template <typename BASE, features_e FEAT, typename LOGCAT> iss::status riscv_hart_mu_p<BASE, FEAT, LOGCAT>::write_instret(unsigned addr, reg_t val) {
|
||||||
if(sizeof(typename traits<BASE>::reg_t) != 4) {
|
if(sizeof(typename traits<BASE>::reg_t) != 4) {
|
||||||
this->reg.instret = static_cast<uint64_t>(val);
|
this->reg.instret = static_cast<uint64_t>(val);
|
||||||
} else {
|
} else {
|
||||||
|
@ -1131,7 +1131,7 @@ template <typename BASE, features_e FEAT> iss::status riscv_hart_mu_p<BASE, FEAT
|
||||||
return iss::Ok;
|
return iss::Ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename BASE, features_e FEAT> iss::status riscv_hart_mu_p<BASE, FEAT>::read_time(unsigned addr, reg_t& val) {
|
template <typename BASE, features_e FEAT, typename LOGCAT> iss::status riscv_hart_mu_p<BASE, FEAT, LOGCAT>::read_time(unsigned addr, reg_t& val) {
|
||||||
uint64_t time_val = this->reg.icount / (100000000 / 32768 - 1); //-> ~3052;
|
uint64_t time_val = this->reg.icount / (100000000 / 32768 - 1); //-> ~3052;
|
||||||
if(addr == time) {
|
if(addr == time) {
|
||||||
val = static_cast<reg_t>(time_val);
|
val = static_cast<reg_t>(time_val);
|
||||||
|
@ -1143,22 +1143,22 @@ template <typename BASE, features_e FEAT> iss::status riscv_hart_mu_p<BASE, FEAT
|
||||||
return iss::Ok;
|
return iss::Ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename BASE, features_e FEAT> iss::status riscv_hart_mu_p<BASE, FEAT>::read_tvec(unsigned addr, reg_t& val) {
|
template <typename BASE, features_e FEAT, typename LOGCAT> iss::status riscv_hart_mu_p<BASE, FEAT, LOGCAT>::read_tvec(unsigned addr, reg_t& val) {
|
||||||
val = FEAT & features_e::FEAT_CLIC ? csr[addr] : csr[addr] & ~2;
|
val = FEAT & features_e::FEAT_CLIC ? csr[addr] : csr[addr] & ~2;
|
||||||
return iss::Ok;
|
return iss::Ok;
|
||||||
}
|
}
|
||||||
template <typename BASE, features_e FEAT> iss::status riscv_hart_mu_p<BASE, FEAT>::read_status(unsigned addr, reg_t& val) {
|
template <typename BASE, features_e FEAT, typename LOGCAT> iss::status riscv_hart_mu_p<BASE, FEAT, LOGCAT>::read_status(unsigned addr, reg_t& val) {
|
||||||
val = state.mstatus & hart_state_type::get_mask((addr >> 8) & 0x3);
|
val = state.mstatus & hart_state_type::get_mask((addr >> 8) & 0x3);
|
||||||
return iss::Ok;
|
return iss::Ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename BASE, features_e FEAT> iss::status riscv_hart_mu_p<BASE, FEAT>::write_status(unsigned addr, reg_t val) {
|
template <typename BASE, features_e FEAT, typename LOGCAT> iss::status riscv_hart_mu_p<BASE, FEAT, LOGCAT>::write_status(unsigned addr, reg_t val) {
|
||||||
state.write_mstatus(val, (addr >> 8) & 0x3);
|
state.write_mstatus(val, (addr >> 8) & 0x3);
|
||||||
check_interrupt();
|
check_interrupt();
|
||||||
return iss::Ok;
|
return iss::Ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename BASE, features_e FEAT> iss::status riscv_hart_mu_p<BASE, FEAT>::read_cause(unsigned addr, reg_t& val) {
|
template <typename BASE, features_e FEAT, typename LOGCAT> iss::status riscv_hart_mu_p<BASE, FEAT, LOGCAT>::read_cause(unsigned addr, reg_t& val) {
|
||||||
if((FEAT & features_e::FEAT_CLIC) && (csr[mtvec] & 0x3) == 3) {
|
if((FEAT & features_e::FEAT_CLIC) && (csr[mtvec] & 0x3) == 3) {
|
||||||
val = csr[addr] & ((1UL << (traits<BASE>::XLEN - 1)) | (mcause_max_irq - 1) | (0xfUL << 16));
|
val = csr[addr] & ((1UL << (traits<BASE>::XLEN - 1)) | (mcause_max_irq - 1) | (0xfUL << 16));
|
||||||
auto mode = (addr >> 8) & 0x3;
|
auto mode = (addr >> 8) & 0x3;
|
||||||
|
@ -1178,7 +1178,7 @@ template <typename BASE, features_e FEAT> iss::status riscv_hart_mu_p<BASE, FEAT
|
||||||
return iss::Ok;
|
return iss::Ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename BASE, features_e FEAT> iss::status riscv_hart_mu_p<BASE, FEAT>::write_cause(unsigned addr, reg_t val) {
|
template <typename BASE, features_e FEAT, typename LOGCAT> iss::status riscv_hart_mu_p<BASE, FEAT, LOGCAT>::write_cause(unsigned addr, reg_t val) {
|
||||||
if((FEAT & features_e::FEAT_CLIC) && (csr[mtvec] & 0x3) == 3) {
|
if((FEAT & features_e::FEAT_CLIC) && (csr[mtvec] & 0x3) == 3) {
|
||||||
auto mask = ((1UL << (traits<BASE>::XLEN - 1)) | (mcause_max_irq - 1) | (0xfUL << 16));
|
auto mask = ((1UL << (traits<BASE>::XLEN - 1)) | (mcause_max_irq - 1) | (0xfUL << 16));
|
||||||
csr[addr] = (val & mask) | (csr[addr] & ~mask);
|
csr[addr] = (val & mask) | (csr[addr] & ~mask);
|
||||||
|
@ -1201,12 +1201,12 @@ template <typename BASE, features_e FEAT> iss::status riscv_hart_mu_p<BASE, FEAT
|
||||||
return iss::Ok;
|
return iss::Ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename BASE, features_e FEAT> iss::status riscv_hart_mu_p<BASE, FEAT>::read_hartid(unsigned addr, reg_t& val) {
|
template <typename BASE, features_e FEAT, typename LOGCAT> iss::status riscv_hart_mu_p<BASE, FEAT, LOGCAT>::read_hartid(unsigned addr, reg_t& val) {
|
||||||
val = mhartid_reg;
|
val = mhartid_reg;
|
||||||
return iss::Ok;
|
return iss::Ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename BASE, features_e FEAT> iss::status riscv_hart_mu_p<BASE, FEAT>::read_ie(unsigned addr, reg_t& val) {
|
template <typename BASE, features_e FEAT, typename LOGCAT> iss::status riscv_hart_mu_p<BASE, FEAT, LOGCAT>::read_ie(unsigned addr, reg_t& val) {
|
||||||
auto mask = get_irq_mask((addr >> 8) & 0x3);
|
auto mask = get_irq_mask((addr >> 8) & 0x3);
|
||||||
val = csr[mie] & mask;
|
val = csr[mie] & mask;
|
||||||
if(this->reg.PRIV != 3)
|
if(this->reg.PRIV != 3)
|
||||||
|
@ -1214,14 +1214,14 @@ template <typename BASE, features_e FEAT> iss::status riscv_hart_mu_p<BASE, FEAT
|
||||||
return iss::Ok;
|
return iss::Ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename BASE, features_e FEAT> iss::status riscv_hart_mu_p<BASE, FEAT>::write_ie(unsigned addr, reg_t val) {
|
template <typename BASE, features_e FEAT, typename LOGCAT> iss::status riscv_hart_mu_p<BASE, FEAT, LOGCAT>::write_ie(unsigned addr, reg_t val) {
|
||||||
auto mask = get_irq_mask((addr >> 8) & 0x3);
|
auto mask = get_irq_mask((addr >> 8) & 0x3);
|
||||||
csr[mie] = (csr[mie] & ~mask) | (val & mask);
|
csr[mie] = (csr[mie] & ~mask) | (val & mask);
|
||||||
check_interrupt();
|
check_interrupt();
|
||||||
return iss::Ok;
|
return iss::Ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename BASE, features_e FEAT> iss::status riscv_hart_mu_p<BASE, FEAT>::read_ip(unsigned addr, reg_t& val) {
|
template <typename BASE, features_e FEAT, typename LOGCAT> iss::status riscv_hart_mu_p<BASE, FEAT, LOGCAT>::read_ip(unsigned addr, reg_t& val) {
|
||||||
auto mask = get_irq_mask((addr >> 8) & 0x3);
|
auto mask = get_irq_mask((addr >> 8) & 0x3);
|
||||||
val = csr[mip] & mask;
|
val = csr[mip] & mask;
|
||||||
if(this->reg.PRIV != 3)
|
if(this->reg.PRIV != 3)
|
||||||
|
@ -1229,24 +1229,24 @@ template <typename BASE, features_e FEAT> iss::status riscv_hart_mu_p<BASE, FEAT
|
||||||
return iss::Ok;
|
return iss::Ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename BASE, features_e FEAT> iss::status riscv_hart_mu_p<BASE, FEAT>::write_ideleg(unsigned addr, reg_t val) {
|
template <typename BASE, features_e FEAT, typename LOGCAT> iss::status riscv_hart_mu_p<BASE, FEAT, LOGCAT>::write_ideleg(unsigned addr, reg_t val) {
|
||||||
auto mask = 0b000100010001; // only U mode supported
|
auto mask = 0b000100010001; // only U mode supported
|
||||||
csr[mideleg] = (csr[mideleg] & ~mask) | (val & mask);
|
csr[mideleg] = (csr[mideleg] & ~mask) | (val & mask);
|
||||||
return iss::Ok;
|
return iss::Ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename BASE, features_e FEAT> iss::status riscv_hart_mu_p<BASE, FEAT>::write_edeleg(unsigned addr, reg_t val) {
|
template <typename BASE, features_e FEAT, typename LOGCAT> iss::status riscv_hart_mu_p<BASE, FEAT, LOGCAT>::write_edeleg(unsigned addr, reg_t val) {
|
||||||
auto mask = 0b1011001111110111; // bit 14/10 (reserved), bit 11 (Env call), and 3 (break) are hardwired to 0
|
auto mask = 0b1011001111110111; // bit 14/10 (reserved), bit 11 (Env call), and 3 (break) are hardwired to 0
|
||||||
csr[medeleg] = (csr[medeleg] & ~mask) | (val & mask);
|
csr[medeleg] = (csr[medeleg] & ~mask) | (val & mask);
|
||||||
return iss::Ok;
|
return iss::Ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename BASE, features_e FEAT> iss::status riscv_hart_mu_p<BASE, FEAT>::write_epc(unsigned addr, reg_t val) {
|
template <typename BASE, features_e FEAT, typename LOGCAT> iss::status riscv_hart_mu_p<BASE, FEAT, LOGCAT>::write_epc(unsigned addr, reg_t val) {
|
||||||
csr[addr] = val & get_pc_mask();
|
csr[addr] = val & get_pc_mask();
|
||||||
return iss::Ok;
|
return iss::Ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename BASE, features_e FEAT> iss::status riscv_hart_mu_p<BASE, FEAT>::write_dcsr_dcsr(unsigned addr, reg_t val) {
|
template <typename BASE, features_e FEAT, typename LOGCAT> iss::status riscv_hart_mu_p<BASE, FEAT, LOGCAT>::write_dcsr_dcsr(unsigned addr, reg_t val) {
|
||||||
if(!debug_mode_active())
|
if(!debug_mode_active())
|
||||||
throw illegal_instruction_fault(this->fault_data);
|
throw illegal_instruction_fault(this->fault_data);
|
||||||
// +-------------- ebreakm
|
// +-------------- ebreakm
|
||||||
|
@ -1257,35 +1257,35 @@ template <typename BASE, features_e FEAT> iss::status riscv_hart_mu_p<BASE, FEAT
|
||||||
return iss::Ok;
|
return iss::Ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename BASE, features_e FEAT> iss::status riscv_hart_mu_p<BASE, FEAT>::read_dcsr_reg(unsigned addr, reg_t& val) {
|
template <typename BASE, features_e FEAT, typename LOGCAT> iss::status riscv_hart_mu_p<BASE, FEAT, LOGCAT>::read_dcsr_reg(unsigned addr, reg_t& val) {
|
||||||
if(!debug_mode_active())
|
if(!debug_mode_active())
|
||||||
throw illegal_instruction_fault(this->fault_data);
|
throw illegal_instruction_fault(this->fault_data);
|
||||||
val = csr[addr];
|
val = csr[addr];
|
||||||
return iss::Ok;
|
return iss::Ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename BASE, features_e FEAT> iss::status riscv_hart_mu_p<BASE, FEAT>::write_dcsr_reg(unsigned addr, reg_t val) {
|
template <typename BASE, features_e FEAT, typename LOGCAT> iss::status riscv_hart_mu_p<BASE, FEAT, LOGCAT>::write_dcsr_reg(unsigned addr, reg_t val) {
|
||||||
if(!debug_mode_active())
|
if(!debug_mode_active())
|
||||||
throw illegal_instruction_fault(this->fault_data);
|
throw illegal_instruction_fault(this->fault_data);
|
||||||
csr[addr] = val;
|
csr[addr] = val;
|
||||||
return iss::Ok;
|
return iss::Ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename BASE, features_e FEAT> iss::status riscv_hart_mu_p<BASE, FEAT>::read_dpc_reg(unsigned addr, reg_t& val) {
|
template <typename BASE, features_e FEAT, typename LOGCAT> iss::status riscv_hart_mu_p<BASE, FEAT, LOGCAT>::read_dpc_reg(unsigned addr, reg_t& val) {
|
||||||
if(!debug_mode_active())
|
if(!debug_mode_active())
|
||||||
throw illegal_instruction_fault(this->fault_data);
|
throw illegal_instruction_fault(this->fault_data);
|
||||||
val = this->reg.DPC;
|
val = this->reg.DPC;
|
||||||
return iss::Ok;
|
return iss::Ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename BASE, features_e FEAT> iss::status riscv_hart_mu_p<BASE, FEAT>::write_dpc_reg(unsigned addr, reg_t val) {
|
template <typename BASE, features_e FEAT, typename LOGCAT> iss::status riscv_hart_mu_p<BASE, FEAT, LOGCAT>::write_dpc_reg(unsigned addr, reg_t val) {
|
||||||
if(!debug_mode_active())
|
if(!debug_mode_active())
|
||||||
throw illegal_instruction_fault(this->fault_data);
|
throw illegal_instruction_fault(this->fault_data);
|
||||||
this->reg.DPC = val;
|
this->reg.DPC = val;
|
||||||
return iss::Ok;
|
return iss::Ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename BASE, features_e FEAT> iss::status riscv_hart_mu_p<BASE, FEAT>::read_intstatus(unsigned addr, reg_t& val) {
|
template <typename BASE, features_e FEAT, typename LOGCAT> iss::status riscv_hart_mu_p<BASE, FEAT, LOGCAT>::read_intstatus(unsigned addr, reg_t& val) {
|
||||||
auto mode = (addr >> 8) & 0x3;
|
auto mode = (addr >> 8) & 0x3;
|
||||||
val = clic_uact_lvl & 0xff;
|
val = clic_uact_lvl & 0xff;
|
||||||
if(mode == 0x3)
|
if(mode == 0x3)
|
||||||
|
@ -1293,18 +1293,18 @@ template <typename BASE, features_e FEAT> iss::status riscv_hart_mu_p<BASE, FEAT
|
||||||
return iss::Ok;
|
return iss::Ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename BASE, features_e FEAT> iss::status riscv_hart_mu_p<BASE, FEAT>::write_intthresh(unsigned addr, reg_t val) {
|
template <typename BASE, features_e FEAT, typename LOGCAT> iss::status riscv_hart_mu_p<BASE, FEAT, LOGCAT>::write_intthresh(unsigned addr, reg_t val) {
|
||||||
csr[addr] = (val & 0xff) | (1 << (cfg.clic_int_ctl_bits)) - 1;
|
csr[addr] = (val & 0xff) | (1 << (cfg.clic_int_ctl_bits)) - 1;
|
||||||
return iss::Ok;
|
return iss::Ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename BASE, features_e FEAT> iss::status riscv_hart_mu_p<BASE, FEAT>::write_xtvt(unsigned addr, reg_t val) {
|
template <typename BASE, features_e FEAT, typename LOGCAT> iss::status riscv_hart_mu_p<BASE, FEAT, LOGCAT>::write_xtvt(unsigned addr, reg_t val) {
|
||||||
csr[addr] = val & ~0x3fULL;
|
csr[addr] = val & ~0x3fULL;
|
||||||
return iss::Ok;
|
return iss::Ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename BASE, features_e FEAT>
|
template <typename BASE, features_e FEAT, typename LOGCAT>
|
||||||
iss::status riscv_hart_mu_p<BASE, FEAT>::read_mem(phys_addr_t paddr, unsigned length, uint8_t* const data) {
|
iss::status riscv_hart_mu_p<BASE, FEAT, LOGCAT>::read_mem(phys_addr_t paddr, unsigned length, uint8_t* const data) {
|
||||||
switch(paddr.val) {
|
switch(paddr.val) {
|
||||||
default: {
|
default: {
|
||||||
for(auto offs = 0U; offs < length; ++offs) {
|
for(auto offs = 0U; offs < length; ++offs) {
|
||||||
|
@ -1315,8 +1315,8 @@ iss::status riscv_hart_mu_p<BASE, FEAT>::read_mem(phys_addr_t paddr, unsigned le
|
||||||
return iss::Ok;
|
return iss::Ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename BASE, features_e FEAT>
|
template <typename BASE, features_e FEAT, typename LOGCAT>
|
||||||
iss::status riscv_hart_mu_p<BASE, FEAT>::write_mem(phys_addr_t paddr, unsigned length, const uint8_t* const data) {
|
iss::status riscv_hart_mu_p<BASE, FEAT, LOGCAT>::write_mem(phys_addr_t paddr, unsigned length, const uint8_t* const data) {
|
||||||
switch(paddr.val) {
|
switch(paddr.val) {
|
||||||
// TODO remove UART, Peripherals should not be part of the ISS
|
// TODO remove UART, Peripherals should not be part of the ISS
|
||||||
case 0xFFFF0000: // UART0 base, TXFIFO reg
|
case 0xFFFF0000: // UART0 base, TXFIFO reg
|
||||||
|
@ -1377,8 +1377,8 @@ iss::status riscv_hart_mu_p<BASE, FEAT>::write_mem(phys_addr_t paddr, unsigned l
|
||||||
return iss::Ok;
|
return iss::Ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename BASE, features_e FEAT>
|
template <typename BASE, features_e FEAT, typename LOGCAT>
|
||||||
iss::status riscv_hart_mu_p<BASE, FEAT>::read_clic(uint64_t addr, unsigned length, uint8_t* const data) {
|
iss::status riscv_hart_mu_p<BASE, FEAT, LOGCAT>::read_clic(uint64_t addr, unsigned length, uint8_t* const data) {
|
||||||
if(addr == cfg.clic_base) { // cliccfg
|
if(addr == cfg.clic_base) { // cliccfg
|
||||||
*data = clic_cfg_reg;
|
*data = clic_cfg_reg;
|
||||||
for(auto i = 1; i < length; ++i)
|
for(auto i = 1; i < length; ++i)
|
||||||
|
@ -1397,8 +1397,8 @@ iss::status riscv_hart_mu_p<BASE, FEAT>::read_clic(uint64_t addr, unsigned lengt
|
||||||
return iss::Ok;
|
return iss::Ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename BASE, features_e FEAT>
|
template <typename BASE, features_e FEAT, typename LOGCAT>
|
||||||
iss::status riscv_hart_mu_p<BASE, FEAT>::write_clic(uint64_t addr, unsigned length, const uint8_t* const data) {
|
iss::status riscv_hart_mu_p<BASE, FEAT, LOGCAT>::write_clic(uint64_t addr, unsigned length, const uint8_t* const data) {
|
||||||
if(addr == cfg.clic_base) { // cliccfg
|
if(addr == cfg.clic_base) { // cliccfg
|
||||||
clic_cfg_reg = (clic_cfg_reg & ~0x1e) | (*data & 0x1e);
|
clic_cfg_reg = (clic_cfg_reg & ~0x1e) | (*data & 0x1e);
|
||||||
} else if(addr >= (cfg.clic_base + 0x40) && (addr + length) <= (cfg.clic_base + 0x40 + cfg.clic_num_trigger * 4)) { // clicinttrig
|
} else if(addr >= (cfg.clic_base + 0x40) && (addr + length) <= (cfg.clic_base + 0x40 + cfg.clic_num_trigger * 4)) { // clicinttrig
|
||||||
|
@ -1413,12 +1413,12 @@ iss::status riscv_hart_mu_p<BASE, FEAT>::write_clic(uint64_t addr, unsigned leng
|
||||||
return iss::Ok;
|
return iss::Ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename BASE, features_e FEAT> inline void riscv_hart_mu_p<BASE, FEAT>::reset(uint64_t address) {
|
template <typename BASE, features_e FEAT, typename LOGCAT> inline void riscv_hart_mu_p<BASE, FEAT, LOGCAT>::reset(uint64_t address) {
|
||||||
BASE::reset(address);
|
BASE::reset(address);
|
||||||
state.mstatus = hart_state_type::mstatus_reset_val;
|
state.mstatus = hart_state_type::mstatus_reset_val;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename BASE, features_e FEAT> void riscv_hart_mu_p<BASE, FEAT>::check_interrupt() {
|
template <typename BASE, features_e FEAT, typename LOGCAT> void riscv_hart_mu_p<BASE, FEAT, LOGCAT>::check_interrupt() {
|
||||||
// TODO: Implement CLIC functionality
|
// TODO: Implement CLIC functionality
|
||||||
auto ideleg = csr[mideleg];
|
auto ideleg = csr[mideleg];
|
||||||
// Multiple simultaneous interrupts and traps at the same privilege level are
|
// Multiple simultaneous interrupts and traps at the same privilege level are
|
||||||
|
@ -1441,7 +1441,7 @@ template <typename BASE, features_e FEAT> void riscv_hart_mu_p<BASE, FEAT>::chec
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename BASE, features_e FEAT> uint64_t riscv_hart_mu_p<BASE, FEAT>::enter_trap(uint64_t flags, uint64_t addr, uint64_t instr) {
|
template <typename BASE, features_e FEAT, typename LOGCAT> uint64_t riscv_hart_mu_p<BASE, FEAT, LOGCAT>::enter_trap(uint64_t flags, uint64_t addr, uint64_t instr) {
|
||||||
// flags are ACTIVE[31:31], CAUSE[30:16], TRAPID[15:0]
|
// flags are ACTIVE[31:31], CAUSE[30:16], TRAPID[15:0]
|
||||||
// calculate and write mcause val
|
// calculate and write mcause val
|
||||||
if(flags == std::numeric_limits<uint64_t>::max())
|
if(flags == std::numeric_limits<uint64_t>::max())
|
||||||
|
@ -1575,7 +1575,7 @@ template <typename BASE, features_e FEAT> uint64_t riscv_hart_mu_p<BASE, FEAT>::
|
||||||
return this->reg.NEXT_PC;
|
return this->reg.NEXT_PC;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename BASE, features_e FEAT> uint64_t riscv_hart_mu_p<BASE, FEAT>::leave_trap(uint64_t flags) {
|
template <typename BASE, features_e FEAT, typename LOGCAT> uint64_t riscv_hart_mu_p<BASE, FEAT, LOGCAT>::leave_trap(uint64_t flags) {
|
||||||
auto cur_priv = this->reg.PRIV;
|
auto cur_priv = this->reg.PRIV;
|
||||||
auto inst_priv = (flags & 0x3) ? 3 : 0;
|
auto inst_priv = (flags & 0x3) ? 3 : 0;
|
||||||
if(inst_priv > cur_priv) {
|
if(inst_priv > cur_priv) {
|
||||||
|
|
Loading…
Reference in New Issue