fixes FCSR behavior if no floating point is implemented

This commit is contained in:
Eyck Jentzsch 2024-08-02 08:59:22 +02:00
parent c376e34b2b
commit 42efced1eb
3 changed files with 129 additions and 106 deletions

View File

@ -377,8 +377,8 @@ protected:
std::vector<uint8_t> tcm; std::vector<uint8_t> tcm;
iss::status read_csr_reg(unsigned addr, reg_t& val); iss::status read_plain(unsigned addr, reg_t& val);
iss::status write_csr_reg(unsigned addr, reg_t val); iss::status write_plain(unsigned addr, reg_t val);
iss::status read_null(unsigned addr, reg_t& val); iss::status read_null(unsigned addr, reg_t& val);
iss::status write_null(unsigned addr, reg_t val) { return iss::status::Ok; } iss::status write_null(unsigned addr, reg_t val) { return iss::status::Ok; }
iss::status read_cycle(unsigned addr, reg_t& val); iss::status read_cycle(unsigned addr, reg_t& val);
@ -399,17 +399,19 @@ protected:
iss::status read_intstatus(unsigned addr, reg_t& val); iss::status read_intstatus(unsigned addr, reg_t& val);
iss::status write_intthresh(unsigned addr, reg_t val); iss::status write_intthresh(unsigned addr, reg_t val);
iss::status write_xtvt(unsigned addr, reg_t val); iss::status write_xtvt(unsigned addr, reg_t val);
iss::status write_dcsr_dcsr(unsigned addr, reg_t val); iss::status write_dcsr(unsigned addr, reg_t val);
iss::status read_dcsr_reg(unsigned addr, reg_t& val); iss::status read_debug(unsigned addr, reg_t& val);
iss::status write_dcsr_reg(unsigned addr, reg_t val); iss::status write_dscratch(unsigned addr, reg_t val);
iss::status read_dpc_reg(unsigned addr, reg_t& val); iss::status read_dpc(unsigned addr, reg_t& val);
iss::status write_dpc_reg(unsigned addr, reg_t val); iss::status write_dpc(unsigned addr, reg_t val);
iss::status read_fcsr(unsigned addr, reg_t& val);
iss::status write_fcsr(unsigned addr, reg_t val);
virtual iss::status read_custom_csr_reg(unsigned addr, reg_t& val) { return iss::status::Err; }; virtual iss::status read_custom_csr(unsigned addr, reg_t& val) { return iss::status::Err; };
virtual iss::status write_custom_csr_reg(unsigned addr, reg_t val) { return iss::status::Err; }; virtual iss::status write_custom_csr(unsigned addr, reg_t val) { return iss::status::Err; };
void register_custom_csr_rd(unsigned addr) { csr_rd_cb[addr] = &this_class::read_custom_csr_reg; } void register_custom_csr_rd(unsigned addr) { csr_rd_cb[addr] = &this_class::read_custom_csr; }
void register_custom_csr_wr(unsigned addr) { csr_wr_cb[addr] = &this_class::write_custom_csr_reg; } void register_custom_csr_wr(unsigned addr) { csr_wr_cb[addr] = &this_class::write_custom_csr; }
reg_t mhartid_reg{0x0}; reg_t mhartid_reg{0x0};
@ -446,18 +448,21 @@ riscv_hart_m_p<BASE, FEAT, LOGCAT>::riscv_hart_m_p(feature_config cfg)
csr[mimpid] = 1; csr[mimpid] = 1;
uart_buf.str(""); uart_buf.str("");
if(traits<BASE>::FLEN > 0)
csr_rd_cb[fcsr] = &this_class::read_fcsr;
csr_wr_cb[fcsr] = &this_class::write_fcsr;
for(unsigned addr = mhpmcounter3; addr <= mhpmcounter31; ++addr) { for(unsigned addr = mhpmcounter3; addr <= mhpmcounter31; ++addr) {
csr_rd_cb[addr] = &this_class::read_null; csr_rd_cb[addr] = &this_class::read_null;
csr_wr_cb[addr] = &this_class::write_csr_reg; csr_wr_cb[addr] = &this_class::write_plain;
} }
if(traits<BASE>::XLEN == 32) if(traits<BASE>::XLEN == 32)
for(unsigned addr = mhpmcounter3h; addr <= mhpmcounter31h; ++addr) { for(unsigned addr = mhpmcounter3h; addr <= mhpmcounter31h; ++addr) {
csr_rd_cb[addr] = &this_class::read_null; csr_rd_cb[addr] = &this_class::read_null;
csr_wr_cb[addr] = &this_class::write_csr_reg; csr_wr_cb[addr] = &this_class::write_plain;
} }
for(unsigned addr = mhpmevent3; addr <= mhpmevent31; ++addr) { for(unsigned addr = mhpmevent3; addr <= mhpmevent31; ++addr) {
csr_rd_cb[addr] = &this_class::read_null; csr_rd_cb[addr] = &this_class::read_null;
csr_wr_cb[addr] = &this_class::write_csr_reg; csr_wr_cb[addr] = &this_class::write_plain;
} }
for(unsigned addr = hpmcounter3; addr <= hpmcounter31; ++addr) { for(unsigned addr = hpmcounter3; addr <= hpmcounter31; ++addr) {
csr_rd_cb[addr] = &this_class::read_null; csr_rd_cb[addr] = &this_class::read_null;
@ -465,18 +470,17 @@ riscv_hart_m_p<BASE, FEAT, LOGCAT>::riscv_hart_m_p(feature_config cfg)
if(traits<BASE>::XLEN == 32) if(traits<BASE>::XLEN == 32)
for(unsigned addr = hpmcounter3h; addr <= hpmcounter31h; ++addr) { for(unsigned addr = hpmcounter3h; addr <= hpmcounter31h; ++addr) {
csr_rd_cb[addr] = &this_class::read_null; csr_rd_cb[addr] = &this_class::read_null;
// csr_wr_cb[addr] = &this_class::write_csr_reg;
} }
// common regs // common regs
const std::array<unsigned, 4> roaddrs{{misa, mvendorid, marchid, mimpid}}; const std::array<unsigned, 4> roaddrs{{misa, mvendorid, marchid, mimpid}};
for(auto addr : roaddrs) { for(auto addr : roaddrs) {
csr_rd_cb[addr] = &this_class::read_csr_reg; csr_rd_cb[addr] = &this_class::read_plain;
csr_wr_cb[addr] = &this_class::write_null; csr_wr_cb[addr] = &this_class::write_null;
} }
const std::array<unsigned, 4> rwaddrs{{mepc, mtvec, mscratch, mtval}}; const std::array<unsigned, 4> rwaddrs{{mepc, mtvec, mscratch, mtval}};
for(auto addr : rwaddrs) { for(auto addr : rwaddrs) {
csr_rd_cb[addr] = &this_class::read_csr_reg; csr_rd_cb[addr] = &this_class::read_plain;
csr_wr_cb[addr] = &this_class::write_csr_reg; csr_wr_cb[addr] = &this_class::write_plain;
} }
// special handling & overrides // special handling & overrides
csr_rd_cb[time] = &this_class::read_time; csr_rd_cb[time] = &this_class::read_time;
@ -517,7 +521,7 @@ riscv_hart_m_p<BASE, FEAT, LOGCAT>::riscv_hart_m_p(feature_config cfg)
csr_wr_cb[marchid] = &this_class::write_null; csr_wr_cb[marchid] = &this_class::write_null;
csr_wr_cb[mimpid] = &this_class::write_null; csr_wr_cb[mimpid] = &this_class::write_null;
if(FEAT & FEAT_CLIC) { if(FEAT & FEAT_CLIC) {
csr_rd_cb[mtvt] = &this_class::read_csr_reg; csr_rd_cb[mtvt] = &this_class::read_plain;
csr_wr_cb[mtvt] = &this_class::write_xtvt; csr_wr_cb[mtvt] = &this_class::write_xtvt;
// csr_rd_cb[mxnti] = &this_class::read_csr_reg; // csr_rd_cb[mxnti] = &this_class::read_csr_reg;
// csr_wr_cb[mxnti] = &this_class::write_csr_reg; // csr_wr_cb[mxnti] = &this_class::write_csr_reg;
@ -527,7 +531,7 @@ riscv_hart_m_p<BASE, FEAT, LOGCAT>::riscv_hart_m_p(feature_config cfg)
// csr_wr_cb[mscratchcsw] = &this_class::write_csr_reg; // csr_wr_cb[mscratchcsw] = &this_class::write_csr_reg;
// csr_rd_cb[mscratchcswl] = &this_class::read_csr_reg; // csr_rd_cb[mscratchcswl] = &this_class::read_csr_reg;
// csr_wr_cb[mscratchcswl] = &this_class::write_csr_reg; // csr_wr_cb[mscratchcswl] = &this_class::write_csr_reg;
csr_rd_cb[mintthresh] = &this_class::read_csr_reg; csr_rd_cb[mintthresh] = &this_class::read_plain;
csr_wr_cb[mintthresh] = &this_class::write_intthresh; csr_wr_cb[mintthresh] = &this_class::write_intthresh;
clic_int_reg.resize(cfg.clic_num_irq, clic_int_reg_t{.raw = 0}); clic_int_reg.resize(cfg.clic_num_irq, clic_int_reg_t{.raw = 0});
clic_cfg_reg = 0x20; clic_cfg_reg = 0x20;
@ -553,14 +557,14 @@ riscv_hart_m_p<BASE, FEAT, LOGCAT>::riscv_hart_m_p(feature_config cfg)
insert_mem_range(cfg.tcm_base, cfg.tcm_size, read_clic_cb, write_clic_cb); insert_mem_range(cfg.tcm_base, cfg.tcm_size, read_clic_cb, write_clic_cb);
} }
if(FEAT & FEAT_DEBUG) { if(FEAT & FEAT_DEBUG) {
csr_wr_cb[dscratch0] = &this_class::write_dcsr_reg; csr_wr_cb[dscratch0] = &this_class::write_dscratch;
csr_rd_cb[dscratch0] = &this_class::read_dcsr_reg; csr_rd_cb[dscratch0] = &this_class::read_debug;
csr_wr_cb[dscratch1] = &this_class::write_dcsr_reg; csr_wr_cb[dscratch1] = &this_class::write_dscratch;
csr_rd_cb[dscratch1] = &this_class::read_dcsr_reg; csr_rd_cb[dscratch1] = &this_class::read_debug;
csr_wr_cb[dpc] = &this_class::write_dpc_reg; csr_wr_cb[dpc] = &this_class::write_dpc;
csr_rd_cb[dpc] = &this_class::read_dpc_reg; csr_rd_cb[dpc] = &this_class::read_dpc;
csr_wr_cb[dcsr] = &this_class::write_dcsr_dcsr; csr_wr_cb[dcsr] = &this_class::write_dcsr;
csr_rd_cb[dcsr] = &this_class::read_dcsr_reg; csr_rd_cb[dcsr] = &this_class::read_debug;
} }
hart_mem_rd_delegate = [this](phys_addr_t a, unsigned l, uint8_t* const d) -> iss::status { return this->read_mem(a, l, d); }; hart_mem_rd_delegate = [this](phys_addr_t a, unsigned l, uint8_t* const d) -> iss::status { return this->read_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); }; 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); };
@ -665,7 +669,7 @@ iss::status riscv_hart_m_p<BASE, FEAT, LOGCAT>::read(const address_type type, co
} }
phys_addr_t phys_addr{access, space, addr}; phys_addr_t phys_addr{access, space, addr};
auto res = iss::Err; auto res = iss::Err;
if(access != access_type::FETCH && memfn_range.size()) { if(!is_fetch(access) && memfn_range.size()) {
auto it = auto it =
std::find_if(std::begin(memfn_range), std::end(memfn_range), [phys_addr](std::tuple<uint64_t, uint64_t> const& a) { std::find_if(std::begin(memfn_range), std::end(memfn_range), [phys_addr](std::tuple<uint64_t, uint64_t> const& a) {
return std::get<0>(a) <= phys_addr.val && (std::get<0>(a) + std::get<1>(a)) > phys_addr.val; return std::get<0>(a) <= phys_addr.val && (std::get<0>(a) + std::get<1>(a)) > phys_addr.val;
@ -692,11 +696,6 @@ iss::status riscv_hart_m_p<BASE, FEAT, LOGCAT>::read(const address_type type, co
case traits<BASE>::CSR: { case traits<BASE>::CSR: {
if(length != sizeof(reg_t)) if(length != sizeof(reg_t))
return iss::Err; return iss::Err;
// We emulate the FCSR in the architectural state
if(addr == 3) {
*data = this->get_fcsr();
return iss::Ok;
}
return read_csr(addr, *reinterpret_cast<reg_t* const>(data)); return read_csr(addr, *reinterpret_cast<reg_t* const>(data));
} break; } break;
case traits<BASE>::FENCE: { case traits<BASE>::FENCE: {
@ -767,7 +766,7 @@ iss::status riscv_hart_m_p<BASE, FEAT, LOGCAT>::write(const address_type type, c
} }
phys_addr_t phys_addr{access, space, addr}; phys_addr_t phys_addr{access, space, addr};
auto res = iss::Err; auto res = iss::Err;
if(access != access_type::FETCH && memfn_range.size()) { if(!is_fetch(access) && memfn_range.size()) {
auto it = auto it =
std::find_if(std::begin(memfn_range), std::end(memfn_range), [phys_addr](std::tuple<uint64_t, uint64_t> const& a) { std::find_if(std::begin(memfn_range), std::end(memfn_range), [phys_addr](std::tuple<uint64_t, uint64_t> const& a) {
return std::get<0>(a) <= phys_addr.val && (std::get<0>(a) + std::get<1>(a)) > phys_addr.val; return std::get<0>(a) <= phys_addr.val && (std::get<0>(a) + std::get<1>(a)) > phys_addr.val;
@ -798,8 +797,6 @@ iss::status riscv_hart_m_p<BASE, FEAT, LOGCAT>::write(const address_type type, c
case 0x10023000: // UART1 base, TXFIFO reg case 0x10023000: // UART1 base, TXFIFO reg
uart_buf << (char)data[0]; uart_buf << (char)data[0];
if(((char)data[0]) == '\n' || data[0] == 0) { if(((char)data[0]) == '\n' || data[0] == 0) {
// CPPLOG(INFO)<<"UART"<<((paddr.val>>16)&0x3)<<" send
// '"<<uart_buf.str()<<"'";
std::cout << uart_buf.str(); std::cout << uart_buf.str();
uart_buf.str(""); uart_buf.str("");
} }
@ -828,11 +825,6 @@ iss::status riscv_hart_m_p<BASE, FEAT, LOGCAT>::write(const address_type type, c
case traits<BASE>::CSR: { case traits<BASE>::CSR: {
if(length != sizeof(reg_t)) if(length != sizeof(reg_t))
return iss::Err; return iss::Err;
// We emulate the FCSR in the architectural state
if(addr == 3) {
this->set_fcsr(*data);
return iss::Ok;
}
return write_csr(addr, *reinterpret_cast<const reg_t*>(data)); return write_csr(addr, *reinterpret_cast<const reg_t*>(data));
} break; } break;
case traits<BASE>::FENCE: { case traits<BASE>::FENCE: {
@ -889,12 +881,6 @@ iss::status riscv_hart_m_p<BASE, FEAT, LOGCAT>::write_csr(unsigned addr, reg_t v
return (this->*(it->second))(addr, val); return (this->*(it->second))(addr, 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];
return iss::Ok;
}
template <typename BASE, features_e FEAT, typename LOGCAT> template <typename BASE, features_e FEAT, typename LOGCAT>
iss::status riscv_hart_m_p<BASE, FEAT, LOGCAT>::read_null(unsigned addr, reg_t& val) { iss::status riscv_hart_m_p<BASE, FEAT, LOGCAT>::read_null(unsigned addr, reg_t& val) {
val = 0; val = 0;
@ -902,7 +888,13 @@ iss::status riscv_hart_m_p<BASE, FEAT, LOGCAT>::read_null(unsigned addr, reg_t&
} }
template <typename BASE, features_e FEAT, typename LOGCAT> 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) { iss::status riscv_hart_m_p<BASE, FEAT, LOGCAT>::read_plain(unsigned addr, reg_t& val) {
val = csr[addr];
return iss::Ok;
}
template <typename BASE, features_e FEAT, typename LOGCAT>
iss::status riscv_hart_m_p<BASE, FEAT, LOGCAT>::write_plain(unsigned addr, reg_t val) {
csr[addr] = val; csr[addr] = val;
return iss::Ok; return iss::Ok;
} }
@ -1052,7 +1044,7 @@ iss::status riscv_hart_m_p<BASE, FEAT, LOGCAT>::write_epc(unsigned addr, reg_t v
} }
template <typename BASE, features_e FEAT, typename LOGCAT> 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) { iss::status riscv_hart_m_p<BASE, FEAT, LOGCAT>::write_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
@ -1064,7 +1056,7 @@ iss::status riscv_hart_m_p<BASE, FEAT, LOGCAT>::write_dcsr_dcsr(unsigned addr, r
} }
template <typename BASE, features_e FEAT, typename LOGCAT> 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) { iss::status riscv_hart_m_p<BASE, FEAT, LOGCAT>::read_debug(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];
@ -1072,7 +1064,7 @@ iss::status riscv_hart_m_p<BASE, FEAT, LOGCAT>::read_dcsr_reg(unsigned addr, reg
} }
template <typename BASE, features_e FEAT, typename LOGCAT> 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) { iss::status riscv_hart_m_p<BASE, FEAT, LOGCAT>::write_dscratch(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;
@ -1080,7 +1072,7 @@ iss::status riscv_hart_m_p<BASE, FEAT, LOGCAT>::write_dcsr_reg(unsigned addr, re
} }
template <typename BASE, features_e FEAT, typename LOGCAT> 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) { iss::status riscv_hart_m_p<BASE, FEAT, LOGCAT>::read_dpc(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;
@ -1088,7 +1080,7 @@ iss::status riscv_hart_m_p<BASE, FEAT, LOGCAT>::read_dpc_reg(unsigned addr, reg_
} }
template <typename BASE, features_e FEAT, typename LOGCAT> 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) { iss::status riscv_hart_m_p<BASE, FEAT, LOGCAT>::write_dpc(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;
@ -1101,6 +1093,18 @@ iss::status riscv_hart_m_p<BASE, FEAT, LOGCAT>::read_intstatus(unsigned addr, re
return iss::Ok; return iss::Ok;
} }
template <typename BASE, features_e FEAT, typename LOGCAT>
iss::status riscv_hart_m_p<BASE, FEAT, LOGCAT>::read_fcsr(unsigned addr, reg_t& val) {
val = this->get_fcsr();
return iss::Ok;
}
template <typename BASE, features_e FEAT, typename LOGCAT>
iss::status riscv_hart_m_p<BASE, FEAT, LOGCAT>::write_fcsr(unsigned addr, reg_t val) {
this->set_fcsr(val);
return iss::Ok;
}
template <typename BASE, features_e FEAT, typename LOGCAT> template <typename BASE, features_e FEAT, typename LOGCAT>
iss::status riscv_hart_m_p<BASE, FEAT, LOGCAT>::write_intthresh(unsigned addr, reg_t val) { 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;

View File

@ -39,7 +39,9 @@
#include "iss/instrumentation_if.h" #include "iss/instrumentation_if.h"
#include "iss/log_categories.h" #include "iss/log_categories.h"
#include "iss/vm_if.h" #include "iss/vm_if.h"
#include "iss/vm_types.h"
#include "riscv_hart_common.h" #include "riscv_hart_common.h"
#include <stdexcept>
#ifndef FMT_HEADER_ONLY #ifndef FMT_HEADER_ONLY
#define FMT_HEADER_ONLY #define FMT_HEADER_ONLY
#endif #endif

View File

@ -39,7 +39,9 @@
#include "iss/instrumentation_if.h" #include "iss/instrumentation_if.h"
#include "iss/log_categories.h" #include "iss/log_categories.h"
#include "iss/vm_if.h" #include "iss/vm_if.h"
#include "iss/vm_types.h"
#include "riscv_hart_common.h" #include "riscv_hart_common.h"
#include <stdexcept>
#ifndef FMT_HEADER_ONLY #ifndef FMT_HEADER_ONLY
#define FMT_HEADER_ONLY #define FMT_HEADER_ONLY
#endif #endif
@ -302,8 +304,8 @@ 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} [p:{};s:0x{:x};c:{}]", pc, instr, lvl[this->reg.PRIV], (reg_t)state.mstatus, NSCLOG(INFO, LOGCAT) << fmt::format("0x{:016x} {:40} [p:{};s:0x{:x};c:{}]", pc, instr, lvl[this->reg.PRIV], (reg_t)state.mstatus,
this->reg.icount + cycle_offset); this->reg.icount + cycle_offset);
}; };
iss::instrumentation_if* get_instrumentation_if() override { return &instr_if; } iss::instrumentation_if* get_instrumentation_if() override { return &instr_if; }
@ -402,8 +404,8 @@ protected:
std::vector<uint8_t> tcm; std::vector<uint8_t> tcm;
iss::status read_csr_reg(unsigned addr, reg_t& val); iss::status read_plain(unsigned addr, reg_t& val);
iss::status write_csr_reg(unsigned addr, reg_t val); iss::status write_plain(unsigned addr, reg_t val);
iss::status read_null(unsigned addr, reg_t& val); iss::status read_null(unsigned addr, reg_t& val);
iss::status write_null(unsigned addr, reg_t val) { return iss::status::Ok; } iss::status write_null(unsigned addr, reg_t val) { return iss::status::Ok; }
iss::status read_cycle(unsigned addr, reg_t& val); iss::status read_cycle(unsigned addr, reg_t& val);
@ -426,15 +428,17 @@ protected:
iss::status read_intstatus(unsigned addr, reg_t& val); iss::status read_intstatus(unsigned addr, reg_t& val);
iss::status write_intthresh(unsigned addr, reg_t val); iss::status write_intthresh(unsigned addr, reg_t val);
iss::status write_xtvt(unsigned addr, reg_t val); iss::status write_xtvt(unsigned addr, reg_t val);
iss::status write_dcsr_dcsr(unsigned addr, reg_t val); iss::status write_dcsr(unsigned addr, reg_t val);
iss::status read_dcsr_reg(unsigned addr, reg_t& val); iss::status read_debug(unsigned addr, reg_t& val);
iss::status write_dcsr_reg(unsigned addr, reg_t val); iss::status write_dscratch(unsigned addr, reg_t val);
iss::status read_dpc_reg(unsigned addr, reg_t& val); iss::status read_dpc(unsigned addr, reg_t& val);
iss::status write_dpc_reg(unsigned addr, reg_t val); iss::status write_dpc(unsigned addr, reg_t val);
iss::status write_pmpcfg_reg(unsigned addr, reg_t val); iss::status read_fcsr(unsigned addr, reg_t& val);
iss::status write_fcsr(unsigned addr, reg_t val);
iss::status write_pmpcfg(unsigned addr, reg_t val);
virtual iss::status read_custom_csr_reg(unsigned addr, reg_t& val) { return iss::status::Err; }; virtual iss::status read_custom_csr(unsigned addr, reg_t& val) { return iss::status::Err; };
virtual iss::status write_custom_csr_reg(unsigned addr, reg_t val) { return iss::status::Err; }; virtual iss::status write_custom_csr(unsigned addr, reg_t val) { return iss::status::Err; };
void register_custom_csr_rd(unsigned addr) { csr_rd_cb[addr] = &this_class::read_custom_csr_reg; } void register_custom_csr_rd(unsigned addr) { csr_rd_cb[addr] = &this_class::read_custom_csr_reg; }
void register_custom_csr_wr(unsigned addr) { csr_wr_cb[addr] = &this_class::write_custom_csr_reg; } void register_custom_csr_wr(unsigned addr) { csr_wr_cb[addr] = &this_class::write_custom_csr_reg; }
@ -474,18 +478,21 @@ riscv_hart_mu_p<BASE, FEAT, LOGCAT>::riscv_hart_mu_p(feature_config cfg)
csr[mimpid] = 1; csr[mimpid] = 1;
uart_buf.str(""); uart_buf.str("");
if(traits<BASE>::FLEN > 0)
csr_rd_cb[fcsr] = &this_class::read_fcsr;
csr_wr_cb[fcsr] = &this_class::write_fcsr;
for(unsigned addr = mhpmcounter3; addr <= mhpmcounter31; ++addr) { for(unsigned addr = mhpmcounter3; addr <= mhpmcounter31; ++addr) {
csr_rd_cb[addr] = &this_class::read_null; csr_rd_cb[addr] = &this_class::read_null;
csr_wr_cb[addr] = &this_class::write_csr_reg; csr_wr_cb[addr] = &this_class::write_plain;
} }
if(traits<BASE>::XLEN == 32) if(traits<BASE>::XLEN == 32)
for(unsigned addr = mhpmcounter3h; addr <= mhpmcounter31h; ++addr) { for(unsigned addr = mhpmcounter3h; addr <= mhpmcounter31h; ++addr) {
csr_rd_cb[addr] = &this_class::read_null; csr_rd_cb[addr] = &this_class::read_null;
csr_wr_cb[addr] = &this_class::write_csr_reg; csr_wr_cb[addr] = &this_class::write_plain;
} }
for(unsigned addr = mhpmevent3; addr <= mhpmevent31; ++addr) { for(unsigned addr = mhpmevent3; addr <= mhpmevent31; ++addr) {
csr_rd_cb[addr] = &this_class::read_null; csr_rd_cb[addr] = &this_class::read_null;
csr_wr_cb[addr] = &this_class::write_csr_reg; csr_wr_cb[addr] = &this_class::write_plain;
} }
for(unsigned addr = hpmcounter3; addr <= hpmcounter31; ++addr) { for(unsigned addr = hpmcounter3; addr <= hpmcounter31; ++addr) {
csr_rd_cb[addr] = &this_class::read_null; csr_rd_cb[addr] = &this_class::read_null;
@ -493,12 +500,11 @@ riscv_hart_mu_p<BASE, FEAT, LOGCAT>::riscv_hart_mu_p(feature_config cfg)
if(traits<BASE>::XLEN == 32) if(traits<BASE>::XLEN == 32)
for(unsigned addr = hpmcounter3h; addr <= hpmcounter31h; ++addr) { for(unsigned addr = hpmcounter3h; addr <= hpmcounter31h; ++addr) {
csr_rd_cb[addr] = &this_class::read_null; csr_rd_cb[addr] = &this_class::read_null;
// csr_wr_cb[addr] = &this_class::write_csr_reg;
} }
// common regs // common regs
const std::array<unsigned, 4> roaddrs{{misa, mvendorid, marchid, mimpid}}; const std::array<unsigned, 4> roaddrs{{misa, mvendorid, marchid, mimpid}};
for(auto addr : roaddrs) { for(auto addr : roaddrs) {
csr_rd_cb[addr] = &this_class::read_csr_reg; csr_rd_cb[addr] = &this_class::read_plain;
csr_wr_cb[addr] = &this_class::write_null; csr_wr_cb[addr] = &this_class::write_null;
} }
const std::array<unsigned, 8> rwaddrs{{ const std::array<unsigned, 8> rwaddrs{{
@ -512,8 +518,8 @@ riscv_hart_mu_p<BASE, FEAT, LOGCAT>::riscv_hart_mu_p(feature_config cfg)
utval, utval,
}}; }};
for(auto addr : rwaddrs) { for(auto addr : rwaddrs) {
csr_rd_cb[addr] = &this_class::read_csr_reg; csr_rd_cb[addr] = &this_class::read_plain;
csr_wr_cb[addr] = &this_class::write_csr_reg; csr_wr_cb[addr] = &this_class::write_plain;
} }
// special handling & overrides // special handling & overrides
csr_rd_cb[time] = &this_class::read_time; csr_rd_cb[time] = &this_class::read_time;
@ -558,18 +564,18 @@ riscv_hart_mu_p<BASE, FEAT, LOGCAT>::riscv_hart_mu_p(feature_config cfg)
if(FEAT & FEAT_PMP) { if(FEAT & FEAT_PMP) {
for(size_t i = pmpaddr0; i <= pmpaddr15; ++i) { for(size_t i = pmpaddr0; i <= pmpaddr15; ++i) {
csr_rd_cb[i] = &this_class::read_csr_reg; csr_rd_cb[i] = &this_class::read_plain;
csr_wr_cb[i] = &this_class::write_csr_reg; csr_wr_cb[i] = &this_class::write_plain;
} }
for(size_t i = pmpcfg0; i < pmpcfg0 + 16 / sizeof(reg_t); ++i) { for(size_t i = pmpcfg0; i < pmpcfg0 + 16 / sizeof(reg_t); ++i) {
csr_rd_cb[i] = &this_class::read_csr_reg; csr_rd_cb[i] = &this_class::read_plain;
csr_wr_cb[i] = &this_class::write_pmpcfg_reg; csr_wr_cb[i] = &this_class::write_pmpcfg;
} }
} }
if(FEAT & FEAT_EXT_N) { if(FEAT & FEAT_EXT_N) {
csr_rd_cb[mideleg] = &this_class::read_csr_reg; csr_rd_cb[mideleg] = &this_class::read_plain;
csr_wr_cb[mideleg] = &this_class::write_ideleg; csr_wr_cb[mideleg] = &this_class::write_ideleg;
csr_rd_cb[medeleg] = &this_class::read_csr_reg; csr_rd_cb[medeleg] = &this_class::read_plain;
csr_wr_cb[medeleg] = &this_class::write_edeleg; csr_wr_cb[medeleg] = &this_class::write_edeleg;
csr_rd_cb[uie] = &this_class::read_ie; csr_rd_cb[uie] = &this_class::read_ie;
csr_wr_cb[uie] = &this_class::write_ie; csr_wr_cb[uie] = &this_class::write_ie;
@ -583,7 +589,7 @@ riscv_hart_mu_p<BASE, FEAT, LOGCAT>::riscv_hart_mu_p(feature_config cfg)
csr_rd_cb[utvec] = &this_class::read_tvec; csr_rd_cb[utvec] = &this_class::read_tvec;
} }
if(FEAT & FEAT_CLIC) { if(FEAT & FEAT_CLIC) {
csr_rd_cb[mtvt] = &this_class::read_csr_reg; csr_rd_cb[mtvt] = &this_class::read_plain;
csr_wr_cb[mtvt] = &this_class::write_xtvt; csr_wr_cb[mtvt] = &this_class::write_xtvt;
// csr_rd_cb[mxnti] = &this_class::read_csr_reg; // csr_rd_cb[mxnti] = &this_class::read_csr_reg;
// csr_wr_cb[mxnti] = &this_class::write_csr_reg; // csr_wr_cb[mxnti] = &this_class::write_csr_reg;
@ -593,14 +599,14 @@ riscv_hart_mu_p<BASE, FEAT, LOGCAT>::riscv_hart_mu_p(feature_config cfg)
// csr_wr_cb[mscratchcsw] = &this_class::write_csr_reg; // csr_wr_cb[mscratchcsw] = &this_class::write_csr_reg;
// csr_rd_cb[mscratchcswl] = &this_class::read_csr_reg; // csr_rd_cb[mscratchcswl] = &this_class::read_csr_reg;
// csr_wr_cb[mscratchcswl] = &this_class::write_csr_reg; // csr_wr_cb[mscratchcswl] = &this_class::write_csr_reg;
csr_rd_cb[mintthresh] = &this_class::read_csr_reg; csr_rd_cb[mintthresh] = &this_class::read_plain;
csr_wr_cb[mintthresh] = &this_class::write_intthresh; csr_wr_cb[mintthresh] = &this_class::write_intthresh;
if(FEAT & FEAT_EXT_N) { if(FEAT & FEAT_EXT_N) {
csr_rd_cb[utvt] = &this_class::read_csr_reg; csr_rd_cb[utvt] = &this_class::read_plain;
csr_wr_cb[utvt] = &this_class::write_xtvt; csr_wr_cb[utvt] = &this_class::write_xtvt;
csr_rd_cb[uintstatus] = &this_class::read_intstatus; csr_rd_cb[uintstatus] = &this_class::read_intstatus;
csr_wr_cb[uintstatus] = &this_class::write_null; csr_wr_cb[uintstatus] = &this_class::write_null;
csr_rd_cb[uintthresh] = &this_class::read_csr_reg; csr_rd_cb[uintthresh] = &this_class::read_plain;
csr_wr_cb[uintthresh] = &this_class::write_intthresh; csr_wr_cb[uintthresh] = &this_class::write_intthresh;
} }
clic_int_reg.resize(cfg.clic_num_irq, clic_int_reg_t{.raw = 0}); clic_int_reg.resize(cfg.clic_num_irq, clic_int_reg_t{.raw = 0});
@ -629,14 +635,14 @@ riscv_hart_mu_p<BASE, FEAT, LOGCAT>::riscv_hart_mu_p(feature_config cfg)
insert_mem_range(cfg.tcm_base, cfg.tcm_size, read_clic_cb, write_clic_cb); insert_mem_range(cfg.tcm_base, cfg.tcm_size, read_clic_cb, write_clic_cb);
} }
if(FEAT & FEAT_DEBUG) { if(FEAT & FEAT_DEBUG) {
csr_wr_cb[dscratch0] = &this_class::write_dcsr_reg; csr_wr_cb[dscratch0] = &this_class::write_dscratch;
csr_rd_cb[dscratch0] = &this_class::read_dcsr_reg; csr_rd_cb[dscratch0] = &this_class::read_debug;
csr_wr_cb[dscratch1] = &this_class::write_dcsr_reg; csr_wr_cb[dscratch1] = &this_class::write_dscratch;
csr_rd_cb[dscratch1] = &this_class::read_dcsr_reg; csr_rd_cb[dscratch1] = &this_class::read_debug;
csr_wr_cb[dpc] = &this_class::write_dpc_reg; csr_wr_cb[dpc] = &this_class::write_dpc;
csr_rd_cb[dpc] = &this_class::read_dpc_reg; csr_rd_cb[dpc] = &this_class::read_dpc;
csr_wr_cb[dcsr] = &this_class::write_dcsr_dcsr; csr_wr_cb[dcsr] = &this_class::write_dcsr;
csr_rd_cb[dcsr] = &this_class::read_dcsr_reg; csr_rd_cb[dcsr] = &this_class::read_debug;
} }
hart_mem_rd_delegate = [this](phys_addr_t a, unsigned l, uint8_t* const d) -> iss::status { return this->read_mem(a, l, d); }; hart_mem_rd_delegate = [this](phys_addr_t a, unsigned l, uint8_t* const d) -> iss::status { return this->read_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); }; 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); };
@ -725,7 +731,7 @@ inline void riscv_hart_mu_p<BASE, FEAT, LOGCAT>::insert_mem_range(uint64_t base,
} }
template <typename BASE, features_e FEAT, typename LOGCAT> 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) { inline iss::status riscv_hart_mu_p<BASE, FEAT, LOGCAT>::write_pmpcfg(unsigned addr, reg_t val) {
csr[addr] = val & 0x9f9f9f9f; csr[addr] = val & 0x9f9f9f9f;
return iss::Ok; return iss::Ok;
} }
@ -988,8 +994,6 @@ iss::status riscv_hart_mu_p<BASE, FEAT, LOGCAT>::write(const address_type type,
case 0x10023000: // UART1 base, TXFIFO reg case 0x10023000: // UART1 base, TXFIFO reg
uart_buf << (char)data[0]; uart_buf << (char)data[0];
if(((char)data[0]) == '\n' || data[0] == 0) { if(((char)data[0]) == '\n' || data[0] == 0) {
// CPPLOG(INFO)<<"UART"<<((addr>>16)&0x3)<<" send
// '"<<uart_buf.str()<<"'";
std::cout << uart_buf.str(); std::cout << uart_buf.str();
uart_buf.str(""); uart_buf.str("");
} }
@ -1074,12 +1078,6 @@ iss::status riscv_hart_mu_p<BASE, FEAT, LOGCAT>::write_csr(unsigned addr, reg_t
return (this->*(it->second))(addr, val); return (this->*(it->second))(addr, 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];
return iss::Ok;
}
template <typename BASE, features_e FEAT, typename LOGCAT> template <typename BASE, features_e FEAT, typename LOGCAT>
iss::status riscv_hart_mu_p<BASE, FEAT, LOGCAT>::read_null(unsigned addr, reg_t& val) { iss::status riscv_hart_mu_p<BASE, FEAT, LOGCAT>::read_null(unsigned addr, reg_t& val) {
val = 0; val = 0;
@ -1087,7 +1085,13 @@ iss::status riscv_hart_mu_p<BASE, FEAT, LOGCAT>::read_null(unsigned addr, reg_t&
} }
template <typename BASE, features_e FEAT, typename LOGCAT> 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) { iss::status riscv_hart_mu_p<BASE, FEAT, LOGCAT>::read_plain(unsigned addr, reg_t& val) {
val = csr[addr];
return iss::Ok;
}
template <typename BASE, features_e FEAT, typename LOGCAT>
iss::status riscv_hart_mu_p<BASE, FEAT, LOGCAT>::write_plain(unsigned addr, reg_t val) {
csr[addr] = val; csr[addr] = val;
return iss::Ok; return iss::Ok;
} }
@ -1161,6 +1165,7 @@ iss::status riscv_hart_mu_p<BASE, FEAT, LOGCAT>::read_tvec(unsigned addr, reg_t&
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, typename LOGCAT> template <typename BASE, features_e FEAT, typename LOGCAT>
iss::status riscv_hart_mu_p<BASE, FEAT, LOGCAT>::read_status(unsigned addr, reg_t& val) { 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);
@ -1272,7 +1277,7 @@ iss::status riscv_hart_mu_p<BASE, FEAT, LOGCAT>::write_epc(unsigned addr, reg_t
} }
template <typename BASE, features_e FEAT, typename LOGCAT> 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) { iss::status riscv_hart_mu_p<BASE, FEAT, LOGCAT>::write_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
@ -1284,7 +1289,7 @@ iss::status riscv_hart_mu_p<BASE, FEAT, LOGCAT>::write_dcsr_dcsr(unsigned addr,
} }
template <typename BASE, features_e FEAT, typename LOGCAT> 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) { iss::status riscv_hart_mu_p<BASE, FEAT, LOGCAT>::read_debug(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];
@ -1292,7 +1297,7 @@ iss::status riscv_hart_mu_p<BASE, FEAT, LOGCAT>::read_dcsr_reg(unsigned addr, re
} }
template <typename BASE, features_e FEAT, typename LOGCAT> 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) { iss::status riscv_hart_mu_p<BASE, FEAT, LOGCAT>::write_dscratch(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;
@ -1300,7 +1305,7 @@ iss::status riscv_hart_mu_p<BASE, FEAT, LOGCAT>::write_dcsr_reg(unsigned addr, r
} }
template <typename BASE, features_e FEAT, typename LOGCAT> 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) { iss::status riscv_hart_mu_p<BASE, FEAT, LOGCAT>::read_dpc(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;
@ -1308,7 +1313,7 @@ iss::status riscv_hart_mu_p<BASE, FEAT, LOGCAT>::read_dpc_reg(unsigned addr, reg
} }
template <typename BASE, features_e FEAT, typename LOGCAT> 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) { iss::status riscv_hart_mu_p<BASE, FEAT, LOGCAT>::write_dpc(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;
@ -1324,6 +1329,18 @@ iss::status riscv_hart_mu_p<BASE, FEAT, LOGCAT>::read_intstatus(unsigned addr, r
return iss::Ok; return iss::Ok;
} }
template <typename BASE, features_e FEAT, typename LOGCAT>
iss::status riscv_hart_mu_p<BASE, FEAT, LOGCAT>::read_fcsr(unsigned addr, reg_t& val) {
val = this->get_fcsr();
return iss::Ok;
}
template <typename BASE, features_e FEAT, typename LOGCAT>
iss::status riscv_hart_mu_p<BASE, FEAT, LOGCAT>::write_fcsr(unsigned addr, reg_t val) {
this->set_fcsr(val);
return iss::Ok;
}
template <typename BASE, features_e FEAT, typename LOGCAT> template <typename BASE, features_e FEAT, typename LOGCAT>
iss::status riscv_hart_mu_p<BASE, FEAT, LOGCAT>::write_intthresh(unsigned addr, reg_t val) { 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;