Compare commits
	
		
			3 Commits
		
	
	
		
			e432dd8208
			...
			23b9741adf
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 23b9741adf | |||
| 5d8da08ce5 | |||
| a249aea703 | 
 Submodule gen_input/CoreDSL-Instruction-Set-Description updated: cf601042ed...0c70a41376
									
								
							| @@ -33,7 +33,7 @@ | |||||||
| def getRegisterSizes(){ | def getRegisterSizes(){ | ||||||
| 	def regs = registers.collect{it.size} | 	def regs = registers.collect{it.size} | ||||||
| 	regs[-1]=64 // correct for NEXT_PC | 	regs[-1]=64 // correct for NEXT_PC | ||||||
| 	regs+=[32, 32, 64] // append TRAP_STATE, PENDING_TRAP, ICOUNT | 	regs+=[32, 32, 64, 64, 64] // append TRAP_STATE, PENDING_TRAP, ICOUNT, CYCLE, INSTRET | ||||||
|     return regs |     return regs | ||||||
| } | } | ||||||
| %> | %> | ||||||
|   | |||||||
| @@ -37,7 +37,7 @@ def nativeTypeSize(int size){ | |||||||
| } | } | ||||||
| def getRegisterSizes(){ | def getRegisterSizes(){ | ||||||
|     def regs = registers.collect{nativeTypeSize(it.size)} |     def regs = registers.collect{nativeTypeSize(it.size)} | ||||||
|     regs+=[32,32, 64] // append TRAP_STATE, PENDING_TRAP, ICOUNT |     regs+=[32,32, 64, 64, 64] // append TRAP_STATE, PENDING_TRAP, ICOUNT, CYCLE, INSTRET | ||||||
|     return regs |     return regs | ||||||
| } | } | ||||||
| def getRegisterOffsets(){ | def getRegisterOffsets(){ | ||||||
| @@ -94,7 +94,9 @@ template <> struct traits<${coreDef.name.toLowerCase()}> { | |||||||
|         ${registers.collect{it.name}.join(', ')}, NUM_REGS, |         ${registers.collect{it.name}.join(', ')}, NUM_REGS, | ||||||
|         TRAP_STATE=NUM_REGS, |         TRAP_STATE=NUM_REGS, | ||||||
|         PENDING_TRAP, |         PENDING_TRAP, | ||||||
|         ICOUNT |         ICOUNT, | ||||||
|  |         CYCLE, | ||||||
|  |         INSTRET | ||||||
|     }; |     }; | ||||||
|  |  | ||||||
|     using reg_t = uint${addrDataWidth}_t; |     using reg_t = uint${addrDataWidth}_t; | ||||||
| @@ -175,6 +177,8 @@ protected: | |||||||
|         }}%> |         }}%> | ||||||
|         uint32_t trap_state = 0, pending_trap = 0; |         uint32_t trap_state = 0, pending_trap = 0; | ||||||
|         uint64_t icount = 0; |         uint64_t icount = 0; | ||||||
|  |         uint64_t cycle = 0; | ||||||
|  |         uint64_t instret = 0; | ||||||
|         uint32_t last_branch; |         uint32_t last_branch; | ||||||
|     } reg; |     } reg; | ||||||
| #pragma pack(pop) | #pragma pack(pop) | ||||||
|   | |||||||
| @@ -219,20 +219,22 @@ private: | |||||||
|     /* instruction ${idx}: ${instr.name} */ |     /* instruction ${idx}: ${instr.name} */ | ||||||
|     compile_ret_t __${generator.functionName(instr.name)}(virt_addr_t& pc, code_word_t instr){ |     compile_ret_t __${generator.functionName(instr.name)}(virt_addr_t& pc, code_word_t instr){ | ||||||
|         // pre execution stuff |         // pre execution stuff | ||||||
|         this->do_sync(PRE_SYNC, ${idx}); |         auto* PC = reinterpret_cast<uint${addrDataWidth}_t*>(this->regs_base_ptr+arch::traits<ARCH>::reg_byte_offsets[arch::traits<ARCH>::PC]); | ||||||
|  |         auto NEXT_PC = reinterpret_cast<uint${addrDataWidth}_t*>(this->regs_base_ptr+arch::traits<ARCH>::reg_byte_offsets[arch::traits<ARCH>::NEXT_PC]); | ||||||
|  |         *PC=*NEXT_PC; | ||||||
|  |         auto* trap_state = reinterpret_cast<uint32_t*>(this->regs_base_ptr+arch::traits<ARCH>::reg_byte_offsets[arch::traits<ARCH>::TRAP_STATE]); | ||||||
|  |         *trap_state = *reinterpret_cast<uint32_t*>(this->regs_base_ptr+arch::traits<ARCH>::reg_byte_offsets[arch::traits<ARCH>::PENDING_TRAP]); | ||||||
|  |         if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, ${idx}); | ||||||
|         <%instr.fields.eachLine{%>${it} |         <%instr.fields.eachLine{%>${it} | ||||||
|         <%}%>if(this->disass_enabled){ |         <%}%>if(this->disass_enabled){ | ||||||
|             /* generate console output when executing the command */ |             /* generate console output when executing the command */ | ||||||
|             <%instr.disass.eachLine{%>${it} |             <%instr.disass.eachLine{%>${it} | ||||||
|             <%}%> |             <%}%> | ||||||
|         } |         } | ||||||
|         // prepare execution |  | ||||||
|         uint${addrDataWidth}_t* PC = reinterpret_cast<uint${addrDataWidth}_t*>(this->regs_base_ptr+arch::traits<ARCH>::reg_byte_offsets[arch::traits<ARCH>::PC]); |  | ||||||
|         uint${addrDataWidth}_t* NEXT_PC = reinterpret_cast<uint${addrDataWidth}_t*>(this->regs_base_ptr+arch::traits<ARCH>::reg_byte_offsets[arch::traits<ARCH>::NEXT_PC]); |  | ||||||
|         // used registers<%instr.usedVariables.each{ k,v-> |         // used registers<%instr.usedVariables.each{ k,v-> | ||||||
|             if(v.isArray) {%> |             if(v.isArray) {%> | ||||||
|         uint${v.type.size}_t* ${k} = reinterpret_cast<uint${v.type.size}_t*>(this->regs_base_ptr+arch::traits<ARCH>::reg_byte_offsets[arch::traits<ARCH>::${k}0]);<% }else{ %>  |         auto* ${k} = reinterpret_cast<uint${v.type.size}_t*>(this->regs_base_ptr+arch::traits<ARCH>::reg_byte_offsets[arch::traits<ARCH>::${k}0]);<% }else{ %>  | ||||||
|         uint${v.type.size}_t* ${k} = reinterpret_cast<uint${v.type.size}_t*>(this->regs_base_ptr+arch::traits<ARCH>::reg_byte_offsets[arch::traits<ARCH>::${k}]); |         auto* ${k} = reinterpret_cast<uint${v.type.size}_t*>(this->regs_base_ptr+arch::traits<ARCH>::reg_byte_offsets[arch::traits<ARCH>::${k}]); | ||||||
|         <%}}%>// calculate next pc value |         <%}}%>// calculate next pc value | ||||||
|         *NEXT_PC = *PC + ${instr.length/8}; |         *NEXT_PC = *PC + ${instr.length/8}; | ||||||
|         // execute instruction |         // execute instruction | ||||||
| @@ -241,11 +243,14 @@ private: | |||||||
|         <%}%>} catch(...){} |         <%}%>} catch(...){} | ||||||
|         // post execution stuff |         // post execution stuff | ||||||
|         if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, ${idx}); |         if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, ${idx}); | ||||||
|         auto* trap_state = reinterpret_cast<uint32_t*>(this->regs_base_ptr+arch::traits<ARCH>::reg_byte_offsets[arch::traits<ARCH>::TRAP_STATE]); |  | ||||||
|         // trap check |         // trap check | ||||||
|         if(*trap_state!=0){ |         if(*trap_state!=0){ | ||||||
|             super::core.enter_trap(*trap_state, pc.val); |             super::core.enter_trap(*trap_state, pc.val, instr); | ||||||
|  |         } else { | ||||||
|  |             (*reinterpret_cast<uint64_t*>(this->regs_base_ptr+arch::traits<ARCH>::reg_byte_offsets[arch::traits<ARCH>::ICOUNT]))++; | ||||||
|  |             (*reinterpret_cast<uint64_t*>(this->regs_base_ptr+arch::traits<ARCH>::reg_byte_offsets[arch::traits<ARCH>::INSTRET]))++; | ||||||
|         } |         } | ||||||
|  |         (*reinterpret_cast<uint64_t*>(this->regs_base_ptr+arch::traits<ARCH>::reg_byte_offsets[arch::traits<ARCH>::CYCLE]))++; | ||||||
|         pc.val=*NEXT_PC; |         pc.val=*NEXT_PC; | ||||||
|         return pc; |         return pc; | ||||||
|     } |     } | ||||||
| @@ -264,7 +269,7 @@ private: | |||||||
|         auto* trap_state = reinterpret_cast<uint32_t*>(this->regs_base_ptr+arch::traits<ARCH>::reg_byte_offsets[arch::traits<ARCH>::TRAP_STATE]); |         auto* trap_state = reinterpret_cast<uint32_t*>(this->regs_base_ptr+arch::traits<ARCH>::reg_byte_offsets[arch::traits<ARCH>::TRAP_STATE]); | ||||||
|         // trap check |         // trap check | ||||||
|         if(*trap_state!=0){ |         if(*trap_state!=0){ | ||||||
|             super::core.enter_trap(*trap_state, pc.val); |             super::core.enter_trap(*trap_state, pc.val, instr); | ||||||
|         } |         } | ||||||
|         pc.val=*NEXT_PC; |         pc.val=*NEXT_PC; | ||||||
|         return pc; |         return pc; | ||||||
| @@ -318,7 +323,7 @@ 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); |             auto new_pc = super::core.enter_trap(TRAP_ID, pc.val, 0); | ||||||
|             res = fetch_ins(virt_addr_t{access_type::FETCH, new_pc}, data); |             res = fetch_ins(virt_addr_t{access_type::FETCH, new_pc}, data); | ||||||
|             if(res!=iss::Ok) throw simulation_stopped(0); |             if(res!=iss::Ok) throw simulation_stopped(0); | ||||||
|         } |         } | ||||||
|   | |||||||
| @@ -1,5 +1,5 @@ | |||||||
| /******************************************************************************* | /******************************************************************************* | ||||||
|  * Copyright (C) 2021, MINRES Technologies GmbH |  * Copyright (C) 2021 MINRES Technologies GmbH | ||||||
|  * All rights reserved. |  * All rights reserved. | ||||||
|  * |  * | ||||||
|  * Redistribution and use in source and binary forms, with or without |  * Redistribution and use in source and binary forms, with or without | ||||||
| @@ -91,11 +91,11 @@ protected: | |||||||
|          "User timer interrupt", "Supervisor timer interrupt", "Reserved", "Machine timer interrupt", |          "User timer interrupt", "Supervisor timer interrupt", "Reserved", "Machine timer interrupt", | ||||||
|          "User external interrupt", "Supervisor external interrupt", "Reserved", "Machine external interrupt"}}; |          "User external interrupt", "Supervisor external interrupt", "Reserved", "Machine external interrupt"}}; | ||||||
| public: | public: | ||||||
|     using super = BASE; |     using core = BASE; | ||||||
|     using this_class = riscv_hart_m_p<BASE>; |     using this_class = riscv_hart_m_p<BASE>; | ||||||
|     using phys_addr_t = typename super::phys_addr_t; |     using phys_addr_t = typename core::phys_addr_t; | ||||||
|     using reg_t = typename super::reg_t; |     using reg_t = typename core::reg_t; | ||||||
|     using addr_t = typename super::addr_t; |     using addr_t = typename core::addr_t; | ||||||
|  |  | ||||||
|     using rd_csr_f = iss::status (this_class::*)(unsigned addr, reg_t &); |     using rd_csr_f = iss::status (this_class::*)(unsigned addr, reg_t &); | ||||||
|     using wr_csr_f = iss::status (this_class::*)(unsigned addr, reg_t); |     using wr_csr_f = iss::status (this_class::*)(unsigned addr, reg_t); | ||||||
| @@ -176,8 +176,8 @@ public: | |||||||
|     iss::status write(const address_type type, const access_type access, const uint32_t space, |     iss::status 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) override; |             const uint64_t addr, const unsigned length, const uint8_t *const data) override; | ||||||
|  |  | ||||||
|     virtual uint64_t enter_trap(uint64_t flags) override { return riscv_hart_m_p::enter_trap(flags, fault_data); } |     virtual uint64_t enter_trap(uint64_t flags) override { return riscv_hart_m_p::enter_trap(flags, fault_data, fault_data); } | ||||||
|     virtual uint64_t enter_trap(uint64_t flags, uint64_t addr) override; |     virtual uint64_t enter_trap(uint64_t flags, uint64_t addr, uint64_t instr) override; | ||||||
|     virtual uint64_t leave_trap(uint64_t flags) override; |     virtual uint64_t leave_trap(uint64_t flags) override; | ||||||
|  |  | ||||||
|     const reg_t& get_mhartid() const { return mhartid_reg;	} |     const reg_t& get_mhartid() const { return mhartid_reg;	} | ||||||
| @@ -234,7 +234,10 @@ protected: | |||||||
|     virtual iss::status write_csr(unsigned addr, reg_t val); |     virtual iss::status write_csr(unsigned addr, reg_t val); | ||||||
|  |  | ||||||
|     hart_state_type state; |     hart_state_type state; | ||||||
|     uint64_t cycle_offset; |     int64_t cycle_offset{0}; | ||||||
|  |     uint64_t mcycle_csr{0}; | ||||||
|  |     int64_t instret_offset{0}; | ||||||
|  |     uint64_t minstret_csr{0}; | ||||||
|     reg_t fault_data; |     reg_t fault_data; | ||||||
|     uint64_t tohost = tohost_dflt; |     uint64_t tohost = tohost_dflt; | ||||||
|     uint64_t fromhost = fromhost_dflt; |     uint64_t fromhost = fromhost_dflt; | ||||||
| @@ -255,7 +258,13 @@ protected: | |||||||
| private: | private: | ||||||
|     iss::status read_reg(unsigned addr, reg_t &val); |     iss::status read_reg(unsigned addr, reg_t &val); | ||||||
|     iss::status write_reg(unsigned addr, reg_t val); |     iss::status write_reg(unsigned addr, reg_t val); | ||||||
|  |     iss::status read_null(unsigned addr, reg_t &val); | ||||||
|  |     iss::status write_null(unsigned addr, reg_t val){return iss::status::Ok;} | ||||||
|     iss::status read_cycle(unsigned addr, reg_t &val); |     iss::status read_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 write_instret(unsigned addr, reg_t val); | ||||||
|  |     iss::status read_mtvec(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); | ||||||
| @@ -276,37 +285,59 @@ protected: | |||||||
| template <typename BASE> | template <typename BASE> | ||||||
| riscv_hart_m_p<BASE>::riscv_hart_m_p() | riscv_hart_m_p<BASE>::riscv_hart_m_p() | ||||||
| : state() | : state() | ||||||
| , cycle_offset(0) |  | ||||||
| , instr_if(*this) { | , instr_if(*this) { | ||||||
|     csr[misa] = traits<BASE>::MISA_VAL; |     csr[misa] = traits<BASE>::MISA_VAL; | ||||||
|     uart_buf.str(""); |     uart_buf.str(""); | ||||||
|     for (unsigned addr = mcycle; addr <= hpmcounter31; ++addr) csr_wr_cb[addr] = nullptr; |     for (unsigned addr = mhpmcounter3; addr <= mhpmcounter31; ++addr){ | ||||||
|     for (unsigned addr = mcycleh; addr <= hpmcounter31h; ++addr) csr_wr_cb[addr] = nullptr; |         csr_rd_cb[addr] = &this_class::read_null; | ||||||
|     // special handling |         csr_wr_cb[addr] = &this_class::write_reg; | ||||||
|     csr_rd_cb[time] = &riscv_hart_m_p<BASE>::read_time; |  | ||||||
|     csr_wr_cb[time] = nullptr; |  | ||||||
|     csr_rd_cb[timeh] = &riscv_hart_m_p<BASE>::read_time; |  | ||||||
|     csr_wr_cb[timeh] = nullptr; |  | ||||||
|     csr_rd_cb[mcycle] = &riscv_hart_m_p<BASE>::read_cycle; |  | ||||||
|     csr_rd_cb[mcycleh] = &riscv_hart_m_p<BASE>::read_cycle; |  | ||||||
|     csr_rd_cb[minstret] = &riscv_hart_m_p<BASE>::read_cycle; |  | ||||||
|     csr_rd_cb[minstreth] = &riscv_hart_m_p<BASE>::read_cycle; |  | ||||||
|     csr_rd_cb[mstatus] = &riscv_hart_m_p<BASE>::read_status; |  | ||||||
|     csr_wr_cb[mstatus] = &riscv_hart_m_p<BASE>::write_status; |  | ||||||
|     csr_rd_cb[mip] = &riscv_hart_m_p<BASE>::read_ip; |  | ||||||
|     csr_wr_cb[mip] = &riscv_hart_m_p<BASE>::write_ip; |  | ||||||
|     csr_rd_cb[mie] = &riscv_hart_m_p<BASE>::read_ie; |  | ||||||
|     csr_wr_cb[mie] = &riscv_hart_m_p<BASE>::write_ie; |  | ||||||
|     csr_rd_cb[mhartid] = &riscv_hart_m_p<BASE>::read_hartid; |  | ||||||
|     // common regs |  | ||||||
|     const std::array<unsigned, 6> addrs{{mepc, mtvec, mscratch, mcause, mtval, mscratch}}; |  | ||||||
|     for(auto addr: addrs) { |  | ||||||
|         csr_rd_cb[addr] = &riscv_hart_m_p<BASE>::read_reg; |  | ||||||
|         csr_wr_cb[addr] = &riscv_hart_m_p<BASE>::write_reg; |  | ||||||
|     } |     } | ||||||
|     // read-only registers |     for (unsigned addr = mhpmcounter3h; addr <= mhpmcounter31h; ++addr){ | ||||||
|     csr_rd_cb[misa] = &riscv_hart_m_p<BASE>::read_reg; |         csr_rd_cb[addr] = &this_class::read_null; | ||||||
|     csr_wr_cb[misa] = nullptr; |         csr_wr_cb[addr] = &this_class::write_reg; | ||||||
|  |     } | ||||||
|  |     for (unsigned addr = mhpmevent3; addr <= mhpmevent31; ++addr){ | ||||||
|  |         csr_rd_cb[addr] = &this_class::read_null; | ||||||
|  |         csr_wr_cb[addr] = &this_class::write_reg; | ||||||
|  |     } | ||||||
|  |     for (unsigned addr = cycle; addr <= hpmcounter31; ++addr){ | ||||||
|  |         csr_rd_cb[addr] = &this_class::read_null; | ||||||
|  |         csr_wr_cb[addr] = &this_class::write_reg; | ||||||
|  |     } | ||||||
|  |     for (unsigned addr = cycleh; addr <= hpmcounter31h; ++addr){ | ||||||
|  |         csr_rd_cb[addr] = &this_class::read_null; | ||||||
|  |         csr_wr_cb[addr] = &this_class::write_reg; | ||||||
|  |     } | ||||||
|  |     // common regs | ||||||
|  |     const std::array<unsigned, 7> addrs{{misa, mepc, mtvec, mscratch, mcause, mtval, mscratch}}; | ||||||
|  |     for(auto addr: addrs) { | ||||||
|  |         csr_rd_cb[addr] = &this_class::read_reg; | ||||||
|  |         csr_wr_cb[addr] = &this_class::write_reg; | ||||||
|  |     } | ||||||
|  |     // special handling & overrides | ||||||
|  |     csr_rd_cb[time] = &this_class::read_time; | ||||||
|  |     csr_wr_cb[time] = nullptr; | ||||||
|  |     csr_rd_cb[timeh] = &this_class::read_time; | ||||||
|  |     csr_wr_cb[timeh] = nullptr; | ||||||
|  |     csr_rd_cb[mcycle] = &this_class::read_cycle; | ||||||
|  |     csr_wr_cb[mcycle] = &this_class::write_cycle; | ||||||
|  |     csr_rd_cb[mcycleh] = &this_class::read_cycle; | ||||||
|  |     csr_wr_cb[mcycleh] = &this_class::write_cycle; | ||||||
|  |     csr_rd_cb[minstret] = &this_class::read_instret; | ||||||
|  |     csr_wr_cb[minstret] = &this_class::write_instret; | ||||||
|  |     csr_rd_cb[minstreth] = &this_class::read_instret; | ||||||
|  |     csr_wr_cb[minstreth] = &this_class::write_instret; | ||||||
|  |     csr_rd_cb[mstatus] = &this_class::read_status; | ||||||
|  |     csr_wr_cb[mstatus] = &this_class::write_status; | ||||||
|  |     csr_rd_cb[mip] = &this_class::read_ip; | ||||||
|  |     csr_wr_cb[mip] = &this_class::write_ip; | ||||||
|  |     csr_rd_cb[mie] = &this_class::read_ie; | ||||||
|  |     csr_wr_cb[mie] = &this_class::write_ie; | ||||||
|  |     csr_rd_cb[mhartid] = &this_class::read_hartid; | ||||||
|  |     csr_rd_cb[mcounteren] = &this_class::read_null; | ||||||
|  |     csr_wr_cb[mcounteren] = &this_class::write_null; | ||||||
|  |     csr_rd_cb[mtvec] = &this_class::read_mtvec; | ||||||
|  |     csr_wr_cb[misa] = &this_class::write_null; | ||||||
| } | } | ||||||
|  |  | ||||||
| template <typename BASE> std::pair<uint64_t, bool> riscv_hart_m_p<BASE>::load_file(std::string name, int type) { | template <typename BASE> std::pair<uint64_t, bool> riscv_hart_m_p<BASE>::load_file(std::string name, int type) { | ||||||
| @@ -547,6 +578,11 @@ template <typename BASE> iss::status riscv_hart_m_p<BASE>::read_reg(unsigned add | |||||||
|     return iss::Ok; |     return iss::Ok; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | template <typename BASE> iss::status riscv_hart_m_p<BASE>::read_null(unsigned addr, reg_t &val) { | ||||||
|  |     val = 0; | ||||||
|  |     return iss::Ok; | ||||||
|  | } | ||||||
|  |  | ||||||
| template <typename BASE> iss::status riscv_hart_m_p<BASE>::write_reg(unsigned addr, reg_t val) { | template <typename BASE> iss::status riscv_hart_m_p<BASE>::write_reg(unsigned addr, reg_t val) { | ||||||
|     csr[addr] = val; |     csr[addr] = val; | ||||||
|     return iss::Ok; |     return iss::Ok; | ||||||
| @@ -563,8 +599,50 @@ template <typename BASE> iss::status riscv_hart_m_p<BASE>::read_cycle(unsigned a | |||||||
|     return iss::Ok; |     return iss::Ok; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | template <typename BASE> iss::status riscv_hart_m_p<BASE>::write_cycle(unsigned addr, reg_t val) { | ||||||
|  |     if (sizeof(typename traits<BASE>::reg_t) != 4) { | ||||||
|  |         if (addr == mcycleh) | ||||||
|  |             return iss::Err; | ||||||
|  |         mcycle_csr = static_cast<uint64_t>(val); | ||||||
|  |     } else { | ||||||
|  |         if (addr == mcycle) { | ||||||
|  |             mcycle_csr = (mcycle_csr & 0xffffffff00000000) + val; | ||||||
|  |         } else  { | ||||||
|  |             mcycle_csr = (static_cast<uint64_t>(val)<<32) + (mcycle_csr & 0xffffffff); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |     cycle_offset = mcycle_csr-this->reg.icount; // TODO: relying on wrap-around | ||||||
|  |     return iss::Ok; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | template <typename BASE> iss::status riscv_hart_m_p<BASE>::read_instret(unsigned addr, reg_t &val) { | ||||||
|  |     if (addr == minstret) { | ||||||
|  |         val = static_cast<reg_t>(this->reg.instret); | ||||||
|  |     } else if (addr == minstreth) { | ||||||
|  |         if (sizeof(typename traits<BASE>::reg_t) != 4) return iss::Err; | ||||||
|  |         val = static_cast<reg_t>(this->reg.instret >> 32); | ||||||
|  |     } | ||||||
|  |     return iss::Ok; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | template <typename BASE> iss::status riscv_hart_m_p<BASE>::write_instret(unsigned addr, reg_t val) { | ||||||
|  |     if (sizeof(typename traits<BASE>::reg_t) != 4) { | ||||||
|  |         if (addr == minstreth) | ||||||
|  |             return iss::Err; | ||||||
|  |         this->reg.instret = static_cast<uint64_t>(val); | ||||||
|  |     } else { | ||||||
|  |         if (addr == minstret) { | ||||||
|  |             this->reg.instret = (this->reg.instret & 0xffffffff00000000) + val; | ||||||
|  |         } else  { | ||||||
|  |             this->reg.instret = (static_cast<uint64_t>(val)<<32) + (this->reg.instret & 0xffffffff); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |     this->reg.instret--; | ||||||
|  |     return iss::Ok; | ||||||
|  | } | ||||||
|  |  | ||||||
| template <typename BASE> iss::status riscv_hart_m_p<BASE>::read_time(unsigned addr, reg_t &val) { | template <typename BASE> iss::status riscv_hart_m_p<BASE>::read_time(unsigned addr, reg_t &val) { | ||||||
|     uint64_t time_val = (this->reg.icount + cycle_offset) / (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); | ||||||
|     } else if (addr == timeh) { |     } else if (addr == timeh) { | ||||||
| @@ -574,6 +652,11 @@ 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) { | ||||||
|  |     val = csr[mtvec] & ~2; | ||||||
|  |     return iss::Ok; | ||||||
|  | } | ||||||
|  |  | ||||||
| template <typename BASE> iss::status riscv_hart_m_p<BASE>::read_status(unsigned addr, reg_t &val) { | template <typename BASE> iss::status riscv_hart_m_p<BASE>::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; | ||||||
| @@ -619,7 +702,6 @@ template <typename BASE> iss::status riscv_hart_m_p<BASE>::write_ip(unsigned add | |||||||
|  |  | ||||||
| template <typename BASE> | template <typename BASE> | ||||||
| iss::status riscv_hart_m_p<BASE>::read_mem(phys_addr_t paddr, unsigned length, uint8_t *const data) { | iss::status riscv_hart_m_p<BASE>::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); |     if(mem_read_cb) return mem_read_cb(paddr, length, data); | ||||||
|     switch (paddr.val) { |     switch (paddr.val) { | ||||||
|     case 0x0200BFF8: { // CLINT base, mtime reg |     case 0x0200BFF8: { // CLINT base, mtime reg | ||||||
| @@ -635,9 +717,9 @@ iss::status riscv_hart_m_p<BASE>::read_mem(phys_addr_t paddr, unsigned length, u | |||||||
|         if (this->reg.icount > 30000) data[3] |= 0x80; |         if (this->reg.icount > 30000) data[3] |= 0x80; | ||||||
|     } break; |     } break; | ||||||
|     default: { |     default: { | ||||||
|         const auto &p = mem(paddr.val / mem.page_size); |         for(auto offs=0U; offs<length; ++offs) { | ||||||
|         auto offs = paddr.val & mem.page_addr_mask; |             *(data + offs)=mem[(paddr.val+offs)%mem.size()]; | ||||||
|         std::copy(p.data() + offs, p.data() + offs + length, data); |         } | ||||||
|     } |     } | ||||||
|     } |     } | ||||||
|     return iss::Ok; |     return iss::Ok; | ||||||
| @@ -747,7 +829,7 @@ template <typename BASE> void riscv_hart_m_p<BASE>::check_interrupt() { | |||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| template <typename BASE> uint64_t riscv_hart_m_p<BASE>::enter_trap(uint64_t flags, uint64_t addr) { | template <typename BASE> uint64_t riscv_hart_m_p<BASE>::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 | ||||||
|     auto trap_id = bit_sub<0, 16>(flags); |     auto trap_id = bit_sub<0, 16>(flags); | ||||||
| @@ -757,7 +839,7 @@ template <typename BASE> uint64_t riscv_hart_m_p<BASE>::enter_trap(uint64_t flag | |||||||
|     if (trap_id == 0) { // exception |     if (trap_id == 0) { // exception | ||||||
|         // store ret addr in xepc register |         // store ret addr in xepc register | ||||||
|         csr[mepc] = static_cast<reg_t>(addr); // store actual address instruction of exception |         csr[mepc] = static_cast<reg_t>(addr); // store actual address instruction of exception | ||||||
|         csr[mtval] = fault_data; |         csr[mtval] = cause==2?instr:fault_data; | ||||||
|         fault_data = 0; |         fault_data = 0; | ||||||
|     } else { |     } else { | ||||||
|         csr[mepc] = this->reg.NEXT_PC; // store next address if interrupt |         csr[mepc] = this->reg.NEXT_PC; // store next address if interrupt | ||||||
| @@ -779,7 +861,7 @@ template <typename BASE> uint64_t riscv_hart_m_p<BASE>::enter_trap(uint64_t flag | |||||||
|     auto ivec = csr[mtvec]; |     auto ivec = csr[mtvec]; | ||||||
|     // calculate addr// set NEXT_PC to trap addressess to jump to based on MODE |     // calculate addr// set NEXT_PC to trap addressess to jump to based on MODE | ||||||
|     // bits in mtvec |     // bits in mtvec | ||||||
|     this->reg.NEXT_PC = ivec & ~0x1UL; |     this->reg.NEXT_PC = ivec & ~0x3UL; | ||||||
|     if ((ivec & 0x1) == 1 && trap_id != 0) this->reg.NEXT_PC += 4 * cause; |     if ((ivec & 0x1) == 1 && trap_id != 0) this->reg.NEXT_PC += 4 * cause; | ||||||
|     // reset trap state |     // reset trap state | ||||||
|     this->reg.PRIV = PRIV_M; |     this->reg.PRIV = PRIV_M; | ||||||
|   | |||||||
| @@ -43,13 +43,14 @@ | |||||||
| #ifndef FMT_HEADER_ONLY | #ifndef FMT_HEADER_ONLY | ||||||
| #define FMT_HEADER_ONLY | #define FMT_HEADER_ONLY | ||||||
| #endif | #endif | ||||||
| #include <fmt/format.h> |  | ||||||
| #include <array> | #include <array> | ||||||
| #include <elfio/elfio.hpp> | #include <elfio/elfio.hpp> | ||||||
|  | #include <fmt/format.h> | ||||||
| #include <iomanip> | #include <iomanip> | ||||||
| #include <sstream> | #include <sstream> | ||||||
| #include <type_traits> | #include <type_traits> | ||||||
| #include <unordered_map> | #include <unordered_map> | ||||||
|  | #include <functional> | ||||||
| #include <util/bit_field.h> | #include <util/bit_field.h> | ||||||
| #include <util/ities.h> | #include <util/ities.h> | ||||||
| #include <util/sparse_array.h> | #include <util/sparse_array.h> | ||||||
| @@ -90,12 +91,12 @@ protected: | |||||||
|          "User timer interrupt", "Supervisor timer interrupt", "Reserved", "Machine timer interrupt", |          "User timer interrupt", "Supervisor timer interrupt", "Reserved", "Machine timer interrupt", | ||||||
|          "User external interrupt", "Supervisor external interrupt", "Reserved", "Machine external interrupt"}}; |          "User external interrupt", "Supervisor external interrupt", "Reserved", "Machine external interrupt"}}; | ||||||
| public: | public: | ||||||
|     using super = BASE; |     using core = BASE; | ||||||
|     using this_class = riscv_hart_msu_vp<BASE>; |     using this_class = riscv_hart_msu_vp<BASE>; | ||||||
|     using virt_addr_t = typename super::virt_addr_t; |     using virt_addr_t = typename core::virt_addr_t; | ||||||
|     using phys_addr_t = typename super::phys_addr_t; |     using phys_addr_t = typename core::phys_addr_t; | ||||||
|     using reg_t = typename super::reg_t; |     using reg_t = typename core::reg_t; | ||||||
|     using addr_t = typename super::addr_t; |     using addr_t = typename core::addr_t; | ||||||
|  |  | ||||||
|     using rd_csr_f = iss::status (this_class::*)(unsigned addr, reg_t &); |     using rd_csr_f = iss::status (this_class::*)(unsigned addr, reg_t &); | ||||||
|     using wr_csr_f = iss::status (this_class::*)(unsigned addr, reg_t); |     using wr_csr_f = iss::status (this_class::*)(unsigned addr, reg_t); | ||||||
| @@ -272,8 +273,8 @@ public: | |||||||
|     }; |     }; | ||||||
|     using hart_state_type = hart_state<reg_t>; |     using hart_state_type = hart_state<reg_t>; | ||||||
|  |  | ||||||
|     const typename super::reg_t PGSIZE = 1 << PGSHIFT; |     const typename core::reg_t PGSIZE = 1 << PGSHIFT; | ||||||
|     const typename super::reg_t PGMASK = PGSIZE - 1; |     const typename core::reg_t PGMASK = PGSIZE - 1; | ||||||
|  |  | ||||||
|     constexpr reg_t get_irq_mask(size_t mode) { |     constexpr reg_t get_irq_mask(size_t mode) { | ||||||
|         std::array<const reg_t, 4> m = {{ |         std::array<const reg_t, 4> m = {{ | ||||||
| @@ -299,18 +300,30 @@ public: | |||||||
|     iss::status write(const address_type type, const access_type access, const uint32_t space, |     iss::status 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) override; |             const uint64_t addr, const unsigned length, const uint8_t *const data) override; | ||||||
|  |  | ||||||
|     virtual uint64_t enter_trap(uint64_t flags) override { return riscv_hart_msu_vp::enter_trap(flags, fault_data); } |     virtual uint64_t enter_trap(uint64_t flags) override { return riscv_hart_msu_vp::enter_trap(flags, fault_data, fault_data); } | ||||||
|     virtual uint64_t enter_trap(uint64_t flags, uint64_t addr) override; |     virtual uint64_t enter_trap(uint64_t flags, uint64_t addr, uint64_t instr) override; | ||||||
|     virtual uint64_t leave_trap(uint64_t flags) override; |     virtual uint64_t leave_trap(uint64_t flags) override; | ||||||
|     void wait_until(uint64_t flags) override; |     void wait_until(uint64_t flags) override; | ||||||
|  |  | ||||||
|     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} [p:{};s:0x{:x};c:{}]", |         CLOG(INFO, disass) << fmt::format("0x{:016x}    {:40} [p:{};s:0x{:x};c:{}]", | ||||||
|                 pc, instr, lvl[this->reg.PRIV], (reg_t)state.mstatus, this->reg.icount); |                 pc, instr, lvl[this->reg.PRIV], (reg_t)state.mstatus, this->reg.ccount); | ||||||
|     }; |     }; | ||||||
|  |  | ||||||
|     iss::instrumentation_if *get_instrumentation_if() override { return &instr_if; } |     iss::instrumentation_if *get_instrumentation_if() override { return &instr_if; } | ||||||
|  |  | ||||||
|  |     void setMemReadCb(std::function<iss::status(phys_addr_t, unsigned, uint8_t* const)> const& memReadCb) { | ||||||
|  |         mem_read_cb = memReadCb; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     void setMemWriteCb(std::function<iss::status(phys_addr_t, unsigned, const uint8_t* const)> const& memWriteCb) { | ||||||
|  |         mem_write_cb = memWriteCb; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     void set_csr(unsigned addr, reg_t val){ | ||||||
|  |         csr[addr & csr.page_addr_mask] = val; | ||||||
|  |     } | ||||||
|  |  | ||||||
| protected: | protected: | ||||||
|     struct riscv_instrumentation_if : public iss::instrumentation_if { |     struct riscv_instrumentation_if : public iss::instrumentation_if { | ||||||
|  |  | ||||||
| @@ -364,6 +377,9 @@ protected: | |||||||
|     std::unordered_map<unsigned, wr_csr_f> csr_wr_cb; |     std::unordered_map<unsigned, wr_csr_f> csr_wr_cb; | ||||||
|  |  | ||||||
| private: | private: | ||||||
|  |     iss::status read_null(unsigned addr, reg_t &val); | ||||||
|  |     iss::status read_reg(unsigned addr, reg_t &val); | ||||||
|  |     iss::status write_reg(unsigned addr, reg_t val); | ||||||
|     iss::status read_cycle(unsigned addr, reg_t &val); |     iss::status read_cycle(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); | ||||||
| @@ -372,11 +388,16 @@ private: | |||||||
|     iss::status write_ie(unsigned addr, reg_t val); |     iss::status write_ie(unsigned addr, reg_t val); | ||||||
|     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_satp(unsigned addr, reg_t &val); |     iss::status read_satp(unsigned addr, reg_t &val); | ||||||
|     iss::status write_satp(unsigned addr, reg_t val); |     iss::status write_satp(unsigned addr, reg_t val); | ||||||
|     iss::status read_fcsr(unsigned addr, reg_t &val); |     iss::status read_fcsr(unsigned addr, reg_t &val); | ||||||
|     iss::status write_fcsr(unsigned addr, reg_t val); |     iss::status write_fcsr(unsigned addr, reg_t val); | ||||||
|  |  | ||||||
|  |     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, const uint8_t *const)> mem_write_cb; | ||||||
|  |  | ||||||
| protected: | protected: | ||||||
|     void check_interrupt(); |     void check_interrupt(); | ||||||
| }; | }; | ||||||
| @@ -388,10 +409,26 @@ riscv_hart_msu_vp<BASE>::riscv_hart_msu_vp() | |||||||
| , instr_if(*this) { | , instr_if(*this) { | ||||||
|     csr[misa] = hart_state_type::get_misa(); |     csr[misa] = hart_state_type::get_misa(); | ||||||
|     uart_buf.str(""); |     uart_buf.str(""); | ||||||
|     // read-only registers |     for (unsigned addr = mcycle; addr <= mhpmcounter31; ++addr){ | ||||||
|     csr_wr_cb[misa] = nullptr; |         csr_rd_cb[addr] = &this_class::read_null; | ||||||
|     for (unsigned addr = mcycle; addr <= hpmcounter31; ++addr) csr_wr_cb[addr] = nullptr; |         csr_wr_cb[addr] = &this_class::write_reg; | ||||||
|     for (unsigned addr = mcycleh; addr <= hpmcounter31h; ++addr) csr_wr_cb[addr] = nullptr; |     } | ||||||
|  |     for (unsigned addr = mcycleh; addr <= mhpmcounter31h; ++addr){ | ||||||
|  |         csr_rd_cb[addr] = &this_class::read_null; | ||||||
|  |         csr_wr_cb[addr] = &this_class::write_reg; | ||||||
|  |     } | ||||||
|  |     for (unsigned addr = mhpmevent3; addr <= mhpmevent31; ++addr){ | ||||||
|  |         csr_rd_cb[addr] = &this_class::read_null; | ||||||
|  |         csr_wr_cb[addr] = &this_class::write_reg; | ||||||
|  |     } | ||||||
|  |     for (unsigned addr = cycle; addr <= hpmcounter31; ++addr){ | ||||||
|  |         csr_rd_cb[addr] = &this_class::read_null; | ||||||
|  |         csr_wr_cb[addr] = &this_class::write_reg; | ||||||
|  |     } | ||||||
|  |     for (unsigned addr = cycleh; addr <= hpmcounter31h; ++addr){ | ||||||
|  |         csr_rd_cb[addr] = &this_class::read_null; | ||||||
|  |         csr_wr_cb[addr] = &this_class::write_reg; | ||||||
|  |     } | ||||||
|     // special handling |     // special handling | ||||||
|     csr_rd_cb[time] = &this_class::read_time; |     csr_rd_cb[time] = &this_class::read_time; | ||||||
|     csr_wr_cb[time] = nullptr; |     csr_wr_cb[time] = nullptr; | ||||||
| @@ -419,6 +456,17 @@ riscv_hart_msu_vp<BASE>::riscv_hart_msu_vp() | |||||||
|     csr_wr_cb[sie] = &this_class::write_ie; |     csr_wr_cb[sie] = &this_class::write_ie; | ||||||
|     csr_rd_cb[uie] = &this_class::read_ie; |     csr_rd_cb[uie] = &this_class::read_ie; | ||||||
|     csr_wr_cb[uie] = &this_class::write_ie; |     csr_wr_cb[uie] = &this_class::write_ie; | ||||||
|  |     csr_rd_cb[mhartid] = &this_class::read_hartid; | ||||||
|  |     // common regs | ||||||
|  |     const std::array<unsigned, 6> addrs{{mepc, mtvec, mscratch, mcause, mtval, mscratch}}; | ||||||
|  |     for(auto addr: addrs) { | ||||||
|  |         csr_rd_cb[addr] = &this_class::read_reg; | ||||||
|  |         csr_wr_cb[addr] = &this_class::write_reg; | ||||||
|  |     } | ||||||
|  |     // read-only registers | ||||||
|  |     csr_rd_cb[misa] = &this_class::read_reg; | ||||||
|  |     csr_wr_cb[misa] = nullptr; | ||||||
|  |      | ||||||
|     csr_rd_cb[satp] = &this_class::read_satp; |     csr_rd_cb[satp] = &this_class::read_satp; | ||||||
|     csr_wr_cb[satp] = &this_class::write_satp; |     csr_wr_cb[satp] = &this_class::write_satp; | ||||||
|     csr_rd_cb[fcsr] = &this_class::read_fcsr; |     csr_rd_cb[fcsr] = &this_class::read_fcsr; | ||||||
| @@ -679,35 +727,43 @@ iss::status riscv_hart_msu_vp<BASE>::write(const address_type type, const access | |||||||
| template <typename BASE> iss::status riscv_hart_msu_vp<BASE>::read_csr(unsigned addr, reg_t &val) { | template <typename BASE> iss::status riscv_hart_msu_vp<BASE>::read_csr(unsigned addr, reg_t &val) { | ||||||
|     if (addr >= csr.size()) return iss::Err; |     if (addr >= csr.size()) return iss::Err; | ||||||
|     auto req_priv_lvl = (addr >> 8) & 0x3; |     auto req_priv_lvl = (addr >> 8) & 0x3; | ||||||
|     if (this->reg.PRIV < req_priv_lvl) throw illegal_instruction_fault(this->fault_data); |     if (this->reg.PRIV < req_priv_lvl) // not having required privileges | ||||||
|  |     	throw illegal_instruction_fault(this->fault_data); | ||||||
|     auto it = csr_rd_cb.find(addr); |     auto it = csr_rd_cb.find(addr); | ||||||
|     if (it == csr_rd_cb.end()) { |     if (it == csr_rd_cb.end() || !it->second) // non existent register | ||||||
|         val = csr[addr & csr.page_addr_mask]; |         throw illegal_instruction_fault(this->fault_data); | ||||||
|         return iss::Ok; |     return (this->*(it->second))(addr, val); | ||||||
|     } |  | ||||||
|     rd_csr_f f = it->second; |  | ||||||
|     if (f == nullptr) throw illegal_instruction_fault(this->fault_data); |  | ||||||
|     return (this->*f)(addr, val); |  | ||||||
| } | } | ||||||
|  |  | ||||||
| template <typename BASE> iss::status riscv_hart_msu_vp<BASE>::write_csr(unsigned addr, reg_t val) { | template <typename BASE> iss::status riscv_hart_msu_vp<BASE>::write_csr(unsigned addr, reg_t val) { | ||||||
|     if (addr >= csr.size()) return iss::Err; |     if (addr >= csr.size()) return iss::Err; | ||||||
|     auto req_priv_lvl = (addr >> 8) & 0x3; |     auto req_priv_lvl = (addr >> 8) & 0x3; | ||||||
|     if (this->reg.PRIV < req_priv_lvl) |     if (this->reg.PRIV < req_priv_lvl) // not having required privileges | ||||||
|         throw illegal_instruction_fault(this->fault_data); |         throw illegal_instruction_fault(this->fault_data); | ||||||
|     if((addr&0xc00)==0xc00) |     if((addr&0xc00)==0xc00) // writing to read-only region | ||||||
|         throw illegal_instruction_fault(this->fault_data); |         throw illegal_instruction_fault(this->fault_data); | ||||||
|     auto it = csr_wr_cb.find(addr); |     auto it = csr_wr_cb.find(addr); | ||||||
|     if (it == csr_wr_cb.end()) { |     if (it == csr_wr_cb.end() || !it->second) // non existent register | ||||||
|         csr[addr & csr.page_addr_mask] = val; |         throw illegal_instruction_fault(this->fault_data); | ||||||
|         return iss::Ok; |     return (this->*(it->second))(addr, val); | ||||||
|     } |  | ||||||
|     wr_csr_f f = it->second; |  | ||||||
|     if (f == nullptr) throw illegal_instruction_fault(this->fault_data); |  | ||||||
|     return (this->*f)(addr, val); |  | ||||||
| } | } | ||||||
|  |  | ||||||
| template <typename BASE> iss::status riscv_hart_msu_vp<BASE>::read_cycle(unsigned addr, reg_t &val) { | template <typename BASE> iss::status riscv_hart_msu_vp<BASE>::read_reg(unsigned addr, reg_t &val) { | ||||||
|  |     val = csr[addr]; | ||||||
|  |     return iss::Ok; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | template <typename BASE> iss::status riscv_hart_msu_vp<BASE>::read_null(unsigned addr, reg_t &val) { | ||||||
|  |     val = 0; | ||||||
|  |     return iss::Ok; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | template <typename BASE> iss::status riscv_hart_msu_vp<BASE>::write_reg(unsigned addr, reg_t val) { | ||||||
|  |     csr[addr] = val; | ||||||
|  |     return iss::Ok; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | template <typename BASE> iss::status riscv_hart_m_p<BASE>::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); | ||||||
| @@ -750,6 +806,11 @@ template <typename BASE> iss::status riscv_hart_msu_vp<BASE>::read_ie(unsigned a | |||||||
|     return iss::Ok; |     return iss::Ok; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | template <typename BASE> iss::status riscv_hart_msu_vp<BASE>::read_hartid(unsigned addr, reg_t &val) { | ||||||
|  |     val = mhartid_reg; | ||||||
|  |     return iss::Ok; | ||||||
|  | } | ||||||
|  |  | ||||||
| template <typename BASE> iss::status riscv_hart_msu_vp<BASE>::write_ie(unsigned addr, reg_t val) { | template <typename BASE> iss::status riscv_hart_msu_vp<BASE>::write_ie(unsigned addr, reg_t val) { | ||||||
|     auto req_priv_lvl = (addr >> 8) & 0x3; |     auto req_priv_lvl = (addr >> 8) & 0x3; | ||||||
|     auto mask = get_irq_mask(req_priv_lvl); |     auto mask = get_irq_mask(req_priv_lvl); | ||||||
| @@ -832,7 +893,7 @@ template <typename BASE> iss::status riscv_hart_msu_vp<BASE>::write_fcsr(unsigne | |||||||
|  |  | ||||||
| template <typename BASE> | template <typename BASE> | ||||||
| iss::status riscv_hart_msu_vp<BASE>::read_mem(phys_addr_t paddr, unsigned length, uint8_t *const data) { | iss::status riscv_hart_msu_vp<BASE>::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) { |     switch (paddr.val) { | ||||||
|     case 0x0200BFF8: { // CLINT base, mtime reg |     case 0x0200BFF8: { // CLINT base, mtime reg | ||||||
|         if (sizeof(reg_t) < length) return iss::Err; |         if (sizeof(reg_t) < length) return iss::Err; | ||||||
| @@ -847,9 +908,9 @@ iss::status riscv_hart_msu_vp<BASE>::read_mem(phys_addr_t paddr, unsigned length | |||||||
|         if (this->reg.icount > 30000) data[3] |= 0x80; |         if (this->reg.icount > 30000) data[3] |= 0x80; | ||||||
|     } break; |     } break; | ||||||
|     default: { |     default: { | ||||||
|         const auto &p = mem(paddr.val / mem.page_size); |         for(auto offs=0U; offs<length; ++offs) { | ||||||
|         auto offs = paddr.val & mem.page_addr_mask; |             *(data + offs)=mem[(paddr.val+offs)%mem.size()]; | ||||||
|         std::copy(p.data() + offs, p.data() + offs + length, data); |     	} | ||||||
|     } |     } | ||||||
|     } |     } | ||||||
|     return iss::Ok; |     return iss::Ok; | ||||||
| @@ -858,6 +919,7 @@ iss::status riscv_hart_msu_vp<BASE>::read_mem(phys_addr_t paddr, unsigned length | |||||||
| template <typename BASE> | template <typename BASE> | ||||||
| iss::status riscv_hart_msu_vp<BASE>::write_mem(phys_addr_t paddr, unsigned length, const uint8_t *const data) { | iss::status riscv_hart_msu_vp<BASE>::write_mem(phys_addr_t paddr, unsigned length, const uint8_t *const data) { | ||||||
|     if ((paddr.val + length) > mem.size()) return iss::Err; |     if ((paddr.val + length) > mem.size()) return iss::Err; | ||||||
|  |     if(mem_write_cb) return mem_write_cb(paddr, length, data); | ||||||
|     switch (paddr.val) { |     switch (paddr.val) { | ||||||
|     case 0x10013000: // UART0 base, TXFIFO reg |     case 0x10013000: // UART0 base, TXFIFO reg | ||||||
|     case 0x10023000: // UART1 base, TXFIFO reg |     case 0x10023000: // UART1 base, TXFIFO reg | ||||||
| @@ -1070,7 +1132,7 @@ typename riscv_hart_msu_vp<BASE>::phys_addr_t riscv_hart_msu_vp<BASE>::virt2phys | |||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| template <typename BASE> uint64_t riscv_hart_msu_vp<BASE>::enter_trap(uint64_t flags, uint64_t addr) { | template <typename BASE> uint64_t riscv_hart_msu_vp<BASE>::enter_trap(uint64_t flags, uint64_t addr, uint64_t instr) { | ||||||
|     auto cur_priv = this->reg.PRIV; |     auto cur_priv = this->reg.PRIV; | ||||||
|     // 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 | ||||||
| @@ -1091,7 +1153,7 @@ template <typename BASE> uint64_t riscv_hart_msu_vp<BASE>::enter_trap(uint64_t f | |||||||
|          * access, or page-fault exception occurs, mtval is written with the |          * access, or page-fault exception occurs, mtval is written with the | ||||||
|          * faulting effective address. |          * faulting effective address. | ||||||
|          */ |          */ | ||||||
|         csr[utval | (new_priv << 8)] = fault_data; |         csr[utval | (new_priv << 8)] = cause==2?instr : fault_data; | ||||||
|         fault_data = 0; |         fault_data = 0; | ||||||
|     } else { |     } else { | ||||||
|         if (cur_priv != PRIV_M && ((csr[mideleg] >> cause) & 0x1) != 0) |         if (cur_priv != PRIV_M && ((csr[mideleg] >> cause) & 0x1) != 0) | ||||||
|   | |||||||
| @@ -93,11 +93,11 @@ protected: | |||||||
|          "User timer interrupt", "Supervisor timer interrupt", "Reserved", "Machine timer interrupt", |          "User timer interrupt", "Supervisor timer interrupt", "Reserved", "Machine timer interrupt", | ||||||
|          "User external interrupt", "Supervisor external interrupt", "Reserved", "Machine external interrupt"}}; |          "User external interrupt", "Supervisor external interrupt", "Reserved", "Machine external interrupt"}}; | ||||||
| public: | public: | ||||||
|     using super = BASE; |     using core = BASE; | ||||||
|     using this_class = riscv_hart_mu_p<BASE, FEAT>; |     using this_class = riscv_hart_mu_p<BASE, FEAT>; | ||||||
|     using phys_addr_t = typename super::phys_addr_t; |     using phys_addr_t = typename core::phys_addr_t; | ||||||
|     using reg_t = typename super::reg_t; |     using reg_t = typename core::reg_t; | ||||||
|     using addr_t = typename super::addr_t; |     using addr_t = typename core::addr_t; | ||||||
|  |  | ||||||
|     using rd_csr_f = iss::status (this_class::*)(unsigned addr, reg_t &); |     using rd_csr_f = iss::status (this_class::*)(unsigned addr, reg_t &); | ||||||
|     using wr_csr_f = iss::status (this_class::*)(unsigned addr, reg_t); |     using wr_csr_f = iss::status (this_class::*)(unsigned addr, reg_t); | ||||||
| @@ -191,8 +191,8 @@ public: | |||||||
|     iss::status write(const address_type type, const access_type access, const uint32_t space, |     iss::status 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) override; |             const uint64_t addr, const unsigned length, const uint8_t *const data) override; | ||||||
|  |  | ||||||
|     virtual uint64_t enter_trap(uint64_t flags) override { return riscv_hart_mu_p::enter_trap(flags, fault_data); } |     virtual uint64_t enter_trap(uint64_t flags) override { return riscv_hart_mu_p::enter_trap(flags, fault_data, fault_data); } | ||||||
|     virtual uint64_t enter_trap(uint64_t flags, uint64_t addr) override; |     virtual uint64_t enter_trap(uint64_t flags, uint64_t addr, uint64_t instr) override; | ||||||
|     virtual uint64_t leave_trap(uint64_t flags) override; |     virtual uint64_t leave_trap(uint64_t flags) override; | ||||||
|  |  | ||||||
|     const reg_t& get_mhartid() const { return mhartid_reg;	} |     const reg_t& get_mhartid() const { return mhartid_reg;	} | ||||||
| @@ -200,7 +200,7 @@ public: | |||||||
|  |  | ||||||
|     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} [p:{};s:0x{:x};c:{}]", |         CLOG(INFO, disass) << fmt::format("0x{:016x}    {:40} [p:{};s:0x{:x};c:{}]", | ||||||
|                 pc, instr, lvl[this->reg.PRIV], (reg_t)state.mstatus, this->reg.icount); |                 pc, instr, lvl[this->reg.PRIV], (reg_t)state.mstatus, this->reg.ccount); | ||||||
|     }; |     }; | ||||||
|  |  | ||||||
|     iss::instrumentation_if *get_instrumentation_if() override { return &instr_if; } |     iss::instrumentation_if *get_instrumentation_if() override { return &instr_if; } | ||||||
| @@ -789,7 +789,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) { | 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 | ||||||
|     auto trap_id = bit_sub<0, 16>(flags); |     auto trap_id = bit_sub<0, 16>(flags); | ||||||
| @@ -809,7 +809,7 @@ template <typename BASE, features_e FEAT> uint64_t riscv_hart_mu_p<BASE, FEAT>:: | |||||||
|          * access, or page-fault exception occurs, mtval is written with the |          * access, or page-fault exception occurs, mtval is written with the | ||||||
|          * faulting effective address. |          * faulting effective address. | ||||||
|          */ |          */ | ||||||
|         csr[utval | (new_priv << 8)] = fault_data; |         csr[utval | (new_priv << 8)] = cause==2?instr:fault_data; | ||||||
|         fault_data = 0; |         fault_data = 0; | ||||||
|     } else { |     } else { | ||||||
|         if (this->reg.PRIV != PRIV_M && ((csr[mideleg] >> cause) & 0x1) != 0) |         if (this->reg.PRIV != PRIV_M && ((csr[mideleg] >> cause) & 0x1) != 0) | ||||||
|   | |||||||
| @@ -61,7 +61,9 @@ template <> struct traits<tgc_c> { | |||||||
|         X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, X30, X31, PC, NEXT_PC, PRIV, NUM_REGS, |         X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, X30, X31, PC, NEXT_PC, PRIV, NUM_REGS, | ||||||
|         TRAP_STATE=NUM_REGS, |         TRAP_STATE=NUM_REGS, | ||||||
|         PENDING_TRAP, |         PENDING_TRAP, | ||||||
|         ICOUNT |         ICOUNT, | ||||||
|  |         CYCLE, | ||||||
|  |         INSTRET | ||||||
|     }; |     }; | ||||||
|  |  | ||||||
|     using reg_t = uint32_t; |     using reg_t = uint32_t; | ||||||
| @@ -74,11 +76,11 @@ template <> struct traits<tgc_c> { | |||||||
|  |  | ||||||
|     using phys_addr_t = iss::typed_addr_t<iss::address_type::PHYSICAL>; |     using phys_addr_t = iss::typed_addr_t<iss::address_type::PHYSICAL>; | ||||||
|  |  | ||||||
|     static constexpr std::array<const uint32_t, 38> reg_bit_widths{ |     static constexpr std::array<const uint32_t, 40> reg_bit_widths{ | ||||||
|         {32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,8,32,32,64}}; |         {32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,8,32,32,64,64,64}}; | ||||||
|  |  | ||||||
|     static constexpr std::array<const uint32_t, 38> reg_byte_offsets{ |     static constexpr std::array<const uint32_t, 40> reg_byte_offsets{ | ||||||
|         {0,4,8,12,16,20,24,28,32,36,40,44,48,52,56,60,64,68,72,76,80,84,88,92,96,100,104,108,112,116,120,124,128,132,136,137,141,145}}; |         {0,4,8,12,16,20,24,28,32,36,40,44,48,52,56,60,64,68,72,76,80,84,88,92,96,100,104,108,112,116,120,124,128,132,136,137,141,145,153,161}}; | ||||||
|  |  | ||||||
|     static const uint64_t addr_mask = (reg_t(1) << (XLEN - 1)) | ((reg_t(1) << (XLEN - 1)) - 1); |     static const uint64_t addr_mask = (reg_t(1) << (XLEN - 1)) | ((reg_t(1) << (XLEN - 1)) - 1); | ||||||
|  |  | ||||||
| @@ -154,25 +156,27 @@ template <> struct traits<tgc_c> { | |||||||
|         CLI = 64, |         CLI = 64, | ||||||
|         CLUI = 65, |         CLUI = 65, | ||||||
|         CADDI16SP = 66, |         CADDI16SP = 66, | ||||||
|         CSRLI = 67, |         __reserved_clui = 67, | ||||||
|         CSRAI = 68, |         CSRLI = 68, | ||||||
|         CANDI = 69, |         CSRAI = 69, | ||||||
|         CSUB = 70, |         CANDI = 70, | ||||||
|         CXOR = 71, |         CSUB = 71, | ||||||
|         COR = 72, |         CXOR = 72, | ||||||
|         CAND = 73, |         COR = 73, | ||||||
|         CJ = 74, |         CAND = 74, | ||||||
|         CBEQZ = 75, |         CJ = 75, | ||||||
|         CBNEZ = 76, |         CBEQZ = 76, | ||||||
|         CSLLI = 77, |         CBNEZ = 77, | ||||||
|         CLWSP = 78, |         CSLLI = 78, | ||||||
|         CMV = 79, |         CLWSP = 79, | ||||||
|         CJR = 80, |         CMV = 80, | ||||||
|         CADD = 81, |         CJR = 81, | ||||||
|         CJALR = 82, |         __reserved_cmv = 82, | ||||||
|         CEBREAK = 83, |         CADD = 83, | ||||||
|         CSWSP = 84, |         CJALR = 84, | ||||||
|         DII = 85, |         CEBREAK = 85, | ||||||
|  |         CSWSP = 86, | ||||||
|  |         DII = 87, | ||||||
|         MAX_OPCODE |         MAX_OPCODE | ||||||
|     }; |     }; | ||||||
| }; | }; | ||||||
| @@ -259,6 +263,8 @@ protected: | |||||||
|         uint8_t PRIV = 0; |         uint8_t PRIV = 0; | ||||||
|         uint32_t trap_state = 0, pending_trap = 0; |         uint32_t trap_state = 0, pending_trap = 0; | ||||||
|         uint64_t icount = 0; |         uint64_t icount = 0; | ||||||
|  |         uint64_t cycle = 0; | ||||||
|  |         uint64_t instret = 0; | ||||||
|         uint32_t last_branch; |         uint32_t last_branch; | ||||||
|     } reg; |     } reg; | ||||||
| #pragma pack(pop) | #pragma pack(pop) | ||||||
|   | |||||||
| @@ -42,7 +42,7 @@ using vm_ptr= std::unique_ptr<iss::vm_if>; | |||||||
|  |  | ||||||
| template<typename PLAT> | template<typename PLAT> | ||||||
| std::tuple<cpu_ptr, vm_ptr> create_cpu(std::string const& backend, unsigned gdb_port){ | std::tuple<cpu_ptr, vm_ptr> create_cpu(std::string const& backend, unsigned gdb_port){ | ||||||
|     using core_type = typename PLAT::super; |     using core_type = typename PLAT::core; | ||||||
|     core_type* lcpu = new PLAT(); |     core_type* lcpu = new PLAT(); | ||||||
|     if(backend == "interp") |     if(backend == "interp") | ||||||
|         return {cpu_ptr{lcpu}, vm_ptr{iss::interp::create(lcpu, gdb_port)}}; |         return {cpu_ptr{lcpu}, vm_ptr{iss::interp::create(lcpu, gdb_port)}}; | ||||||
|   | |||||||
| @@ -41,8 +41,8 @@ using namespace iss::arch; | |||||||
|  |  | ||||||
| constexpr std::array<const char*, 35>    iss::arch::traits<iss::arch::tgc_c>::reg_names; | constexpr std::array<const char*, 35>    iss::arch::traits<iss::arch::tgc_c>::reg_names; | ||||||
| constexpr std::array<const char*, 35>    iss::arch::traits<iss::arch::tgc_c>::reg_aliases; | constexpr std::array<const char*, 35>    iss::arch::traits<iss::arch::tgc_c>::reg_aliases; | ||||||
| constexpr std::array<const uint32_t, 38> iss::arch::traits<iss::arch::tgc_c>::reg_bit_widths; | constexpr std::array<const uint32_t, 40> iss::arch::traits<iss::arch::tgc_c>::reg_bit_widths; | ||||||
| constexpr std::array<const uint32_t, 38> iss::arch::traits<iss::arch::tgc_c>::reg_byte_offsets; | constexpr std::array<const uint32_t, 40> iss::arch::traits<iss::arch::tgc_c>::reg_byte_offsets; | ||||||
|  |  | ||||||
| tgc_c::tgc_c() { | tgc_c::tgc_c() { | ||||||
|     reg.icount = 0; |     reg.icount = 0; | ||||||
|   | |||||||
| @@ -36,11 +36,9 @@ | |||||||
| #include "iss/arch/tgc_b.h" | #include "iss/arch/tgc_b.h" | ||||||
| using tgc_b_plat_type = iss::arch::riscv_hart_m_p<iss::arch::tgc_b>; | using tgc_b_plat_type = iss::arch::riscv_hart_m_p<iss::arch::tgc_b>; | ||||||
| #endif | #endif | ||||||
| #ifdef CORE_TGC_C |  | ||||||
| #include "iss/arch/riscv_hart_m_p.h" | #include "iss/arch/riscv_hart_m_p.h" | ||||||
| #include "iss/arch/tgc_c.h" | #include "iss/arch/tgc_c.h" | ||||||
| using tgc_c_plat_type = iss::arch::riscv_hart_m_p<iss::arch::tgc_c>; | using tgc_c_plat_type = iss::arch::riscv_hart_m_p<iss::arch::tgc_c>; | ||||||
| #endif |  | ||||||
| #ifdef CORE_TGC_D | #ifdef CORE_TGC_D | ||||||
| #include "iss/arch/riscv_hart_mu_p.h" | #include "iss/arch/riscv_hart_mu_p.h" | ||||||
| #include "iss/arch/tgc_d.h" | #include "iss/arch/tgc_d.h" | ||||||
| @@ -81,8 +79,8 @@ std::array<const char, 4> lvl = {{'U', 'S', 'H', 'M'}}; | |||||||
| template<typename PLAT> | template<typename PLAT> | ||||||
| class core_wrapper_t : public PLAT { | class core_wrapper_t : public PLAT { | ||||||
| public: | public: | ||||||
|     using reg_t       = typename arch::traits<typename PLAT::super>::reg_t; |     using reg_t       = typename arch::traits<typename PLAT::core>::reg_t; | ||||||
|     using phys_addr_t = typename arch::traits<typename PLAT::super>::phys_addr_t; |     using phys_addr_t = typename arch::traits<typename PLAT::core>::phys_addr_t; | ||||||
|     using heart_state_t = typename PLAT::hart_state_type; |     using heart_state_t = typename PLAT::hart_state_type; | ||||||
|     core_wrapper_t(core_complex *owner) |     core_wrapper_t(core_complex *owner) | ||||||
|     : owner(owner) { } |     : owner(owner) { } | ||||||
| @@ -155,7 +153,7 @@ public: | |||||||
|     void wait_until(uint64_t flags) override { |     void wait_until(uint64_t flags) override { | ||||||
|         SCCDEBUG(owner->name()) << "Sleeping until interrupt"; |         SCCDEBUG(owner->name()) << "Sleeping until interrupt"; | ||||||
|         do { |         do { | ||||||
|             wait(wfi_evt); |             sc_core::wait(wfi_evt); | ||||||
|         } while (this->reg.pending_trap == 0); |         } while (this->reg.pending_trap == 0); | ||||||
|         PLAT::wait_until(flags); |         PLAT::wait_until(flags); | ||||||
|     } |     } | ||||||
| @@ -248,7 +246,7 @@ public: | |||||||
|         set_interrupt_execution = [lcpu](bool b) { return lcpu->set_interrupt_execution(b); }; |         set_interrupt_execution = [lcpu](bool b) { return lcpu->set_interrupt_execution(b); }; | ||||||
|         local_irq = [lcpu](short s, bool b) { return lcpu->local_irq(s, b); }; |         local_irq = [lcpu](short s, bool b) { return lcpu->local_irq(s, b); }; | ||||||
|         if(backend == "interp") |         if(backend == "interp") | ||||||
|             return {cpu_ptr{lcpu}, vm_ptr{iss::interp::create(lcpu, gdb_port)}}; |             return {cpu_ptr{lcpu}, vm_ptr{iss::interp::create(static_cast<typename PLAT::core*>(lcpu), gdb_port)}}; | ||||||
| #ifdef WITH_LLVM | #ifdef WITH_LLVM | ||||||
|         if(backend == "llvm") |         if(backend == "llvm") | ||||||
|             return {cpu_ptr{lcpu}, vm_ptr{iss::llvm::create(lcpu, gdb_port)}}; |             return {cpu_ptr{lcpu}, vm_ptr{iss::llvm::create(lcpu, gdb_port)}}; | ||||||
| @@ -263,7 +261,7 @@ public: | |||||||
|     void create_cpu(std::string const& type, std::string const& backend, unsigned gdb_port, uint32_t hart_id){ |     void create_cpu(std::string const& type, std::string const& backend, unsigned gdb_port, uint32_t hart_id){ | ||||||
|         CREATE_CORE(tgc_c) |         CREATE_CORE(tgc_c) | ||||||
| #ifdef CORE_TGC_B | #ifdef CORE_TGC_B | ||||||
|         CREATE_CORE(tgc_c) |         CREATE_CORE(tgc_b) | ||||||
| #endif | #endif | ||||||
| #ifdef CORE_TGC_D | #ifdef CORE_TGC_D | ||||||
|         CREATE_CORE(tgc_d) |         CREATE_CORE(tgc_d) | ||||||
| @@ -335,7 +333,7 @@ void core_complex::before_end_of_elaboration() { | |||||||
| #ifdef WITH_SCV | #ifdef WITH_SCV | ||||||
|     cpu->vm->setDisassEnabled(enable_disass.get_value() || m_db != nullptr); |     cpu->vm->setDisassEnabled(enable_disass.get_value() || m_db != nullptr); | ||||||
| #else | #else | ||||||
|     vm->setDisassEnabled(enable_disass.get_value()); |     cpu->vm->setDisassEnabled(enable_disass.get_value()); | ||||||
| #endif | #endif | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
		Reference in New Issue
	
	Block a user