diff --git a/gen_input/templates/CORENAME_sysc.cpp.gtl b/gen_input/templates/CORENAME_sysc.cpp.gtl index 5882e57..9e99eec 100644 --- a/gen_input/templates/CORENAME_sysc.cpp.gtl +++ b/gen_input/templates/CORENAME_sysc.cpp.gtl @@ -38,6 +38,10 @@ #include #include #include +<% if(coreDef.name.toLowerCase()=="tgc5d" || coreDef.name.toLowerCase()=="tgc5e") { %> +#include +#include +<%}%> <% def array_count = coreDef.name.toLowerCase()=="tgc5d" || coreDef.name.toLowerCase()=="tgc5e"? 3 : 2; %> @@ -59,8 +63,11 @@ volatile std::array ${coreDef.name.toLowerCase()}_init = { auto* cpu = new core2sc_adapter>(cc); return {sysc::core_ptr{cpu}, vm_ptr{create(static_cast(cpu), gdb_port)}}; })<%if(coreDef.name.toLowerCase()=="tgc5d" || coreDef.name.toLowerCase()=="tgc5e") {%>, - iss_factory::instance().register_creator("${coreDef.name.toLowerCase()}_mu_p_clic_pmp:interp", [](unsigned gdb_port, sysc::riscv::core_complex_if* cc) -> iss_factory::base_t { + iss_factory::instance().register_creator("${coreDef.name.toLowerCase()}_clic_pmp:interp", [](unsigned gdb_port, sysc::riscv::core_complex_if* cc) -> iss_factory::base_t { auto* cpu = new core2sc_adapter>(cc); + cpu->memories.insert_before_last(std::make_unique>(cpu->get_priv_if())); + iss::mem::clic_config ccfg{.clic_base=0xc0000000, .clic_int_ctl_bits=4, .clic_num_irq=16, .clic_num_trigger=0, .nmode=true}; + cpu->memories.insert_before_last(std::make_unique::reg_t>>(cpu->get_priv_if(), ccfg)); return {sysc::core_ptr{cpu}, vm_ptr{create(static_cast(cpu), gdb_port)}}; })<%}%> }; @@ -77,8 +84,11 @@ volatile std::array ${coreDef.name.toLowerCase()}_init = { auto* cpu = new core2sc_adapter>(cc); return {sysc::core_ptr{cpu}, vm_ptr{create(static_cast(cpu), gdb_port)}}; })<%if(coreDef.name.toLowerCase()=="tgc5d" || coreDef.name.toLowerCase()=="tgc5e") {%>, - iss_factory::instance().register_creator("${coreDef.name.toLowerCase()}_mu_p_clic_pmp:llvm", [](unsigned gdb_port, sysc::riscv::core_complex_if* cc) -> iss_factory::base_t { + iss_factory::instance().register_creator("${coreDef.name.toLowerCase()}_clic_pmp:llvm", [](unsigned gdb_port, sysc::riscv::core_complex_if* cc) -> iss_factory::base_t { auto* cpu = new core2sc_adapter>(cc); + cpu->memories.insert_before_last(std::make_unique>(cpu->get_priv_if())); + iss::mem::clic_config ccfg{.clic_base=0xc0000000, .clic_int_ctl_bits=4, .clic_num_irq=16, .clic_num_trigger=0, .nmode=true}; + cpu->memories.insert_before_last(std::make_unique::reg_t>>(cpu->get_priv_if(), ccfg)); return {sysc::core_ptr{cpu}, vm_ptr{create(static_cast(cpu), gdb_port)}}; })<%}%> }; @@ -104,6 +114,9 @@ volatile std::array ${coreDef.name.toLowerCase()}_init = { })<%if(coreDef.name.toLowerCase()=="tgc5d" || coreDef.name.toLowerCase()=="tgc5e") {%>, iss_factory::instance().register_creator("${coreDef.name.toLowerCase()}_mu_p_clic_pmp:asmjit", [](unsigned gdb_port, sysc::riscv::core_complex_if* cc) -> iss_factory::base_t { auto* cpu = new core2sc_adapter>(cc); + cpu->memories.insert_before_last(std::make_unique>(cpu->get_priv_if())); + iss::mem::clic_config ccfg{.clic_base=0xc0000000, .clic_int_ctl_bits=4, .clic_num_irq=16, .clic_num_trigger=0, .nmode=true}; + cpu->memories.insert_before_last(std::make_unique::reg_t>>(cpu->get_priv_if(), ccfg)); return {sysc::core_ptr{cpu}, vm_ptr{create(static_cast(cpu), gdb_port)}}; })<%}%> }; diff --git a/gen_input/templates/interp/CORENAME.cpp.gtl b/gen_input/templates/interp/CORENAME.cpp.gtl index ed8c026..2164036 100644 --- a/gen_input/templates/interp/CORENAME.cpp.gtl +++ b/gen_input/templates/interp/CORENAME.cpp.gtl @@ -56,7 +56,6 @@ if(vector) {%> #include #include #include -#include #include @@ -453,6 +452,13 @@ std::unique_ptr create(arch::${coreD #include #include #include +<% if(coreDef.name.toLowerCase()=="tgc5d" || coreDef.name.toLowerCase()=="tgc5e") { %> +#include +#include +<%}%> +<% +def array_count = coreDef.name.toLowerCase()=="tgc5d" || coreDef.name.toLowerCase()=="tgc5e"? 3 : 2; +%> namespace iss { namespace { <% if(instructions.find{it.instruction.name.toLowerCase() == "sret"}) {%> @@ -466,8 +472,8 @@ volatile std::array dummy = { cpu->set_semihosting_callback(*cb); } return {cpu_ptr{cpu}, vm_ptr{vm}}; - }),<% } else { %> -volatile std::array dummy = {<%}%> + }),<%} else {%> +volatile std::array dummy = {<%}%> core_factory::instance().register_creator("${coreDef.name.toLowerCase()}_m:interp", [](unsigned port, void* init_data) -> std::tuple{ auto* cpu = new iss::arch::riscv_hart_m_p(); auto vm = new interp::${coreDef.name.toLowerCase()}::vm_impl(*cpu, false); @@ -487,7 +493,20 @@ volatile std::array dummy = {<%}%> cpu->set_semihosting_callback(*cb); } return {cpu_ptr{cpu}, vm_ptr{vm}}; - }) + })<%if(coreDef.name.toLowerCase()=="tgc5d" || coreDef.name.toLowerCase()=="tgc5e") {%>, + core_factory::instance().register_creator("${coreDef.name.toLowerCase()}_clic_pmp:interp", [](unsigned port, void* init_data) -> std::tuple{ + auto* cpu = new iss::arch::riscv_hart_mu_p(); + cpu->memories.insert_before_last(std::make_unique>(cpu->get_priv_if())); + iss::mem::clic_config ccfg{.clic_base=0xc0000000, .clic_int_ctl_bits=4, .clic_num_irq=16, .clic_num_trigger=0, .nmode=true}; + cpu->memories.insert_before_last(std::make_unique::reg_t>>(cpu->get_priv_if(), ccfg)); + auto vm = new interp::${coreDef.name.toLowerCase()}::vm_impl(*cpu, false); + if (port != 0) debugger::server::run_server(vm, port); + if(init_data){ + auto* cb = reinterpret_cast::reg_t>*>(init_data); + cpu->set_semihosting_callback(*cb); + } + return {cpu_ptr{cpu}, vm_ptr{vm}}; + })<%}%> }; } } diff --git a/src/iss/arch/riscv_hart_common.h b/src/iss/arch/riscv_hart_common.h index 9a76d3e..01e15d3 100644 --- a/src/iss/arch/riscv_hart_common.h +++ b/src/iss/arch/riscv_hart_common.h @@ -938,7 +938,7 @@ template struct riscv_hart_common : public BAS this->fault_data = fault_data; }, .csr_rd_cb{this->csr_rd_cb}, - .csr_wr_cb{csr_wr_cb}, + .csr_wr_cb{this->csr_wr_cb}, .state{this->state}, .PRIV{this->reg.PRIV}, .PC{this->reg.PC}, diff --git a/src/iss/mem/clic.h b/src/iss/mem/clic.h index 2262d43..190bac1 100644 --- a/src/iss/mem/clic.h +++ b/src/iss/mem/clic.h @@ -46,7 +46,7 @@ struct clic_config { unsigned clic_num_trigger{0}; bool nmode{false}; }; - +namespace { inline void read_reg_with_offset(uint32_t reg, uint8_t offs, uint8_t* const data, unsigned length) { auto reg_ptr = reinterpret_cast(®); switch(offs) { @@ -88,20 +88,21 @@ inline void write_reg_with_offset(uint32_t& reg, uint8_t offs, const uint8_t* co break; } } +} // namespace template struct clic : public memory_elem { using this_class = clic; using reg_t = WORD_TYPE; constexpr static unsigned WORD_LEN = sizeof(WORD_TYPE) * 8; - clic(arch::priv_if hart_if, clic_config cfg) + clic(arch::priv_if hart_if, clic_config const& cfg) : hart_if(hart_if) , cfg(cfg) { clic_int_reg.resize(cfg.clic_num_irq, clic_int_reg_t{.raw = 0}); clic_cfg_reg = 0x30; clic_mact_lvl = clic_mprev_lvl = (1 << (cfg.clic_int_ctl_bits)) - 1; clic_uact_lvl = clic_uprev_lvl = (1 << (cfg.clic_int_ctl_bits)) - 1; - hart_if.csr_rd_cb[arch::mtvt] = MK_CSR_RD_CB(read_plain); + hart_if.csr_rd_cb[arch::mtvt] = MK_CSR_RD_CB(read_xtvt); // 0x307 hart_if.csr_wr_cb[arch::mtvt] = MK_CSR_WR_CB(write_xtvt); // hart_if.csr_rd_cb[mxnti] = MK_CSR_RD_CB(read_plain(a,r);}; // hart_if.csr_wr_cb[mxnti] = MK_CSR_WR_CB(write_plain(a,r);}; @@ -111,18 +112,18 @@ template struct clic : public memory_elem { // hart_if.csr_wr_cb[mscratchcsw] = MK_CSR_WR_CB(write_plain(a,r);}; // hart_if.csr_rd_cb[mscratchcswl] = MK_CSR_RD_CB(read_plain(a,r);}; // hart_if.csr_wr_cb[mscratchcswl] = MK_CSR_WR_CB(write_plain(a,r);}; - hart_if.csr_rd_cb[arch::mintthresh] = MK_CSR_RD_CB(read_plain); + hart_if.csr_rd_cb[arch::mintthresh] = MK_CSR_RD_CB(read_intthresh); hart_if.csr_wr_cb[arch::mintthresh] = MK_CSR_WR_CB(write_intthresh); if(cfg.nmode) { - hart_if.csr_rd_cb[arch::utvt] = MK_CSR_RD_CB(read_plain); + hart_if.csr_rd_cb[arch::utvt] = MK_CSR_RD_CB(read_xtvt); // 0x007 hart_if.csr_wr_cb[arch::utvt] = MK_CSR_WR_CB(write_xtvt); hart_if.csr_rd_cb[arch::uintstatus] = MK_CSR_RD_CB(read_intstatus); hart_if.csr_wr_cb[arch::uintstatus] = MK_CSR_WR_CB(write_null); - hart_if.csr_rd_cb[arch::uintthresh] = MK_CSR_RD_CB(read_plain); + hart_if.csr_rd_cb[arch::uintthresh] = MK_CSR_RD_CB(read_intthresh); hart_if.csr_wr_cb[arch::uintthresh] = MK_CSR_WR_CB(write_intthresh); } - hart_if.csr[arch::mintthresh] = (1 << (cfg.clic_int_ctl_bits)) - 1; - hart_if.csr[arch::uintthresh] = (1 << (cfg.clic_int_ctl_bits)) - 1; + clic_intthresh[arch::mintthresh >> 8] = (1 << (cfg.clic_int_ctl_bits)) - 1; + clic_intthresh[arch::uintthresh >> 8] = (1 << (cfg.clic_int_ctl_bits)) - 1; } ~clic() = default; @@ -137,16 +138,16 @@ template struct clic : public memory_elem { std::tuple get_range() override { return {cfg.clic_base, cfg.clic_base + 0x7fff}; } private: - iss::status read_mem(iss::access_type access, uint64_t addr, unsigned length, uint8_t* data) { - if(addr >= cfg.clic_base && (addr + length) < (cfg.clic_base + 0x8000)) - return read_clic(addr, length, data); - return down_stream_mem.rd_mem(access, addr, length, data); + iss::status read_mem(addr_t const& addr, unsigned length, uint8_t* data) { + if(addr.space == 0 && addr.val >= cfg.clic_base && (addr.val + length) < (cfg.clic_base + 0x8000)) + return read_clic(addr.val, length, data); + return down_stream_mem.rd_mem(addr, length, data); } - iss::status write_mem(iss::access_type access, uint64_t addr, unsigned length, uint8_t const* data) { - if(addr >= cfg.clic_base && (addr + length) < (cfg.clic_base + 0x8000)) - return write_clic(addr, length, data); - return down_stream_mem.wr_mem(access, addr, length, data); + iss::status write_mem(addr_t const& addr, unsigned length, uint8_t const* data) { + if(addr.space == 0 && addr.val >= cfg.clic_base && (addr.val + length) < (cfg.clic_base + 0x8000)) + return write_clic(addr.val, length, data); + return down_stream_mem.wr_mem(addr, length, data); } iss::status read_clic(uint64_t addr, unsigned length, uint8_t* data); @@ -155,21 +156,33 @@ template struct clic : public memory_elem { iss::status write_null(unsigned addr, reg_t val) { return iss::status::Ok; } - iss::status read_plain(unsigned addr, reg_t& val) { - val = hart_if.csr[addr]; + iss::status read_xtvt(unsigned addr, reg_t& val) { + val = clic_xtvt[addr >> 8]; return iss::Ok; } iss::status write_xtvt(unsigned addr, reg_t val) { - hart_if.csr[addr] = val & ~0x3fULL; + clic_xtvt[addr >> 8] = val & ~0x3fULL; return iss::Ok; } - iss::status read_cause(unsigned addr, reg_t& val); - iss::status write_cause(unsigned addr, reg_t val); + iss::status read_intstatus(unsigned addr, reg_t& val) { + auto mode = (addr >> 8) & 0x3; + val = clic_uact_lvl & 0xff; + if(mode == 0x3) + val += (clic_mact_lvl & 0xff) << 24; + return iss::Ok; + } + + iss::status read_intthresh(unsigned addr, reg_t& val) { + val = clic_intthresh[addr >> 8]; + return iss::Ok; + } - 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) { + clic_intthresh[addr >> 8] = (val & 0xff) | (1 << (cfg.clic_int_ctl_bits)) - 1; + return iss::Ok; + } protected: arch::priv_if hart_if; @@ -189,6 +202,8 @@ template struct clic : public memory_elem { std::vector clic_int_reg; uint8_t clic_mprev_lvl{0}, clic_uprev_lvl{0}; uint8_t clic_mact_lvl{0}, clic_uact_lvl{0}; + std::array clic_intthresh; + std::array clic_xtvt; }; template iss::status clic::read_clic(uint64_t addr, unsigned length, uint8_t* const data) { @@ -225,61 +240,5 @@ template iss::status clic::write_clic(uint64_t a return iss::Ok; } -template iss::status clic::read_cause(unsigned addr, reg_t& val) { - if((hart_if.csr[arch::mtvec] & 0x3) == 3) { - val = hart_if.csr[addr] & (1UL << (sizeof(reg_t) * 8) | (hart_if.mcause_max_irq - 1) | (0xfUL << 16)); - auto mode = (addr >> 8) & 0x3; - switch(mode) { - case 0: - val |= clic_uprev_lvl << 16; - val |= hart_if.state.mstatus.UPIE << 27; - break; - default: - val |= clic_mprev_lvl << 16; - val |= hart_if.state.mstatus.MPIE << 27; - val |= hart_if.state.mstatus.MPP << 28; - break; - } - } else - val = hart_if.csr[addr] & ((1UL << (sizeof(WORD_TYPE) * 8 - 1)) | (hart_if.mcause_max_irq - 1)); - return iss::Ok; -} - -template iss::status clic::write_cause(unsigned addr, reg_t val) { - if((hart_if.csr[arch::mtvec] & 0x3) == 3) { - auto mask = ((1UL << (sizeof(WORD_TYPE) * 8 - 1)) | (hart_if.mcause_max_irq - 1) | (0xfUL << 16)); - hart_if.csr[addr] = (val & mask) | (hart_if.csr[addr] & ~mask); - auto mode = (addr >> 8) & 0x3; - switch(mode) { - case 0: - clic_uprev_lvl = ((val >> 16) & 0xff) | (1 << (8 - cfg.clic_int_ctl_bits)) - 1; - hart_if.state.mstatus.UPIE = (val >> 27) & 0x1; - break; - default: - clic_mprev_lvl = ((val >> 16) & 0xff) | (1 << (8 - cfg.clic_int_ctl_bits)) - 1; - hart_if.state.mstatus.MPIE = (val >> 27) & 0x1; - hart_if.state.mstatus.MPP = (val >> 28) & 0x3; - break; - } - } else { - auto mask = ((1UL << (sizeof(WORD_TYPE) * 8 - 1)) | (hart_if.mcause_max_irq - 1)); - hart_if.csr[addr] = (val & mask) | (hart_if.csr[addr] & ~mask); - } - return iss::Ok; -} - -template iss::status clic::read_intstatus(unsigned addr, reg_t& val) { - auto mode = (addr >> 8) & 0x3; - val = clic_uact_lvl & 0xff; - if(mode == 0x3) - val += (clic_mact_lvl & 0xff) << 24; - return iss::Ok; -} - -template iss::status clic::write_intthresh(unsigned addr, reg_t val) { - hart_if.csr[addr] = (val & 0xff) | (1 << (cfg.clic_int_ctl_bits)) - 1; - return iss::Ok; -} - } // namespace mem } // namespace iss diff --git a/src/iss/mem/memory_if.cpp b/src/iss/mem/memory_if.cpp index 3a68bcf..7f590fc 100644 --- a/src/iss/mem/memory_if.cpp +++ b/src/iss/mem/memory_if.cpp @@ -53,8 +53,14 @@ void memory_hierarchy::append(memory_elem& e) { hierarchy.push_back(&e); update_chain(); } -void memory_hierarchy::insert_before(memory_elem&) {} -void memory_hierarchy::insert_after(memory_elem&) {} +void memory_hierarchy::insert_before_last(memory_elem& e) { + hierarchy.insert(hierarchy.begin() + hierarchy.size() - 1, &e); + update_chain(); +} +void memory_hierarchy::insert_after_first(memory_elem& e) { + hierarchy.insert(hierarchy.begin() + 1, &e); + update_chain(); +} void memory_hierarchy::replace_last(memory_elem& e) { auto old = hierarchy.back(); auto it = std::find_if(std::begin(owned_elems), std::end(owned_elems), @@ -82,13 +88,13 @@ void memory_hierarchy::append(std::unique_ptr&& p) { owned_elems.push_back(std::move(p)); } -void memory_hierarchy::insert_before(std::unique_ptr&& p) { - insert_before(*p); +void memory_hierarchy::insert_before_last(std::unique_ptr&& p) { + insert_before_last(*p); owned_elems.push_back(std::move(p)); } -void memory_hierarchy::insert_after(std::unique_ptr&& p) { - insert_after(*p); +void memory_hierarchy::insert_after_first(std::unique_ptr&& p) { + insert_after_first(*p); owned_elems.push_back(std::move(p)); } diff --git a/src/iss/mem/memory_if.h b/src/iss/mem/memory_if.h index 48cfea2..4fc30af 100644 --- a/src/iss/mem/memory_if.h +++ b/src/iss/mem/memory_if.h @@ -65,13 +65,13 @@ struct memory_hierarchy { void root(memory_elem&); void prepend(memory_elem&); void append(memory_elem&); - void insert_before(memory_elem&); - void insert_after(memory_elem&); + void insert_before_last(memory_elem&); + void insert_after_first(memory_elem&); void replace_last(memory_elem&); void prepend(std::unique_ptr&&); void append(std::unique_ptr&&); - void insert_before(std::unique_ptr&&); - void insert_after(std::unique_ptr&&); + void insert_before_last(std::unique_ptr&&); + void insert_after_first(std::unique_ptr&&); void replace_last(std::unique_ptr&&); protected: diff --git a/src/iss/mem/pmp.h b/src/iss/mem/pmp.h index bc3a17c..f4ae6ec 100644 --- a/src/iss/mem/pmp.h +++ b/src/iss/mem/pmp.h @@ -40,68 +40,29 @@ namespace iss { namespace mem { -struct clic_config { - uint64_t clic_base{0xc0000000}; - unsigned clic_int_ctl_bits{4}; - unsigned clic_num_irq{16}; - unsigned clic_num_trigger{0}; - bool nmode{false}; -}; - -inline void read_reg_with_offset(uint32_t reg, uint8_t offs, uint8_t* const data, unsigned length) { - auto reg_ptr = reinterpret_cast(®); - switch(offs) { - default: - 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_with_offset(uint32_t& reg, uint8_t offs, const uint8_t* const data, unsigned length) { - auto reg_ptr = reinterpret_cast(®); - switch(offs) { - default: - 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 struct pmp : public memory_elem { using this_class = pmp; using reg_t = typename PLAT::reg_t; + static constexpr auto cfg_reg_size = sizeof(reg_t); + static constexpr auto PMP_SHIFT = 2U; + static constexpr auto PMP_R = 0x1U; + static constexpr auto PMP_W = 0x2U; + static constexpr auto PMP_X = 0x4U; + static constexpr auto PMP_A = 0x18U; + static constexpr auto PMP_L = 0x80U; + static constexpr auto PMP_TOR = 0x1U; + static constexpr auto PMP_NA4 = 0x2U; + static constexpr auto PMP_NAPOT = 0x3U; pmp(arch::priv_if hart_if) : hart_if(hart_if) { for(size_t i = arch::pmpaddr0; i <= arch::pmpaddr15; ++i) { - hart_if.csr_rd_cb[i] = MK_CSR_RD_CB(read_plain); - hart_if.csr_wr_cb[i] = MK_CSR_WR_CB(write_plain); + hart_if.csr_rd_cb[i] = MK_CSR_RD_CB(read_pmpaddr); + hart_if.csr_wr_cb[i] = MK_CSR_WR_CB(write_pmpaddr); } for(size_t i = arch::pmpcfg0; i < arch::pmpcfg0 + 16 / sizeof(reg_t); ++i) { - hart_if.csr_rd_cb[i] = MK_CSR_RD_CB(read_plain); + hart_if.csr_rd_cb[i] = MK_CSR_RD_CB(read_pmpcfg); hart_if.csr_wr_cb[i] = MK_CSR_WR_CB(write_pmpcfg); } } @@ -116,13 +77,16 @@ template struct pmp : public memory_elem { void set_next(memory_if mem) override { down_stream_mem = mem; } private: + std::array pmpaddr; + std::array pmpcfg; + iss::status read_mem(const addr_t& addr, unsigned length, uint8_t* data) { assert((addr.type == iss::address_type::PHYSICAL || is_debug(addr.access)) && "Only physical addresses are expected in pmp"); - if(likely(addr.space == arch::traits::MEM) && !pmp_check(addr.access, addr.val, length) && !is_debug(addr.access)) { - hart_if.fault_data = addr; + if(likely(addr.space == arch::traits::MEM || std::numeric_limits::max()) && + !pmp_check(addr.access, addr.val, length) && !is_debug(addr.access)) { if(is_debug(addr.access)) throw trap_access(0, addr.val); - hart_if.reg.trap_state = (1UL << 31) | ((addr.access == access_type::FETCH ? 1 : 5) << 16); // issue trap 1 + hart_if.raise_trap(/*trap_id*/ 0, /*cause*/ (addr.access == access_type::FETCH) ? 1 : 5, /*fault_data*/ addr.val); return iss::Err; } return down_stream_mem.rd_mem(addr, length, data); @@ -131,62 +95,71 @@ template struct pmp : public memory_elem { iss::status write_mem(const addr_t& addr, unsigned length, uint8_t const* data) { assert((addr.type == iss::address_type::PHYSICAL || is_debug(addr.access)) && "Only physical addresses are expected in pmp"); if(likely(addr.space == arch::traits::MEM) && !pmp_check(addr.access, addr.val, length) && !is_debug(addr.access)) { - hart_if.fault_data = addr; if(is_debug(addr.access)) throw trap_access(0, addr.val); - hart_if.reg.trap_state = (1UL << 31) | (7 << 16); // issue trap 1 + hart_if.raise_trap(/*trap_id*/ 0, /*cause*/ 7, /*fault_data*/ addr.val); return iss::Err; } return down_stream_mem.wr_mem(addr, length, data); } - iss::status read_plain(unsigned addr, reg_t& val) { - val = hart_if.csr[addr]; - return iss::Ok; + iss::status read_pmpaddr(unsigned addr, reg_t& val) { + if(addr >= arch::pmpaddr0 && addr <= arch::pmpaddr15) { + val = pmpaddr[addr - arch::pmpaddr0]; + return iss::Ok; + } + return iss::Err; } - iss::status write_plain(unsigned addr, reg_t const& val) { - hart_if.csr[addr] = val; - return iss::Ok; + iss::status write_pmpaddr(unsigned addr, reg_t const& val) { + if(addr >= arch::pmpaddr0 && addr <= arch::pmpaddr15) { + pmpaddr[addr - arch::pmpaddr0] = val; + return iss::Ok; + } + return iss::Err; } + iss::status read_pmpcfg(unsigned addr, reg_t& val) { + if(addr >= arch::pmpcfg0 && addr < (arch::pmpcfg0 + 16 / sizeof(reg_t))) { + val = pmpaddr[addr - arch::pmpcfg0]; + return iss::Ok; + } + return iss::Err; + } iss::status write_pmpcfg(unsigned addr, reg_t val) { - hart_if.csr[addr] = val & 0x9f9f9f9f; - return iss::Ok; + if(addr >= arch::pmpcfg0 && addr < (arch::pmpcfg0 + 16 / sizeof(reg_t))) { + pmpaddr[addr - arch::pmpcfg0] = val & 0x9f9f9f9f; + any_active = false; + for(size_t i = 0; i < 16; i++) { + auto cfg = pmpcfg[i / cfg_reg_size] >> (i % cfg_reg_size); + any_active |= cfg & PMP_A; + } + return iss::Ok; + } + return iss::Err; } - bool pmp_check(const access_type type, const uint64_t addr, const unsigned len); + bool pmp_check(access_type type, uint64_t addr, unsigned len); protected: + bool any_active = false; arch::priv_if hart_if; memory_if down_stream_mem; }; -template bool pmp::pmp_check(const access_type type, const uint64_t addr, const unsigned len) { - constexpr auto PMP_SHIFT = 2U; - constexpr auto PMP_R = 0x1U; - constexpr auto PMP_W = 0x2U; - constexpr auto PMP_X = 0x4U; - constexpr auto PMP_A = 0x18U; - constexpr auto PMP_L = 0x80U; - constexpr auto PMP_TOR = 0x1U; - constexpr auto PMP_NA4 = 0x2U; - constexpr auto PMP_NAPOT = 0x3U; +template bool pmp::pmp_check(access_type type, uint64_t addr, unsigned len) { + if(!any_active) + return true; reg_t base = 0; - auto any_active = false; - auto const cfg_reg_size = sizeof(reg_t); for(size_t i = 0; i < 16; i++) { - reg_t tor = hart_if.csr[arch::pmpaddr0 + i] << PMP_SHIFT; - uint8_t cfg = hart_if.csr[arch::pmpcfg0 + (i / cfg_reg_size)] >> (i % cfg_reg_size); + reg_t tor = pmpaddr[i] << PMP_SHIFT; + reg_t cfg = pmpcfg[i / cfg_reg_size] >> (i % cfg_reg_size); if(cfg & PMP_A) { - any_active = true; auto pmp_a = (cfg & PMP_A) >> 3; auto is_tor = pmp_a == PMP_TOR; auto is_na4 = pmp_a == PMP_NA4; - - reg_t mask = (hart_if.csr[arch::pmpaddr0 + i] << 1) | (!is_na4); + reg_t mask = (pmpaddr[i] << 1) | (!is_na4); mask = ~(mask & ~(mask + 1)) << PMP_SHIFT; - // Check each 4-byte sector of the access auto any_match = false; auto all_match = true; @@ -202,7 +175,7 @@ template bool pmp::pmp_check(const access_type type, const // If the PMP matches only a strict subset of the access, fail it if(!all_match) return false; - return (hart_if.reg.PRIV == arch::PRIV_M && !(cfg & PMP_L)) || (type == access_type::READ && (cfg & PMP_R)) || + return (hart_if.PRIV == arch::PRIV_M && !(cfg & PMP_L)) || (type == access_type::READ && (cfg & PMP_R)) || (type == access_type::WRITE && (cfg & PMP_W)) || (type == access_type::FETCH && (cfg & PMP_X)); } } @@ -239,7 +212,7 @@ template bool pmp::pmp_check(const access_type type, const // } // tor_base = pmpaddr; // } - return !any_active || hart_if.reg.PRIV == arch::PRIV_M; + return hart_if.PRIV == arch::PRIV_M; } } // namespace mem diff --git a/src/main.cpp b/src/main.cpp index 2f042ed..d78b83d 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -147,16 +147,10 @@ int main(int argc, char* argv[]) { } return 0; } else if(isa_opt.find(':') == std::string::npos) { + if(isa_opt == "tgc5d" || isa_opt == "tgc5e") + isa_opt += "_clic_pmp"; std::tie(cpu, vm) = f.create(isa_opt + ":" + clim["backend"].as(), clim["gdb-port"].as(), &semihosting_cb); - } else { - auto base_isa = isa_opt.substr(0, 5); - if(base_isa == "tgc5d" || base_isa == "tgc5e") { - isa_opt += "_clic_pmp:" + clim["backend"].as(); - } else { - isa_opt += ":" + clim["backend"].as(); - } - std::tie(cpu, vm) = f.create(isa_opt, clim["gdb-port"].as(), &semihosting_cb); } if(!cpu) { auto list = f.get_names(); diff --git a/src/vm/interp/vm_rv32gc.cpp b/src/vm/interp/vm_rv32gc.cpp index 5b405e8..a12d624 100644 --- a/src/vm/interp/vm_rv32gc.cpp +++ b/src/vm/interp/vm_rv32gc.cpp @@ -46,7 +46,6 @@ #include #include #include -#include #include @@ -3034,7 +3033,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co if(this->disass_enabled){ /* generate console output when executing the command */ auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, sp, {uimm:#05x}", fmt::arg("mnemonic", "c.lwsp"), + "{mnemonic:10} {rd}, {uimm:#05x}(sp)", fmt::arg("mnemonic", "c.lwsp"), fmt::arg("rd", name(rd)), fmt::arg("uimm", uimm)); this->core.disass_output(pc.val, mnemonic); } @@ -4930,6 +4929,8 @@ std::unique_ptr create(arch::rv32gc *core, unsigned short p #include #include #include + + namespace iss { namespace { diff --git a/src/vm/interp/vm_rv32gcv.cpp b/src/vm/interp/vm_rv32gcv.cpp index c5e6994..a387f21 100644 --- a/src/vm/interp/vm_rv32gcv.cpp +++ b/src/vm/interp/vm_rv32gcv.cpp @@ -48,7 +48,6 @@ #include #include #include -#include #include @@ -4005,7 +4004,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co if(this->disass_enabled){ /* generate console output when executing the command */ auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, sp, {uimm:#05x}", fmt::arg("mnemonic", "c.lwsp"), + "{mnemonic:10} {rd}, {uimm:#05x}(sp)", fmt::arg("mnemonic", "c.lwsp"), fmt::arg("rd", name(rd)), fmt::arg("uimm", uimm)); this->core.disass_output(pc.val, mnemonic); } @@ -29814,6 +29813,8 @@ std::unique_ptr create(arch::rv32gcv *core, unsigned short #include #include #include + + namespace iss { namespace { diff --git a/src/vm/interp/vm_rv32i.cpp b/src/vm/interp/vm_rv32i.cpp index 7447095..34e3865 100644 --- a/src/vm/interp/vm_rv32i.cpp +++ b/src/vm/interp/vm_rv32i.cpp @@ -44,7 +44,6 @@ #include #include #include -#include #include @@ -1797,6 +1796,8 @@ std::unique_ptr create(arch::rv32i *core, unsigned short por #include #include #include + + namespace iss { namespace { diff --git a/src/vm/interp/vm_rv32imac.cpp b/src/vm/interp/vm_rv32imac.cpp index ca29721..e3a365a 100644 --- a/src/vm/interp/vm_rv32imac.cpp +++ b/src/vm/interp/vm_rv32imac.cpp @@ -44,7 +44,6 @@ #include #include #include -#include #include @@ -2939,7 +2938,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co if(this->disass_enabled){ /* generate console output when executing the command */ auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, sp, {uimm:#05x}", fmt::arg("mnemonic", "c.lwsp"), + "{mnemonic:10} {rd}, {uimm:#05x}(sp)", fmt::arg("mnemonic", "c.lwsp"), fmt::arg("rd", name(rd)), fmt::arg("uimm", uimm)); this->core.disass_output(pc.val, mnemonic); } @@ -3199,6 +3198,8 @@ std::unique_ptr create(arch::rv32imac *core, unsigned sho #include #include #include + + namespace iss { namespace { diff --git a/src/vm/interp/vm_rv64gc.cpp b/src/vm/interp/vm_rv64gc.cpp index ced250c..b0c4b24 100644 --- a/src/vm/interp/vm_rv64gc.cpp +++ b/src/vm/interp/vm_rv64gc.cpp @@ -46,7 +46,6 @@ #include #include #include -#include #include @@ -4113,7 +4112,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co if(this->disass_enabled){ /* generate console output when executing the command */ auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, sp, {uimm:#05x}", fmt::arg("mnemonic", "c.lwsp"), + "{mnemonic:10} {rd}, {uimm:#05x}(sp)", fmt::arg("mnemonic", "c.lwsp"), fmt::arg("rd", name(rd)), fmt::arg("uimm", uimm)); this->core.disass_output(pc.val, mnemonic); } @@ -6273,6 +6272,8 @@ std::unique_ptr create(arch::rv64gc *core, unsigned short p #include #include #include + + namespace iss { namespace { diff --git a/src/vm/interp/vm_rv64gcv.cpp b/src/vm/interp/vm_rv64gcv.cpp index efc747a..8d00b6b 100644 --- a/src/vm/interp/vm_rv64gcv.cpp +++ b/src/vm/interp/vm_rv64gcv.cpp @@ -48,7 +48,6 @@ #include #include #include -#include #include @@ -5084,7 +5083,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co if(this->disass_enabled){ /* generate console output when executing the command */ auto mnemonic = fmt::format( - "{mnemonic:10} {rd}, sp, {uimm:#05x}", fmt::arg("mnemonic", "c.lwsp"), + "{mnemonic:10} {rd}, {uimm:#05x}(sp)", fmt::arg("mnemonic", "c.lwsp"), fmt::arg("rd", name(rd)), fmt::arg("uimm", uimm)); this->core.disass_output(pc.val, mnemonic); } @@ -31157,6 +31156,8 @@ std::unique_ptr create(arch::rv64gcv *core, unsigned short #include #include #include + + namespace iss { namespace { diff --git a/src/vm/interp/vm_rv64i.cpp b/src/vm/interp/vm_rv64i.cpp index 9ca2dc6..d9749d4 100644 --- a/src/vm/interp/vm_rv64i.cpp +++ b/src/vm/interp/vm_rv64i.cpp @@ -44,7 +44,6 @@ #include #include #include -#include #include @@ -2163,6 +2162,8 @@ std::unique_ptr create(arch::rv64i *core, unsigned short por #include #include #include + + namespace iss { namespace { diff --git a/src/vm/interp/vm_tgc5c.cpp b/src/vm/interp/vm_tgc5c.cpp index 5bc85f8..ab5072d 100644 --- a/src/vm/interp/vm_tgc5c.cpp +++ b/src/vm/interp/vm_tgc5c.cpp @@ -44,7 +44,6 @@ #include #include #include -#include #include @@ -2784,6 +2783,8 @@ std::unique_ptr create(arch::tgc5c *core, unsigned short por #include #include #include + + namespace iss { namespace {