|  |  |  | @@ -66,7 +66,9 @@ | 
		
	
		
			
				|  |  |  |  | namespace iss { | 
		
	
		
			
				|  |  |  |  | namespace arch { | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | template <typename BASE, bool PMP=false> class riscv_hart_mu_p : public BASE { | 
		
	
		
			
				|  |  |  |  | enum features_e{FEAT_NONE, FEAT_PMP, FEAT_EXT_N}; | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | template <typename BASE, features_e FEAT=FEAT_NONE> class riscv_hart_mu_p : public BASE { | 
		
	
		
			
				|  |  |  |  | protected: | 
		
	
		
			
				|  |  |  |  |     const std::array<const char, 4> lvl = {{'U', 'S', 'H', 'M'}}; | 
		
	
		
			
				|  |  |  |  |     const std::array<const char *, 16> trap_str = {{"" | 
		
	
	
		
			
				
					
					|  |  |  | @@ -92,7 +94,7 @@ protected: | 
		
	
		
			
				|  |  |  |  |          "User external interrupt", "Supervisor external interrupt", "Reserved", "Machine external interrupt"}}; | 
		
	
		
			
				|  |  |  |  | public: | 
		
	
		
			
				|  |  |  |  |     using super = BASE; | 
		
	
		
			
				|  |  |  |  |     using this_class = riscv_hart_mu_p<BASE, PMP>; | 
		
	
		
			
				|  |  |  |  |     using this_class = riscv_hart_mu_p<BASE, FEAT>; | 
		
	
		
			
				|  |  |  |  |     using phys_addr_t = typename super::phys_addr_t; | 
		
	
		
			
				|  |  |  |  |     using reg_t = typename super::reg_t; | 
		
	
		
			
				|  |  |  |  |     using addr_t = typename super::addr_t; | 
		
	
	
		
			
				
					
					|  |  |  | @@ -218,7 +220,7 @@ public: | 
		
	
		
			
				|  |  |  |  | protected: | 
		
	
		
			
				|  |  |  |  |     struct riscv_instrumentation_if : public iss::instrumentation_if { | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  |         riscv_instrumentation_if(riscv_hart_mu_p<BASE, PMP> &arch) | 
		
	
		
			
				|  |  |  |  |         riscv_instrumentation_if(riscv_hart_mu_p<BASE, FEAT> &arch) | 
		
	
		
			
				|  |  |  |  |         : arch(arch) {} | 
		
	
		
			
				|  |  |  |  |         /** | 
		
	
		
			
				|  |  |  |  |          * get the name of this architecture | 
		
	
	
		
			
				
					
					|  |  |  | @@ -233,7 +235,7 @@ protected: | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  |         virtual void set_curr_instr_cycles(unsigned cycles) { arch.cycle_offset += cycles - 1; }; | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  |         riscv_hart_mu_p<BASE, PMP> &arch; | 
		
	
		
			
				|  |  |  |  |         riscv_hart_mu_p<BASE, FEAT> &arch; | 
		
	
		
			
				|  |  |  |  |     }; | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  |     friend struct riscv_instrumentation_if; | 
		
	
	
		
			
				
					
					|  |  |  | @@ -286,8 +288,8 @@ protected: | 
		
	
		
			
				|  |  |  |  |     void check_interrupt(); | 
		
	
		
			
				|  |  |  |  | }; | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | template <typename BASE, bool PMP> | 
		
	
		
			
				|  |  |  |  | riscv_hart_mu_p<BASE, PMP>::riscv_hart_mu_p() | 
		
	
		
			
				|  |  |  |  | template <typename BASE, features_e FEAT> | 
		
	
		
			
				|  |  |  |  | riscv_hart_mu_p<BASE, FEAT>::riscv_hart_mu_p() | 
		
	
		
			
				|  |  |  |  | : state() | 
		
	
		
			
				|  |  |  |  | , cycle_offset(0) | 
		
	
		
			
				|  |  |  |  | , instr_if(*this) { | 
		
	
	
		
			
				
					
					|  |  |  | @@ -326,9 +328,26 @@ riscv_hart_mu_p<BASE, PMP>::riscv_hart_mu_p() | 
		
	
		
			
				|  |  |  |  |     // read-only registers | 
		
	
		
			
				|  |  |  |  |     csr_rd_cb[misa] = &this_class::read_reg; | 
		
	
		
			
				|  |  |  |  |     csr_wr_cb[misa] = nullptr; | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  |     if(FEAT & FEAT_PMP){ | 
		
	
		
			
				|  |  |  |  |         for(size_t i=pmpaddr0; i<=pmpaddr15; ++i){ | 
		
	
		
			
				|  |  |  |  |             csr_rd_cb[i] = &this_class::read_reg; | 
		
	
		
			
				|  |  |  |  |             csr_wr_cb[i] = &this_class::write_reg; | 
		
	
		
			
				|  |  |  |  |         } | 
		
	
		
			
				|  |  |  |  |         for(size_t i=pmpcfg0; i<=pmpcfg3; ++i){ | 
		
	
		
			
				|  |  |  |  |             csr_rd_cb[i] = &this_class::read_reg; | 
		
	
		
			
				|  |  |  |  |             csr_wr_cb[i] = &this_class::write_reg; | 
		
	
		
			
				|  |  |  |  |         } | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
		
			
				|  |  |  |  |     if(FEAT & FEAT_EXT_N){ | 
		
	
		
			
				|  |  |  |  |         csr_rd_cb[mideleg] = &this_class::read_reg; | 
		
	
		
			
				|  |  |  |  |         csr_wr_cb[mideleg] = &this_class::write_reg; | 
		
	
		
			
				|  |  |  |  |         csr_rd_cb[medeleg] = &this_class::read_reg; | 
		
	
		
			
				|  |  |  |  |         csr_wr_cb[medeleg] = &this_class::write_reg; | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | template <typename BASE, bool PMP> std::pair<uint64_t, bool> riscv_hart_mu_p<BASE, PMP>::load_file(std::string name, int type) { | 
		
	
		
			
				|  |  |  |  | template <typename BASE, features_e FEAT> std::pair<uint64_t, bool> riscv_hart_mu_p<BASE, FEAT>::load_file(std::string name, int type) { | 
		
	
		
			
				|  |  |  |  |     FILE *fp = fopen(name.c_str(), "r"); | 
		
	
		
			
				|  |  |  |  |     if (fp) { | 
		
	
		
			
				|  |  |  |  |         std::array<char, 5> buf; | 
		
	
	
		
			
				
					
					|  |  |  | @@ -372,8 +391,8 @@ template <typename BASE, bool PMP> std::pair<uint64_t, bool> riscv_hart_mu_p<BAS | 
		
	
		
			
				|  |  |  |  |     throw std::runtime_error("memory load file not found"); | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | template <typename BASE, bool PMP> | 
		
	
		
			
				|  |  |  |  | iss::status riscv_hart_mu_p<BASE, PMP>::read(const address_type type, const access_type access, const uint32_t space, | 
		
	
		
			
				|  |  |  |  | template <typename BASE, features_e FEAT> | 
		
	
		
			
				|  |  |  |  | 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, const unsigned length, uint8_t *const data) { | 
		
	
		
			
				|  |  |  |  | #ifndef NDEBUG | 
		
	
		
			
				|  |  |  |  |     if (access && iss::access_type::DEBUG) { | 
		
	
	
		
			
				
					
					|  |  |  | @@ -430,8 +449,8 @@ iss::status riscv_hart_mu_p<BASE, PMP>::read(const address_type type, const acce | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | template <typename BASE, bool PMP> | 
		
	
		
			
				|  |  |  |  | iss::status riscv_hart_mu_p<BASE, PMP>::write(const address_type type, const access_type access, const uint32_t space, | 
		
	
		
			
				|  |  |  |  | template <typename BASE, features_e FEAT> | 
		
	
		
			
				|  |  |  |  | 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, const unsigned length, const uint8_t *const data) { | 
		
	
		
			
				|  |  |  |  | #ifndef NDEBUG | 
		
	
		
			
				|  |  |  |  |     const char *prefix = (access && iss::access_type::DEBUG) ? "debug " : ""; | 
		
	
	
		
			
				
					
					|  |  |  | @@ -537,7 +556,7 @@ iss::status riscv_hart_mu_p<BASE, PMP>::write(const address_type type, const acc | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | template <typename BASE, bool PMP> iss::status riscv_hart_mu_p<BASE, PMP>::read_csr(unsigned addr, reg_t &val) { | 
		
	
		
			
				|  |  |  |  | template <typename BASE, features_e FEAT> iss::status riscv_hart_mu_p<BASE, FEAT>::read_csr(unsigned addr, reg_t &val) { | 
		
	
		
			
				|  |  |  |  |     if (addr >= csr.size()) return iss::Err; | 
		
	
		
			
				|  |  |  |  |     auto req_priv_lvl = (addr >> 8) & 0x3; | 
		
	
		
			
				|  |  |  |  |     if (this->reg.PRIV < req_priv_lvl) // not having required privileges | 
		
	
	
		
			
				
					
					|  |  |  | @@ -548,7 +567,7 @@ template <typename BASE, bool PMP> iss::status riscv_hart_mu_p<BASE, PMP>::read_ | 
		
	
		
			
				|  |  |  |  |     return (this->*(it->second))(addr, val); | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | template <typename BASE, bool PMP> iss::status riscv_hart_mu_p<BASE, PMP>::write_csr(unsigned addr, reg_t val) { | 
		
	
		
			
				|  |  |  |  | template <typename BASE, features_e FEAT> iss::status riscv_hart_mu_p<BASE, FEAT>::write_csr(unsigned addr, reg_t val) { | 
		
	
		
			
				|  |  |  |  |     if (addr >= csr.size()) return iss::Err; | 
		
	
		
			
				|  |  |  |  |     auto req_priv_lvl = (addr >> 8) & 0x3; | 
		
	
		
			
				|  |  |  |  |     if (this->reg.PRIV < req_priv_lvl) // not having required privileges | 
		
	
	
		
			
				
					
					|  |  |  | @@ -561,17 +580,17 @@ template <typename BASE, bool PMP> iss::status riscv_hart_mu_p<BASE, PMP>::write | 
		
	
		
			
				|  |  |  |  |     return (this->*(it->second))(addr, val); | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | template <typename BASE, bool PMP> iss::status riscv_hart_mu_p<BASE, PMP>::read_reg(unsigned addr, reg_t &val) { | 
		
	
		
			
				|  |  |  |  | template <typename BASE, features_e FEAT> iss::status riscv_hart_mu_p<BASE, FEAT>::read_reg(unsigned addr, reg_t &val) { | 
		
	
		
			
				|  |  |  |  |     val = csr[addr]; | 
		
	
		
			
				|  |  |  |  |     return iss::Ok; | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | template <typename BASE, bool PMP> iss::status riscv_hart_mu_p<BASE, PMP>::write_reg(unsigned addr, reg_t val) { | 
		
	
		
			
				|  |  |  |  | template <typename BASE, features_e FEAT> iss::status riscv_hart_mu_p<BASE, FEAT>::write_reg(unsigned addr, reg_t val) { | 
		
	
		
			
				|  |  |  |  |     csr[addr] = val; | 
		
	
		
			
				|  |  |  |  |     return iss::Ok; | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | template <typename BASE, bool PMP> iss::status riscv_hart_mu_p<BASE, PMP>::read_cycle(unsigned addr, reg_t &val) { | 
		
	
		
			
				|  |  |  |  | template <typename BASE, features_e FEAT> iss::status riscv_hart_mu_p<BASE, FEAT>::read_cycle(unsigned addr, reg_t &val) { | 
		
	
		
			
				|  |  |  |  |     auto cycle_val = this->reg.icount + cycle_offset; | 
		
	
		
			
				|  |  |  |  |     if (addr == mcycle) { | 
		
	
		
			
				|  |  |  |  |         val = static_cast<reg_t>(cycle_val); | 
		
	
	
		
			
				
					
					|  |  |  | @@ -582,7 +601,7 @@ template <typename BASE, bool PMP> iss::status riscv_hart_mu_p<BASE, PMP>::read_ | 
		
	
		
			
				|  |  |  |  |     return iss::Ok; | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | template <typename BASE, bool PMP> iss::status riscv_hart_mu_p<BASE, PMP>::read_time(unsigned addr, reg_t &val) { | 
		
	
		
			
				|  |  |  |  | template <typename BASE, features_e FEAT> iss::status riscv_hart_mu_p<BASE, FEAT>::read_time(unsigned addr, reg_t &val) { | 
		
	
		
			
				|  |  |  |  |     uint64_t time_val = (this->reg.icount + cycle_offset) / (100000000 / 32768 - 1); //-> ~3052; | 
		
	
		
			
				|  |  |  |  |     if (addr == time) { | 
		
	
		
			
				|  |  |  |  |         val = static_cast<reg_t>(time_val); | 
		
	
	
		
			
				
					
					|  |  |  | @@ -593,31 +612,31 @@ template <typename BASE, bool PMP> iss::status riscv_hart_mu_p<BASE, PMP>::read_ | 
		
	
		
			
				|  |  |  |  |     return iss::Ok; | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | template <typename BASE, bool PMP> iss::status riscv_hart_mu_p<BASE, PMP>::read_status(unsigned addr, reg_t &val) { | 
		
	
		
			
				|  |  |  |  | template <typename BASE, features_e FEAT> iss::status riscv_hart_mu_p<BASE, FEAT>::read_status(unsigned addr, reg_t &val) { | 
		
	
		
			
				|  |  |  |  |     auto req_priv_lvl = (addr >> 8) & 0x3; | 
		
	
		
			
				|  |  |  |  |     val = state.mstatus & hart_state_type::get_mask(req_priv_lvl); | 
		
	
		
			
				|  |  |  |  |     return iss::Ok; | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | template <typename BASE, bool PMP> iss::status riscv_hart_mu_p<BASE, PMP>::write_status(unsigned addr, reg_t val) { | 
		
	
		
			
				|  |  |  |  | template <typename BASE, features_e FEAT> iss::status riscv_hart_mu_p<BASE, FEAT>::write_status(unsigned addr, reg_t val) { | 
		
	
		
			
				|  |  |  |  |     auto req_priv_lvl = (addr >> 8) & 0x3; | 
		
	
		
			
				|  |  |  |  |     state.write_mstatus(val, req_priv_lvl); | 
		
	
		
			
				|  |  |  |  |     check_interrupt(); | 
		
	
		
			
				|  |  |  |  |     return iss::Ok; | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | template <typename BASE, bool PMP> iss::status riscv_hart_mu_p<BASE, PMP>::read_ie(unsigned addr, reg_t &val) { | 
		
	
		
			
				|  |  |  |  | template <typename BASE, features_e FEAT> iss::status riscv_hart_mu_p<BASE, FEAT>::read_ie(unsigned addr, reg_t &val) { | 
		
	
		
			
				|  |  |  |  |     val = csr[mie]; | 
		
	
		
			
				|  |  |  |  |     val &= csr[mideleg]; | 
		
	
		
			
				|  |  |  |  |     return iss::Ok; | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | template <typename BASE, bool PMP> iss::status riscv_hart_mu_p<BASE, PMP>::read_hartid(unsigned addr, reg_t &val) { | 
		
	
		
			
				|  |  |  |  | template <typename BASE, features_e FEAT> iss::status riscv_hart_mu_p<BASE, FEAT>::read_hartid(unsigned addr, reg_t &val) { | 
		
	
		
			
				|  |  |  |  |     val = mhartid_reg; | 
		
	
		
			
				|  |  |  |  |     return iss::Ok; | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | template <typename BASE, bool PMP> iss::status riscv_hart_mu_p<BASE, PMP>::write_ie(unsigned addr, reg_t val) { | 
		
	
		
			
				|  |  |  |  | template <typename BASE, features_e FEAT> iss::status riscv_hart_mu_p<BASE, FEAT>::write_ie(unsigned addr, reg_t val) { | 
		
	
		
			
				|  |  |  |  |     auto req_priv_lvl = (addr >> 8) & 0x3; | 
		
	
		
			
				|  |  |  |  |     auto mask = get_irq_mask(req_priv_lvl); | 
		
	
		
			
				|  |  |  |  |     csr[mie] = (csr[mie] & ~mask) | (val & mask); | 
		
	
	
		
			
				
					
					|  |  |  | @@ -625,13 +644,13 @@ template <typename BASE, bool PMP> iss::status riscv_hart_mu_p<BASE, PMP>::write | 
		
	
		
			
				|  |  |  |  |     return iss::Ok; | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | template <typename BASE, bool PMP> iss::status riscv_hart_mu_p<BASE, PMP>::read_ip(unsigned addr, reg_t &val) { | 
		
	
		
			
				|  |  |  |  | template <typename BASE, features_e FEAT> iss::status riscv_hart_mu_p<BASE, FEAT>::read_ip(unsigned addr, reg_t &val) { | 
		
	
		
			
				|  |  |  |  |     val = csr[mip]; | 
		
	
		
			
				|  |  |  |  |     val &= csr[mideleg]; | 
		
	
		
			
				|  |  |  |  |     return iss::Ok; | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | template <typename BASE, bool PMP> iss::status riscv_hart_mu_p<BASE, PMP>::write_ip(unsigned addr, reg_t val) { | 
		
	
		
			
				|  |  |  |  | template <typename BASE, features_e FEAT> iss::status riscv_hart_mu_p<BASE, FEAT>::write_ip(unsigned addr, reg_t val) { | 
		
	
		
			
				|  |  |  |  |     auto req_priv_lvl = (addr >> 8) & 0x3; | 
		
	
		
			
				|  |  |  |  |     auto mask = get_irq_mask(req_priv_lvl); | 
		
	
		
			
				|  |  |  |  |     mask &= ~(1 << 7); // MTIP is read only | 
		
	
	
		
			
				
					
					|  |  |  | @@ -640,8 +659,8 @@ template <typename BASE, bool PMP> iss::status riscv_hart_mu_p<BASE, PMP>::write | 
		
	
		
			
				|  |  |  |  |     return iss::Ok; | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | template <typename BASE, bool PMP> | 
		
	
		
			
				|  |  |  |  | iss::status riscv_hart_mu_p<BASE, PMP>::read_mem(phys_addr_t paddr, unsigned length, uint8_t *const data) { | 
		
	
		
			
				|  |  |  |  | template <typename BASE, features_e FEAT> | 
		
	
		
			
				|  |  |  |  | iss::status riscv_hart_mu_p<BASE, FEAT>::read_mem(phys_addr_t paddr, unsigned length, uint8_t *const data) { | 
		
	
		
			
				|  |  |  |  |     if ((paddr.val + length) > mem.size()) return iss::Err; | 
		
	
		
			
				|  |  |  |  |     if(mem_read_cb) return mem_read_cb(paddr, length, data); | 
		
	
		
			
				|  |  |  |  |     switch (paddr.val) { | 
		
	
	
		
			
				
					
					|  |  |  | @@ -666,8 +685,8 @@ iss::status riscv_hart_mu_p<BASE, PMP>::read_mem(phys_addr_t paddr, unsigned len | 
		
	
		
			
				|  |  |  |  |     return iss::Ok; | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | template <typename BASE, bool PMP> | 
		
	
		
			
				|  |  |  |  | iss::status riscv_hart_mu_p<BASE, PMP>::write_mem(phys_addr_t paddr, unsigned length, const uint8_t *const data) { | 
		
	
		
			
				|  |  |  |  | template <typename BASE, features_e FEAT> | 
		
	
		
			
				|  |  |  |  | iss::status riscv_hart_mu_p<BASE, FEAT>::write_mem(phys_addr_t paddr, unsigned length, const uint8_t *const data) { | 
		
	
		
			
				|  |  |  |  |     if ((paddr.val + length) > mem.size()) return iss::Err; | 
		
	
		
			
				|  |  |  |  |     if(mem_write_cb) return mem_write_cb(paddr, length, data); | 
		
	
		
			
				|  |  |  |  |     switch (paddr.val) { | 
		
	
	
		
			
				
					
					|  |  |  | @@ -743,12 +762,12 @@ iss::status riscv_hart_mu_p<BASE, PMP>::write_mem(phys_addr_t paddr, unsigned le | 
		
	
		
			
				|  |  |  |  |     return iss::Ok; | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | template <typename BASE, bool PMP> inline void riscv_hart_mu_p<BASE, PMP>::reset(uint64_t address) { | 
		
	
		
			
				|  |  |  |  | template <typename BASE, features_e FEAT> inline void riscv_hart_mu_p<BASE, FEAT>::reset(uint64_t address) { | 
		
	
		
			
				|  |  |  |  |     BASE::reset(address); | 
		
	
		
			
				|  |  |  |  |     state.mstatus = hart_state_type::mstatus_reset_val; | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | template <typename BASE, bool PMP> void riscv_hart_mu_p<BASE, PMP>::check_interrupt() { | 
		
	
		
			
				|  |  |  |  | template <typename BASE, features_e FEAT> void riscv_hart_mu_p<BASE, FEAT>::check_interrupt() { | 
		
	
		
			
				|  |  |  |  |     auto ideleg = csr[mideleg]; | 
		
	
		
			
				|  |  |  |  |     // Multiple simultaneous interrupts and traps at the same privilege level are | 
		
	
		
			
				|  |  |  |  |     // handled in the following decreasing priority order: | 
		
	
	
		
			
				
					
					|  |  |  | @@ -770,7 +789,7 @@ template <typename BASE, bool PMP> void riscv_hart_mu_p<BASE, PMP>::check_interr | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | template <typename BASE, bool PMP> uint64_t riscv_hart_mu_p<BASE, PMP>::enter_trap(uint64_t flags, uint64_t addr) { | 
		
	
		
			
				|  |  |  |  | template <typename BASE, features_e FEAT> uint64_t riscv_hart_mu_p<BASE, FEAT>::enter_trap(uint64_t flags, uint64_t addr) { | 
		
	
		
			
				|  |  |  |  |     // flags are ACTIVE[31:31], CAUSE[30:16], TRAPID[15:0] | 
		
	
		
			
				|  |  |  |  |     // calculate and write mcause val | 
		
	
		
			
				|  |  |  |  |     auto trap_id = bit_sub<0, 16>(flags); | 
		
	
	
		
			
				
					
					|  |  |  | @@ -840,10 +859,10 @@ template <typename BASE, bool PMP> uint64_t riscv_hart_mu_p<BASE, PMP>::enter_tr | 
		
	
		
			
				|  |  |  |  |     return this->reg.NEXT_PC; | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | template <typename BASE, bool PMP> uint64_t riscv_hart_mu_p<BASE, PMP>::leave_trap(uint64_t flags) { | 
		
	
		
			
				|  |  |  |  | template <typename BASE, features_e FEAT> uint64_t riscv_hart_mu_p<BASE, FEAT>::leave_trap(uint64_t flags) { | 
		
	
		
			
				|  |  |  |  |     auto cur_priv = this->reg.PRIV; | 
		
	
		
			
				|  |  |  |  |     auto inst_priv = (flags & 0x3)? 3:0; | 
		
	
		
			
				|  |  |  |  |     auto status = state.mstatus; | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  |     // pop the relevant lower-privilege interrupt enable and privilege mode stack | 
		
	
		
			
				|  |  |  |  |     // clear respective yIE | 
		
	
		
			
				|  |  |  |  |     switch (inst_priv) { | 
		
	
	
		
			
				
					
					|  |  |  | @@ -859,7 +878,7 @@ template <typename BASE, bool PMP> uint64_t riscv_hart_mu_p<BASE, PMP>::leave_tr | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
		
			
				|  |  |  |  |     // sets the pc to the value stored in the x epc register. | 
		
	
		
			
				|  |  |  |  |     this->reg.NEXT_PC = csr[uepc | inst_priv << 8]; | 
		
	
		
			
				|  |  |  |  |     CLOG(INFO, disass) << "Executing xRET , changing privilege level from " << lvl[this->reg.PRIV] << " to " | 
		
	
		
			
				|  |  |  |  |     CLOG(INFO, disass) << "Executing xRET , changing privilege level from " << lvl[cur_priv] << " to " | 
		
	
		
			
				|  |  |  |  |                        << lvl[this->reg.PRIV]; | 
		
	
		
			
				|  |  |  |  |     return this->reg.NEXT_PC; | 
		
	
		
			
				|  |  |  |  | } | 
		
	
	
		
			
				
					
					|  |  |  |   |