Compare commits
	
		
			1 Commits
		
	
	
		
			af887c286f
			...
			d95846a849
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| d95846a849 | 
| @@ -296,6 +296,10 @@ inline bool is_count_limit_enabled(finish_cond_e cond){ | |||||||
|     return (cond & finish_cond_e::COUNT_LIMIT) == finish_cond_e::COUNT_LIMIT; |     return (cond & finish_cond_e::COUNT_LIMIT) == finish_cond_e::COUNT_LIMIT; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | inline bool is_jump_to_self_enabled(finish_cond_e cond){ | ||||||
|  |     return (cond & finish_cond_e::JUMP_TO_SELF) == finish_cond_e::JUMP_TO_SELF; | ||||||
|  | } | ||||||
|  |  | ||||||
| template <typename ARCH> | template <typename ARCH> | ||||||
| typename vm_impl<ARCH>::compile_func vm_impl<ARCH>::decode_inst(code_word_t instr){ | typename vm_impl<ARCH>::compile_func vm_impl<ARCH>::decode_inst(code_word_t instr){ | ||||||
|     for(auto& e: qlut[instr&0x3]){ |     for(auto& e: qlut[instr&0x3]){ | ||||||
| @@ -307,7 +311,6 @@ typename vm_impl<ARCH>::compile_func vm_impl<ARCH>::decode_inst(code_word_t inst | |||||||
| template <typename ARCH> | template <typename ARCH> | ||||||
| typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e cond, virt_addr_t start, uint64_t icount_limit){ | typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e cond, virt_addr_t start, uint64_t icount_limit){ | ||||||
|     // we fetch at max 4 byte, alignment is 2 |     // we fetch at max 4 byte, alignment is 2 | ||||||
|     enum {TRAP_ID=1<<16}; |  | ||||||
|     code_word_t insn = 0; |     code_word_t insn = 0; | ||||||
|     auto *const data = (uint8_t *)&insn; |     auto *const data = (uint8_t *)&insn; | ||||||
|     auto pc=start; |     auto pc=start; | ||||||
| @@ -315,14 +318,14 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co | |||||||
|             !(is_count_limit_enabled(cond) && this->core.get_icount() >= icount_limit)){ |             !(is_count_limit_enabled(cond) && this->core.get_icount() >= icount_limit)){ | ||||||
|         auto res = fetch_ins(pc, data); |         auto res = fetch_ins(pc, data); | ||||||
|         if(res!=iss::Ok){ |         if(res!=iss::Ok){ | ||||||
|             auto new_pc = super::core.enter_trap(TRAP_ID, pc.val, 0); |             this->do_sync(POST_SYNC, std::numeric_limits<unsigned>::max()); | ||||||
|             res = fetch_ins(virt_addr_t{access_type::FETCH, new_pc}, data); |             pc.val = super::core.enter_trap(std::numeric_limits<uint64_t>::max(), pc.val, 0); | ||||||
|             if(res!=iss::Ok) throw simulation_stopped(0); |         } else { | ||||||
|  |             if (is_jump_to_self_enabled(cond) && | ||||||
|  |                     (insn == 0x0000006f || (insn&0xffff)==0xa001)) throw simulation_stopped(0); // 'J 0' or 'C.J 0' | ||||||
|  |             auto f = decode_inst(insn); | ||||||
|  |             pc = (this->*f)(pc, insn); | ||||||
|         } |         } | ||||||
|         if ((cond & finish_cond_e::JUMP_TO_SELF) == finish_cond_e::JUMP_TO_SELF && |  | ||||||
|                 (insn == 0x0000006f || (insn&0xffff)==0xa001)) throw simulation_stopped(0); // 'J 0' or 'C.J 0' |  | ||||||
|         auto f = decode_inst(insn); |  | ||||||
|         pc = (this->*f)(pc, insn); |  | ||||||
|     } |     } | ||||||
|     return pc; |     return pc; | ||||||
| } | } | ||||||
|   | |||||||
| @@ -280,7 +280,7 @@ private: | |||||||
|     iss::status write_cycle(unsigned addr, reg_t val); |     iss::status write_cycle(unsigned addr, reg_t val); | ||||||
|     iss::status read_instret(unsigned addr, reg_t &val); |     iss::status read_instret(unsigned addr, reg_t &val); | ||||||
|     iss::status write_instret(unsigned addr, reg_t val); |     iss::status write_instret(unsigned addr, reg_t val); | ||||||
|     iss::status read_mtvec(unsigned addr, reg_t &val); |     iss::status read_tvec(unsigned addr, reg_t &val); | ||||||
|     iss::status read_time(unsigned addr, reg_t &val); |     iss::status read_time(unsigned addr, reg_t &val); | ||||||
|     iss::status read_status(unsigned addr, reg_t &val); |     iss::status read_status(unsigned addr, reg_t &val); | ||||||
|     iss::status write_status(unsigned addr, reg_t val); |     iss::status write_status(unsigned addr, reg_t val); | ||||||
| @@ -290,7 +290,7 @@ private: | |||||||
|     iss::status read_ip(unsigned addr, reg_t &val); |     iss::status read_ip(unsigned addr, reg_t &val); | ||||||
|     iss::status write_ip(unsigned addr, reg_t val); |     iss::status write_ip(unsigned addr, reg_t val); | ||||||
|     iss::status read_hartid(unsigned addr, reg_t &val); |     iss::status read_hartid(unsigned addr, reg_t &val); | ||||||
|     iss::status write_mepc(unsigned addr, reg_t val); |     iss::status write_epc(unsigned addr, reg_t val); | ||||||
|  |  | ||||||
|     reg_t mhartid_reg{0x0}; |     reg_t mhartid_reg{0x0}; | ||||||
|     std::function<iss::status(phys_addr_t, unsigned, uint8_t *const)>mem_read_cb; |     std::function<iss::status(phys_addr_t, unsigned, uint8_t *const)>mem_read_cb; | ||||||
| @@ -355,6 +355,8 @@ riscv_hart_m_p<BASE>::riscv_hart_m_p() | |||||||
|     csr_rd_cb[mstatus] = &this_class::read_status; |     csr_rd_cb[mstatus] = &this_class::read_status; | ||||||
|     csr_wr_cb[mstatus] = &this_class::write_status; |     csr_wr_cb[mstatus] = &this_class::write_status; | ||||||
|     csr_wr_cb[mcause] = &this_class::write_cause; |     csr_wr_cb[mcause] = &this_class::write_cause; | ||||||
|  |     csr_rd_cb[mtvec] = &this_class::read_tvec; | ||||||
|  |     csr_wr_cb[mepc] = &this_class::write_epc; | ||||||
|     csr_rd_cb[mip] = &this_class::read_ip; |     csr_rd_cb[mip] = &this_class::read_ip; | ||||||
|     csr_wr_cb[mip] = &this_class::write_ip; |     csr_wr_cb[mip] = &this_class::write_ip; | ||||||
|     csr_rd_cb[mie] = &this_class::read_ie; |     csr_rd_cb[mie] = &this_class::read_ie; | ||||||
| @@ -362,8 +364,6 @@ riscv_hart_m_p<BASE>::riscv_hart_m_p() | |||||||
|     csr_rd_cb[mhartid] = &this_class::read_hartid; |     csr_rd_cb[mhartid] = &this_class::read_hartid; | ||||||
|     csr_rd_cb[mcounteren] = &this_class::read_null; |     csr_rd_cb[mcounteren] = &this_class::read_null; | ||||||
|     csr_wr_cb[mcounteren] = &this_class::write_null; |     csr_wr_cb[mcounteren] = &this_class::write_null; | ||||||
|     csr_rd_cb[mtvec] = &this_class::read_mtvec; |  | ||||||
|     csr_wr_cb[mepc] = &this_class::write_mepc; |  | ||||||
|     csr_wr_cb[misa] = &this_class::write_null; |     csr_wr_cb[misa] = &this_class::write_null; | ||||||
|     csr_wr_cb[mvendorid] = &this_class::write_null; |     csr_wr_cb[mvendorid] = &this_class::write_null; | ||||||
|     csr_wr_cb[marchid] = &this_class::write_null; |     csr_wr_cb[marchid] = &this_class::write_null; | ||||||
| @@ -702,7 +702,7 @@ template <typename BASE> iss::status riscv_hart_m_p<BASE>::read_time(unsigned ad | |||||||
|     return iss::Ok; |     return iss::Ok; | ||||||
| } | } | ||||||
|  |  | ||||||
| template <typename BASE> iss::status riscv_hart_m_p<BASE>::read_mtvec(unsigned addr, reg_t &val) { | template <typename BASE> iss::status riscv_hart_m_p<BASE>::read_tvec(unsigned addr, reg_t &val) { | ||||||
|     val = csr[mtvec] & ~2; |     val = csr[mtvec] & ~2; | ||||||
|     return iss::Ok; |     return iss::Ok; | ||||||
| } | } | ||||||
| @@ -753,7 +753,7 @@ template <typename BASE> iss::status riscv_hart_m_p<BASE>::write_ip(unsigned add | |||||||
|     return iss::Ok; |     return iss::Ok; | ||||||
| } | } | ||||||
|  |  | ||||||
| template <typename BASE> iss::status riscv_hart_m_p<BASE>::write_mepc(unsigned addr, reg_t val) { | template <typename BASE> iss::status riscv_hart_m_p<BASE>::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; | ||||||
| } | } | ||||||
|   | |||||||
| @@ -478,6 +478,12 @@ riscv_hart_msu_vp<BASE>::riscv_hart_msu_vp() | |||||||
|     csr_rd_cb[ustatus] = &this_class::read_status; |     csr_rd_cb[ustatus] = &this_class::read_status; | ||||||
|     csr_wr_cb[ustatus] = &this_class::write_status; |     csr_wr_cb[ustatus] = &this_class::write_status; | ||||||
|     csr_wr_cb[ucause] = &this_class::write_cause; |     csr_wr_cb[ucause] = &this_class::write_cause; | ||||||
|  |     csr_rd_cb[mtvec] = &this_class::read_tvec; | ||||||
|  |     csr_rd_cb[stvec] = &this_class::read_tvec; | ||||||
|  |     csr_rd_cb[utvec] = &this_class::read_tvec; | ||||||
|  |     csr_wr_cb[mepc] = &this_class::write_epc; | ||||||
|  |     csr_wr_cb[sepc] = &this_class::write_epc; | ||||||
|  |     csr_wr_cb[uepc] = &this_class::write_epc; | ||||||
|     csr_rd_cb[mip] = &this_class::read_ip; |     csr_rd_cb[mip] = &this_class::read_ip; | ||||||
|     csr_wr_cb[mip] = &this_class::write_ip; |     csr_wr_cb[mip] = &this_class::write_ip; | ||||||
|     csr_rd_cb[sip] = &this_class::read_ip; |     csr_rd_cb[sip] = &this_class::read_ip; | ||||||
| @@ -493,8 +499,6 @@ riscv_hart_msu_vp<BASE>::riscv_hart_msu_vp() | |||||||
|     csr_rd_cb[mhartid] = &this_class::read_hartid; |     csr_rd_cb[mhartid] = &this_class::read_hartid; | ||||||
|     csr_rd_cb[mcounteren] = &this_class::read_null; |     csr_rd_cb[mcounteren] = &this_class::read_null; | ||||||
|     csr_wr_cb[mcounteren] = &this_class::write_null; |     csr_wr_cb[mcounteren] = &this_class::write_null; | ||||||
|     csr_rd_cb[mtvec] = &this_class::read_mtvec; |  | ||||||
|     csr_wr_cb[mepc] = &this_class::write_mepc; |  | ||||||
|     csr_wr_cb[misa] = &this_class::write_null; |     csr_wr_cb[misa] = &this_class::write_null; | ||||||
|     csr_wr_cb[mvendorid] = &this_class::write_null; |     csr_wr_cb[mvendorid] = &this_class::write_null; | ||||||
|     csr_wr_cb[marchid] = &this_class::write_null; |     csr_wr_cb[marchid] = &this_class::write_null; | ||||||
| @@ -868,8 +872,8 @@ template <typename BASE> iss::status riscv_hart_m_p<BASE>::read_time(unsigned ad | |||||||
|     return iss::Ok; |     return iss::Ok; | ||||||
| } | } | ||||||
|  |  | ||||||
| template <typename BASE> iss::status riscv_hart_m_p<BASE>::read_mtvec(unsigned addr, reg_t &val) { | template <typename BASE> iss::status riscv_hart_m_p<BASE>::read_tvec(unsigned addr, reg_t &val) { | ||||||
|     val = csr[mtvec] & ~2; |     val = csr[addr] & ~2; | ||||||
|     return iss::Ok; |     return iss::Ok; | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -928,9 +932,8 @@ template <typename BASE> iss::status riscv_hart_msu_vp<BASE>::write_ip(unsigned | |||||||
|     return iss::Ok; |     return iss::Ok; | ||||||
| } | } | ||||||
|  |  | ||||||
| template <typename BASE> iss::status riscv_hart_m_p<BASE>::write_mepc(unsigned addr, reg_t val) { | template <typename BASE> iss::status riscv_hart_m_p<BASE>::write_epc(unsigned addr, reg_t val) { | ||||||
|     auto mask = get_pc_mask(); |      csr[addr] = val & get_pc_mask(); | ||||||
|     csr[addr] = val;//(csr[addr] & ~mask) | (val & mask); |  | ||||||
|     return iss::Ok; |     return iss::Ok; | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -297,7 +297,7 @@ private: | |||||||
|     iss::status write_cycle(unsigned addr, reg_t val); |     iss::status write_cycle(unsigned addr, reg_t val); | ||||||
|     iss::status read_instret(unsigned addr, reg_t &val); |     iss::status read_instret(unsigned addr, reg_t &val); | ||||||
|     iss::status write_instret(unsigned addr, reg_t val); |     iss::status write_instret(unsigned addr, reg_t val); | ||||||
|     iss::status read_mtvec(unsigned addr, reg_t &val); |     iss::status read_tvec(unsigned addr, reg_t &val); | ||||||
|     iss::status read_time(unsigned addr, reg_t &val); |     iss::status read_time(unsigned addr, reg_t &val); | ||||||
|     iss::status read_status(unsigned addr, reg_t &val); |     iss::status read_status(unsigned addr, reg_t &val); | ||||||
|     iss::status write_status(unsigned addr, reg_t val); |     iss::status write_status(unsigned addr, reg_t val); | ||||||
| @@ -307,7 +307,7 @@ private: | |||||||
|     iss::status read_ip(unsigned addr, reg_t &val); |     iss::status read_ip(unsigned addr, reg_t &val); | ||||||
|     iss::status write_ip(unsigned addr, reg_t val); |     iss::status write_ip(unsigned addr, reg_t val); | ||||||
|     iss::status read_hartid(unsigned addr, reg_t &val); |     iss::status read_hartid(unsigned addr, reg_t &val); | ||||||
|     iss::status write_mepc(unsigned addr, reg_t val); |     iss::status write_epc(unsigned addr, reg_t val); | ||||||
|  |  | ||||||
|     reg_t mhartid_reg{0x0}; |     reg_t mhartid_reg{0x0}; | ||||||
|     std::function<iss::status(phys_addr_t, unsigned, uint8_t *const)>mem_read_cb; |     std::function<iss::status(phys_addr_t, unsigned, uint8_t *const)>mem_read_cb; | ||||||
| @@ -315,6 +315,7 @@ private: | |||||||
|  |  | ||||||
| protected: | protected: | ||||||
|     void check_interrupt(); |     void check_interrupt(); | ||||||
|  |     bool pmp_check(const access_type type, const uint64_t addr, const unsigned len); | ||||||
| }; | }; | ||||||
|  |  | ||||||
| template <typename BASE, features_e FEAT> | template <typename BASE, features_e FEAT> | ||||||
| @@ -326,6 +327,7 @@ riscv_hart_mu_p<BASE, FEAT>::riscv_hart_mu_p() | |||||||
|     csr[mvendorid] = 0x669; |     csr[mvendorid] = 0x669; | ||||||
|     csr[marchid] = 0x80000003; |     csr[marchid] = 0x80000003; | ||||||
|     csr[mimpid] = 1; |     csr[mimpid] = 1; | ||||||
|  |     csr[mclicbase] = 0xc0000000; // TODO: should be taken from YAML file | ||||||
|  |  | ||||||
|     uart_buf.str(""); |     uart_buf.str(""); | ||||||
|     for (unsigned addr = mhpmcounter3; addr <= mhpmcounter31; ++addr){ |     for (unsigned addr = mhpmcounter3; addr <= mhpmcounter31; ++addr){ | ||||||
| @@ -348,7 +350,11 @@ riscv_hart_mu_p<BASE, FEAT>::riscv_hart_mu_p() | |||||||
|         //csr_wr_cb[addr] = &this_class::write_reg; |         //csr_wr_cb[addr] = &this_class::write_reg; | ||||||
|     } |     } | ||||||
|     // common regs |     // common regs | ||||||
|     const std::array<unsigned, 10> addrs{{misa, mvendorid, marchid, mimpid, mepc, mtvec, mscratch, mcause, mtval, mscratch}}; |     const std::array<unsigned, 14> addrs{{ | ||||||
|  |         misa, mvendorid, marchid, mimpid, | ||||||
|  |         mepc, mtvec, mscratch, mcause, mtval, | ||||||
|  |         uepc, utvec, uscratch, ucause, utval, | ||||||
|  |     }}; | ||||||
|     for(auto addr: addrs) { |     for(auto addr: addrs) { | ||||||
|         csr_rd_cb[addr] = &this_class::read_reg; |         csr_rd_cb[addr] = &this_class::read_reg; | ||||||
|         csr_wr_cb[addr] = &this_class::write_reg; |         csr_wr_cb[addr] = &this_class::write_reg; | ||||||
| @@ -375,6 +381,10 @@ riscv_hart_mu_p<BASE, FEAT>::riscv_hart_mu_p() | |||||||
|     csr_rd_cb[ustatus] = &this_class::read_status; |     csr_rd_cb[ustatus] = &this_class::read_status; | ||||||
|     csr_wr_cb[ustatus] = &this_class::write_status; |     csr_wr_cb[ustatus] = &this_class::write_status; | ||||||
|     csr_wr_cb[ucause] = &this_class::write_cause; |     csr_wr_cb[ucause] = &this_class::write_cause; | ||||||
|  |     csr_rd_cb[mtvec] = &this_class::read_tvec; | ||||||
|  |     csr_rd_cb[utvec] = &this_class::read_tvec; | ||||||
|  |     csr_wr_cb[mepc] = &this_class::write_epc; | ||||||
|  |     csr_wr_cb[uepc] = &this_class::write_epc; | ||||||
|     csr_rd_cb[mip] = &this_class::read_ip; |     csr_rd_cb[mip] = &this_class::read_ip; | ||||||
|     csr_wr_cb[mip] = &this_class::write_ip; |     csr_wr_cb[mip] = &this_class::write_ip; | ||||||
|     csr_rd_cb[uip] = &this_class::read_ip; |     csr_rd_cb[uip] = &this_class::read_ip; | ||||||
| @@ -386,8 +396,6 @@ riscv_hart_mu_p<BASE, FEAT>::riscv_hart_mu_p() | |||||||
|     csr_rd_cb[mhartid] = &this_class::read_hartid; |     csr_rd_cb[mhartid] = &this_class::read_hartid; | ||||||
|     csr_rd_cb[mcounteren] = &this_class::read_null; |     csr_rd_cb[mcounteren] = &this_class::read_null; | ||||||
|     csr_wr_cb[mcounteren] = &this_class::write_null; |     csr_wr_cb[mcounteren] = &this_class::write_null; | ||||||
|     csr_rd_cb[mtvec] = &this_class::read_mtvec; |  | ||||||
|     csr_wr_cb[mepc] = &this_class::write_mepc; |  | ||||||
|     csr_wr_cb[misa] = &this_class::write_null; |     csr_wr_cb[misa] = &this_class::write_null; | ||||||
|     csr_wr_cb[mvendorid] = &this_class::write_null; |     csr_wr_cb[mvendorid] = &this_class::write_null; | ||||||
|     csr_wr_cb[marchid] = &this_class::write_null; |     csr_wr_cb[marchid] = &this_class::write_null; | ||||||
| @@ -423,7 +431,7 @@ riscv_hart_mu_p<BASE, FEAT>::riscv_hart_mu_p() | |||||||
|         csr_rd_cb[mintthresh] = &this_class::read_reg; |         csr_rd_cb[mintthresh] = &this_class::read_reg; | ||||||
|         csr_wr_cb[mintthresh] = &this_class::write_reg; |         csr_wr_cb[mintthresh] = &this_class::write_reg; | ||||||
|         csr_rd_cb[mclicbase] = &this_class::read_reg; |         csr_rd_cb[mclicbase] = &this_class::read_reg; | ||||||
|         csr_wr_cb[mclicbase] = &this_class::write_reg; |         csr_wr_cb[mclicbase] = &this_class::write_null; | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -471,6 +479,54 @@ template <typename BASE, features_e FEAT> std::pair<uint64_t, bool> riscv_hart_m | |||||||
|     throw std::runtime_error("memory load file not found"); |     throw std::runtime_error("memory load file not found"); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | template <typename BASE, features_e FEAT> bool riscv_hart_mu_p<BASE, FEAT>::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; | ||||||
|  |     reg_t base = 0; | ||||||
|  |     for (size_t i = 0; i < 16; i++) { | ||||||
|  |         reg_t tor = csr[pmpaddr0+i] << PMP_SHIFT; | ||||||
|  |         uint8_t cfg = csr[pmpcfg0+(i/4)]>>(i%4); | ||||||
|  |         if (cfg & PMP_A) { | ||||||
|  |             bool is_tor = (cfg & PMP_A) == PMP_TOR; | ||||||
|  |             bool is_na4 = (cfg & PMP_A) == PMP_NA4; | ||||||
|  |  | ||||||
|  |             reg_t mask = (csr[pmpaddr0+i] << 1) | (!is_na4); | ||||||
|  |             mask = ~(mask & ~(mask + 1)) << PMP_SHIFT; | ||||||
|  |  | ||||||
|  |             // Check each 4-byte sector of the access | ||||||
|  |             bool any_match = false; | ||||||
|  |             bool all_match = true; | ||||||
|  |             for (reg_t offset = 0; offset < len; offset += 1 << PMP_SHIFT) { | ||||||
|  |                 reg_t cur_addr = addr + offset; | ||||||
|  |                 bool napot_match = ((cur_addr ^ tor) & mask) == 0; | ||||||
|  |                 bool tor_match = base <= cur_addr && cur_addr < tor; | ||||||
|  |                 bool match = is_tor ? tor_match : napot_match; | ||||||
|  |                 any_match |= match; | ||||||
|  |                 all_match &= match; | ||||||
|  |             } | ||||||
|  |             if (any_match) { | ||||||
|  |                 // If the PMP matches only a strict subset of the access, fail it | ||||||
|  |                 if (!all_match) | ||||||
|  |                     return false; | ||||||
|  |                 return  (this->reg.PRIV == 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)); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         base = tor; | ||||||
|  |     } | ||||||
|  |     return this->reg.PRIV == PRIV_M; | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
| template <typename BASE, features_e FEAT> | 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, | 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) { |         const uint64_t addr, const unsigned length, uint8_t *const data) { | ||||||
| @@ -486,6 +542,14 @@ iss::status riscv_hart_mu_p<BASE, FEAT>::read(const address_type type, const acc | |||||||
|     try { |     try { | ||||||
|         switch (space) { |         switch (space) { | ||||||
|         case traits<BASE>::MEM: { |         case traits<BASE>::MEM: { | ||||||
|  |             if(FEAT & FEAT_PMP){ | ||||||
|  |                 if(!pmp_check(access, addr, length)) { | ||||||
|  |                     fault_data = addr; | ||||||
|  |                     if (access && iss::access_type::DEBUG) throw trap_access(0, addr); | ||||||
|  |                     this->reg.trap_state = (1 << 31) | (1 << 16); // issue trap 1 | ||||||
|  |                     return iss::Err; | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|             if (unlikely((access == iss::access_type::FETCH || access == iss::access_type::DEBUG_FETCH) && (addr & 0x1) == 1)) { |             if (unlikely((access == iss::access_type::FETCH || access == iss::access_type::DEBUG_FETCH) && (addr & 0x1) == 1)) { | ||||||
|                 fault_data = addr; |                 fault_data = addr; | ||||||
|                 if (access && iss::access_type::DEBUG) throw trap_access(0, addr); |                 if (access && iss::access_type::DEBUG) throw trap_access(0, addr); | ||||||
| @@ -569,6 +633,14 @@ iss::status riscv_hart_mu_p<BASE, FEAT>::write(const address_type type, const ac | |||||||
|     try { |     try { | ||||||
|         switch (space) { |         switch (space) { | ||||||
|         case traits<BASE>::MEM: { |         case traits<BASE>::MEM: { | ||||||
|  |             if(FEAT & FEAT_PMP){ | ||||||
|  |                 if(!pmp_check(access, addr, length)) { | ||||||
|  |                     fault_data = addr; | ||||||
|  |                     if (access && iss::access_type::DEBUG) throw trap_access(0, addr); | ||||||
|  |                     this->reg.trap_state = (1 << 31) | (1 << 16); // issue trap 1 | ||||||
|  |                     return iss::Err; | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|             if (unlikely((access && iss::access_type::FETCH) && (addr & 0x1) == 1)) { |             if (unlikely((access && iss::access_type::FETCH) && (addr & 0x1) == 1)) { | ||||||
|                 fault_data = addr; |                 fault_data = addr; | ||||||
|                 if (access && iss::access_type::DEBUG) throw trap_access(0, addr); |                 if (access && iss::access_type::DEBUG) throw trap_access(0, addr); | ||||||
| @@ -759,8 +831,8 @@ 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_mtvec(unsigned addr, reg_t &val) { | template <typename BASE, features_e FEAT> iss::status riscv_hart_mu_p<BASE, FEAT>::read_tvec(unsigned addr, reg_t &val) { | ||||||
|     val = csr[mtvec] & ~2; |     val = 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> iss::status riscv_hart_mu_p<BASE, FEAT>::read_status(unsigned addr, reg_t &val) { | ||||||
| @@ -815,9 +887,8 @@ 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_mepc(unsigned addr, reg_t val) { | template <typename BASE, features_e FEAT> iss::status riscv_hart_mu_p<BASE, FEAT>::write_epc(unsigned addr, reg_t val) { | ||||||
|     auto mask = get_pc_mask(); |     csr[addr] = val & get_pc_mask(); | ||||||
|     csr[addr] = val;//(csr[addr] & ~mask) | (val & mask); |  | ||||||
|     return iss::Ok; |     return iss::Ok; | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -954,6 +1025,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> uint64_t riscv_hart_mu_p<BASE, FEAT>::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()) flags=this->reg.trap_state; | ||||||
|     auto trap_id = bit_sub<0, 16>(flags); |     auto trap_id = bit_sub<0, 16>(flags); | ||||||
|     auto cause = bit_sub<16, 15>(flags); |     auto cause = bit_sub<16, 15>(flags); | ||||||
|     if (trap_id == 0 && cause == 11) cause = 0x8 + this->reg.PRIV; // adjust environment call cause |     if (trap_id == 0 && cause == 11) cause = 0x8 + this->reg.PRIV; // adjust environment call cause | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user