Compare commits
	
		
			1 Commits
		
	
	
		
			c6b99cd155
			...
			5a2b96ef3e
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 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) { | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user