factors clic & pmp into separate units
This commit is contained in:
@@ -37,8 +37,9 @@
|
||||
|
||||
#include "iss/arch/traits.h"
|
||||
#include "iss/log_categories.h"
|
||||
#include "iss/memory/memory_if.h"
|
||||
#include "iss/mmio/memory_if.h"
|
||||
#include "iss/vm_types.h"
|
||||
#include "mstatus.h"
|
||||
#include "util/delegate.h"
|
||||
#include <array>
|
||||
#include <cstdint>
|
||||
@@ -51,7 +52,6 @@
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <util/ities.h>
|
||||
#include <util/logging.h>
|
||||
#include <util/sparse_array.h>
|
||||
|
||||
@@ -66,7 +66,7 @@
|
||||
namespace iss {
|
||||
namespace arch {
|
||||
|
||||
enum features_e { FEAT_NONE, FEAT_PMP = 1, FEAT_EXT_N = 2, FEAT_CLIC = 4, FEAT_DEBUG = 8, FEAT_TCM = 16 };
|
||||
enum features_e { FEAT_NONE, FEAT_EXT_N = 1, FEAT_DEBUG = 2 };
|
||||
|
||||
enum riscv_csr {
|
||||
/* user-level CSR */
|
||||
@@ -242,10 +242,6 @@ struct vm_info {
|
||||
};
|
||||
|
||||
struct feature_config {
|
||||
uint64_t clic_base{0xc0000000};
|
||||
unsigned clic_int_ctl_bits{4};
|
||||
unsigned clic_num_irq{16};
|
||||
unsigned clic_num_trigger{0};
|
||||
uint64_t tcm_base{0x10000000};
|
||||
uint64_t tcm_size{0x8000};
|
||||
uint64_t io_address{0xf0000000};
|
||||
@@ -278,56 +274,22 @@ public:
|
||||
: trap_access(15 << 16, badaddr) {}
|
||||
};
|
||||
|
||||
inline void read_reg_uint32(uint64_t offs, uint32_t& reg, uint8_t* const data, unsigned length) {
|
||||
auto reg_ptr = reinterpret_cast<uint8_t*>(®);
|
||||
switch(offs & 0x3) {
|
||||
case 0:
|
||||
for(auto i = 0U; i < length; ++i)
|
||||
*(data + i) = *(reg_ptr + i);
|
||||
break;
|
||||
case 1:
|
||||
for(auto i = 0U; i < length; ++i)
|
||||
*(data + i) = *(reg_ptr + 1 + i);
|
||||
break;
|
||||
case 2:
|
||||
for(auto i = 0U; i < length; ++i)
|
||||
*(data + i) = *(reg_ptr + 2 + i);
|
||||
break;
|
||||
case 3:
|
||||
*data = *(reg_ptr + 3);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
inline void write_reg_uint32(uint64_t offs, uint32_t& reg, const uint8_t* const data, unsigned length) {
|
||||
auto reg_ptr = reinterpret_cast<uint8_t*>(®);
|
||||
switch(offs & 0x3) {
|
||||
case 0:
|
||||
for(auto i = 0U; i < length; ++i)
|
||||
*(reg_ptr + i) = *(data + i);
|
||||
break;
|
||||
case 1:
|
||||
for(auto i = 0U; i < length; ++i)
|
||||
*(reg_ptr + 1 + i) = *(data + i);
|
||||
break;
|
||||
case 2:
|
||||
for(auto i = 0U; i < length; ++i)
|
||||
*(reg_ptr + 2 + i) = *(data + i);
|
||||
break;
|
||||
case 3:
|
||||
*(reg_ptr + 3) = *data;
|
||||
break;
|
||||
}
|
||||
}
|
||||
template <typename WORD_TYPE> struct priv_if {
|
||||
using rd_csr_f = std::function<iss::status(unsigned addr, WORD_TYPE&)>;
|
||||
using wr_csr_f = std::function<iss::status(unsigned addr, WORD_TYPE)>;
|
||||
|
||||
std::function<iss::status(unsigned, WORD_TYPE&)> read_csr;
|
||||
std::function<iss::status(unsigned, WORD_TYPE)> write_csr;
|
||||
std::function<iss::status(uint8_t const*)> exec_htif;
|
||||
std::unordered_map<unsigned, rd_csr_f>& csr_rd_cb;
|
||||
std::unordered_map<unsigned, wr_csr_f>& csr_wr_cb;
|
||||
hart_state<WORD_TYPE>& mstatus;
|
||||
uint64_t& tohost;
|
||||
uint64_t& fromhost;
|
||||
unsigned& mcause_max_irq;
|
||||
};
|
||||
|
||||
template <typename BASE, typename LOGCAT = logging::disass> struct riscv_hart_common : public BASE, public memory::memory_elem {
|
||||
template <typename BASE, typename LOGCAT = logging::disass> struct riscv_hart_common : public BASE, public mmio::memory_elem {
|
||||
const std::array<const char, 4> lvl = {{'U', 'S', 'H', 'M'}};
|
||||
const std::array<const char*, 16> trap_str = {{""
|
||||
"Instruction address misaligned", // 0
|
||||
@@ -365,7 +327,8 @@ template <typename BASE, typename LOGCAT = logging::disass> struct riscv_hart_co
|
||||
#define MK_CSR_WR_CB(FCT) [this](unsigned a, reg_t r) -> iss::status { return this->FCT(a, r); };
|
||||
|
||||
riscv_hart_common()
|
||||
: instr_if(*this) {
|
||||
: state()
|
||||
, instr_if(*this) {
|
||||
// reset values
|
||||
csr[misa] = traits<BASE>::MISA_VAL;
|
||||
csr[mvendorid] = 0x669;
|
||||
@@ -748,17 +711,16 @@ template <typename BASE, typename LOGCAT = logging::disass> struct riscv_hart_co
|
||||
return iss::Ok;
|
||||
}
|
||||
|
||||
iss::status write_xtvt(unsigned addr, reg_t val) {
|
||||
csr[addr] = val & ~0x3fULL;
|
||||
return iss::Ok;
|
||||
}
|
||||
|
||||
priv_if<reg_t> get_priv_if() {
|
||||
return priv_if<reg_t>{.read_csr = [this](unsigned addr, reg_t& val) -> iss::status { return read_csr(addr, val); },
|
||||
.write_csr = [this](unsigned addr, reg_t val) -> iss::status { return write_csr(addr, val); },
|
||||
.exec_htif = [this](uint8_t const* data) -> iss::status { return execute_htif(data); },
|
||||
.csr_rd_cb{this->csr_rd_cb},
|
||||
.csr_wr_cb{csr_wr_cb},
|
||||
.mstatus{this->state},
|
||||
.tohost{this->tohost},
|
||||
.fromhost{this->fromhost}};
|
||||
.fromhost{this->fromhost},
|
||||
.mcause_max_irq{mcause_max_irq}};
|
||||
}
|
||||
|
||||
iss::status execute_htif(uint8_t const* data) {
|
||||
@@ -798,17 +760,33 @@ template <typename BASE, typename LOGCAT = logging::disass> struct riscv_hart_co
|
||||
}
|
||||
}
|
||||
|
||||
memory::memory_hierarchy memories;
|
||||
mmio::memory_hierarchy memories;
|
||||
|
||||
virtual memory::memory_if get_mem_if() override {
|
||||
virtual mmio::memory_if get_mem_if() override {
|
||||
assert(false || "This function should nevver be called");
|
||||
return memory::memory_if{};
|
||||
return mmio::memory_if{};
|
||||
}
|
||||
|
||||
virtual void set_next(memory::memory_if mem_if) { memory = mem_if; };
|
||||
virtual void set_next(mmio::memory_if mem_if) { memory = mem_if; };
|
||||
|
||||
void set_irq_num(unsigned i) { mcause_max_irq = 1 << util::ilog2(i); }
|
||||
|
||||
protected:
|
||||
memory::memory_if memory;
|
||||
hart_state<reg_t> state;
|
||||
|
||||
static constexpr reg_t get_mstatus_mask_t(unsigned priv_lvl = PRIV_M) {
|
||||
if(sizeof(reg_t) == 4) {
|
||||
return priv_lvl == PRIV_U ? 0x80000011UL : // 0b1...0 0001 0001
|
||||
priv_lvl == PRIV_S ? 0x800de133UL // 0b0...0 0001 1000 1001 1001;
|
||||
: 0x807ff9ddUL;
|
||||
} else {
|
||||
return priv_lvl == PRIV_U ? 0x011ULL : // 0b1...0 0001 0001
|
||||
priv_lvl == PRIV_S ? 0x000de133ULL
|
||||
: 0x007ff9ddULL;
|
||||
}
|
||||
}
|
||||
|
||||
mmio::memory_if memory;
|
||||
struct riscv_instrumentation_if : public iss::instrumentation_if {
|
||||
|
||||
riscv_instrumentation_if(riscv_hart_common<BASE, LOGCAT>& arch)
|
||||
@@ -864,6 +842,7 @@ protected:
|
||||
int64_t instret_offset{0};
|
||||
semihosting_cb_t<reg_t> semihosting_cb;
|
||||
std::array<vm_info, 2> vm;
|
||||
unsigned mcause_max_irq{16U};
|
||||
};
|
||||
|
||||
} // namespace arch
|
||||
|
Reference in New Issue
Block a user