Refactored file dependencies to decouple components
This commit is contained in:
		
							
								
								
									
										2
									
								
								dbt-core
									
									
									
									
									
								
							
							
								
								
								
								
								
							
						
						
									
										2
									
								
								dbt-core
									
									
									
									
									
								
							 Submodule dbt-core updated: c338c6879f...aefc5681f1
									
								
							| @@ -110,12 +110,24 @@ public: | ||||
| ////////////////////////////////////////////////////////////////////////////// | ||||
|  | ||||
| inline sysc::gpio_regs::gpio_regs(sc_core::sc_module_name nm) | ||||
|     : sc_core::sc_module(nm), NAMED(value, r_value, 0, *this), NAMED(input_en, r_input_en, 0, *this), | ||||
|       NAMED(output_en, r_output_en, 0, *this), NAMED(port, r_port, 0, *this), NAMED(pue, r_pue, 0, *this), | ||||
|       NAMED(ds, r_ds, 0, *this), NAMED(rise_ie, r_rise_ie, 0, *this), NAMED(rise_ip, r_rise_ip, 0, *this), | ||||
|       NAMED(fall_ie, r_fall_ie, 0, *this), NAMED(fall_ip, r_fall_ip, 0, *this), NAMED(high_ie, r_high_ie, 0, *this), | ||||
|       NAMED(high_ip, r_high_ip, 0, *this), NAMED(low_ie, r_low_ie, 0, *this), NAMED(low_ip, r_low_ip, 0, *this), | ||||
|       NAMED(iof_en, r_iof_en, 0, *this), NAMED(iof_sel, r_iof_sel, 0, *this), NAMED(out_xor, r_out_xor, 0, *this) {} | ||||
| : sc_core::sc_module(nm) | ||||
| , NAMED(value, r_value, 0, *this) | ||||
| , NAMED(input_en, r_input_en, 0, *this) | ||||
| , NAMED(output_en, r_output_en, 0, *this) | ||||
| , NAMED(port, r_port, 0, *this) | ||||
| , NAMED(pue, r_pue, 0, *this) | ||||
| , NAMED(ds, r_ds, 0, *this) | ||||
| , NAMED(rise_ie, r_rise_ie, 0, *this) | ||||
| , NAMED(rise_ip, r_rise_ip, 0, *this) | ||||
| , NAMED(fall_ie, r_fall_ie, 0, *this) | ||||
| , NAMED(fall_ip, r_fall_ip, 0, *this) | ||||
| , NAMED(high_ie, r_high_ie, 0, *this) | ||||
| , NAMED(high_ip, r_high_ip, 0, *this) | ||||
| , NAMED(low_ie, r_low_ie, 0, *this) | ||||
| , NAMED(low_ip, r_low_ip, 0, *this) | ||||
| , NAMED(iof_en, r_iof_en, 0, *this) | ||||
| , NAMED(iof_sel, r_iof_sel, 0, *this) | ||||
| , NAMED(out_xor, r_out_xor, 0, *this) {} | ||||
|  | ||||
| template <unsigned BUSWIDTH> inline void sysc::gpio_regs::registerResources(sysc::tlm_target<BUSWIDTH> &target) { | ||||
|     target.addResource(value, 0x0UL); | ||||
|   | ||||
| @@ -79,9 +79,12 @@ public: | ||||
| ////////////////////////////////////////////////////////////////////////////// | ||||
|  | ||||
| inline sysc::plic_regs::plic_regs(sc_core::sc_module_name nm) | ||||
|     : sc_core::sc_module(nm), NAMED(priority, r_priority, 0, *this), NAMED(pending, r_pending, 0, *this), | ||||
|       NAMED(enabled, r_enabled, 0, *this), NAMED(threshold, r_threshold, 0, *this), | ||||
|       NAMED(claim_complete, r_claim_complete, 0, *this) {} | ||||
| : sc_core::sc_module(nm) | ||||
| , NAMED(priority, r_priority, 0, *this) | ||||
| , NAMED(pending, r_pending, 0, *this) | ||||
| , NAMED(enabled, r_enabled, 0, *this) | ||||
| , NAMED(threshold, r_threshold, 0, *this) | ||||
| , NAMED(claim_complete, r_claim_complete, 0, *this) {} | ||||
|  | ||||
| template <unsigned BUSWIDTH> inline void sysc::plic_regs::registerResources(sysc::tlm_target<BUSWIDTH> &target) { | ||||
|     target.addResource(priority, 0x4UL); | ||||
|   | ||||
| @@ -152,12 +152,23 @@ public: | ||||
| ////////////////////////////////////////////////////////////////////////////// | ||||
|  | ||||
| inline sysc::spi_regs::spi_regs(sc_core::sc_module_name nm) | ||||
|     : sc_core::sc_module(nm), NAMED(sckdiv, r_sckdiv, 0, *this), NAMED(sckmode, r_sckmode, 0, *this), | ||||
|       NAMED(csid, r_csid, 0, *this), NAMED(csdef, r_csdef, 0, *this), NAMED(csmode, r_csmode, 0, *this), | ||||
|       NAMED(delay0, r_delay0, 0, *this), NAMED(delay1, r_delay1, 0, *this), NAMED(fmt, r_fmt, 0, *this), | ||||
|       NAMED(txdata, r_txdata, 0, *this), NAMED(rxdata, r_rxdata, 0, *this), NAMED(txmark, r_txmark, 0, *this), | ||||
|       NAMED(rxmark, r_rxmark, 0, *this), NAMED(fctrl, r_fctrl, 0, *this), NAMED(ffmt, r_ffmt, 0, *this), | ||||
|       NAMED(ie, r_ie, 0, *this), NAMED(ip, r_ip, 0, *this) {} | ||||
| : sc_core::sc_module(nm) | ||||
| , NAMED(sckdiv, r_sckdiv, 0, *this) | ||||
| , NAMED(sckmode, r_sckmode, 0, *this) | ||||
| , NAMED(csid, r_csid, 0, *this) | ||||
| , NAMED(csdef, r_csdef, 0, *this) | ||||
| , NAMED(csmode, r_csmode, 0, *this) | ||||
| , NAMED(delay0, r_delay0, 0, *this) | ||||
| , NAMED(delay1, r_delay1, 0, *this) | ||||
| , NAMED(fmt, r_fmt, 0, *this) | ||||
| , NAMED(txdata, r_txdata, 0, *this) | ||||
| , NAMED(rxdata, r_rxdata, 0, *this) | ||||
| , NAMED(txmark, r_txmark, 0, *this) | ||||
| , NAMED(rxmark, r_rxmark, 0, *this) | ||||
| , NAMED(fctrl, r_fctrl, 0, *this) | ||||
| , NAMED(ffmt, r_ffmt, 0, *this) | ||||
| , NAMED(ie, r_ie, 0, *this) | ||||
| , NAMED(ip, r_ip, 0, *this) {} | ||||
|  | ||||
| template <unsigned BUSWIDTH> inline void sysc::spi_regs::registerResources(sysc::tlm_target<BUSWIDTH> &target) { | ||||
|     target.addResource(sckdiv, 0x0UL); | ||||
|   | ||||
| @@ -103,9 +103,14 @@ public: | ||||
| ////////////////////////////////////////////////////////////////////////////// | ||||
|  | ||||
| inline sysc::uart_regs::uart_regs(sc_core::sc_module_name nm) | ||||
|     : sc_core::sc_module(nm), NAMED(txdata, r_txdata, 0, *this), NAMED(rxdata, r_rxdata, 0, *this), | ||||
|       NAMED(txctrl, r_txctrl, 0, *this), NAMED(rxctrl, r_rxctrl, 0, *this), NAMED(ie, r_ie, 0, *this), | ||||
|       NAMED(ip, r_ip, 0, *this), NAMED(div, r_div, 0, *this) {} | ||||
| : sc_core::sc_module(nm) | ||||
| , NAMED(txdata, r_txdata, 0, *this) | ||||
| , NAMED(rxdata, r_rxdata, 0, *this) | ||||
| , NAMED(txctrl, r_txctrl, 0, *this) | ||||
| , NAMED(rxctrl, r_rxctrl, 0, *this) | ||||
| , NAMED(ie, r_ie, 0, *this) | ||||
| , NAMED(ip, r_ip, 0, *this) | ||||
| , NAMED(div, r_div, 0, *this) {} | ||||
|  | ||||
| template <unsigned BUSWIDTH> inline void sysc::uart_regs::registerResources(sysc::tlm_target<BUSWIDTH> &target) { | ||||
|     target.addResource(txdata, 0x0UL); | ||||
|   | ||||
| @@ -34,10 +34,10 @@ add_executable(${APPLICATION_NAME} ${APP_SOURCES}) | ||||
|  | ||||
| # Links the target exe against the libraries | ||||
| target_link_libraries(${APPLICATION_NAME} ${LIBRARY_NAME}) | ||||
| target_link_libraries(${APPLICATION_NAME} risc-v) | ||||
| target_link_libraries(${APPLICATION_NAME} dbt-core) | ||||
| target_link_libraries(${APPLICATION_NAME} sc-components) | ||||
| target_link_libraries(${APPLICATION_NAME} external) | ||||
| target_link_libraries(${APPLICATION_NAME} risc-v) | ||||
| target_link_libraries(${APPLICATION_NAME} ${llvm_libs}) | ||||
| target_link_libraries(${APPLICATION_NAME} ${SystemC_LIBRARIES} ) | ||||
| if(SCV_FOUND) | ||||
|   | ||||
| @@ -39,10 +39,12 @@ | ||||
| namespace sysc { | ||||
| namespace SiFive { | ||||
|  | ||||
| core_complex::core_complex(sc_core::sc_module_name name) : sc_core::sc_module(name), NAMED(initiator), NAMED(rst_i) { | ||||
| core_complex::core_complex(sc_core::sc_module_name name) | ||||
| : sc_core::sc_module(name) | ||||
| , NAMED(initiator) | ||||
| , NAMED(rst_i) { | ||||
|     // TODO Auto-generated constructor stub | ||||
| } | ||||
|  | ||||
|  | ||||
| } /* namespace SiFive */ | ||||
| } /* namespace sysc */ | ||||
|   | ||||
| @@ -21,7 +21,11 @@ | ||||
| namespace sysc { | ||||
|  | ||||
| gpio::gpio(sc_core::sc_module_name nm) | ||||
|     : sc_core::sc_module(nm), tlm_target<>(clk), NAMED(clk_i), NAMED(rst_i), NAMEDD(gpio_regs, regs) { | ||||
| : sc_core::sc_module(nm) | ||||
| , tlm_target<>(clk) | ||||
| , NAMED(clk_i) | ||||
| , NAMED(rst_i) | ||||
| , NAMEDD(gpio_regs, regs) { | ||||
|     regs->registerResources(*this); | ||||
|     SC_METHOD(clock_cb); | ||||
|     sensitive << clk_i; | ||||
| @@ -31,8 +35,7 @@ gpio::gpio(sc_core::sc_module_name nm) | ||||
|  | ||||
| void gpio::clock_cb() {} | ||||
|  | ||||
| gpio::~gpio() { | ||||
| } | ||||
| gpio::~gpio() {} | ||||
|  | ||||
| void gpio::reset_cb() { | ||||
|     if (rst_i.read()) | ||||
|   | ||||
| @@ -25,8 +25,15 @@ | ||||
| namespace sysc { | ||||
|  | ||||
| platform::platform(sc_core::sc_module_name nm) | ||||
|     : sc_core::sc_module(nm), NAMED(i_master), NAMED(i_router, 4, 1), NAMED(i_uart), NAMED(i_spi), NAMED(i_gpio), | ||||
|       NAMED(i_plic), NAMED(s_clk), NAMED(s_rst) { | ||||
| : sc_core::sc_module(nm) | ||||
| , NAMED(i_master) | ||||
| , NAMED(i_router, 4, 1) | ||||
| , NAMED(i_uart) | ||||
| , NAMED(i_spi) | ||||
| , NAMED(i_gpio) | ||||
| , NAMED(i_plic) | ||||
| , NAMED(s_clk) | ||||
| , NAMED(s_rst) { | ||||
|     i_master.initiator(i_router.target[0]); | ||||
|     size_t i = 0; | ||||
|     for (const auto &e : e300_plat_map) { | ||||
|   | ||||
| @@ -21,7 +21,11 @@ | ||||
| namespace sysc { | ||||
|  | ||||
| plic::plic(sc_core::sc_module_name nm) | ||||
|     : sc_core::sc_module(nm), tlm_target<>(clk), NAMED(clk_i), NAMED(rst_i), NAMEDD(plic_regs, regs) { | ||||
| : sc_core::sc_module(nm) | ||||
| , tlm_target<>(clk) | ||||
| , NAMED(clk_i) | ||||
| , NAMED(rst_i) | ||||
| , NAMEDD(plic_regs, regs) { | ||||
|     regs->registerResources(*this); | ||||
|     SC_METHOD(clock_cb); | ||||
|     sensitive << clk_i; | ||||
|   | ||||
| @@ -21,7 +21,11 @@ | ||||
| namespace sysc { | ||||
|  | ||||
| spi::spi(sc_core::sc_module_name nm) | ||||
|     : sc_core::sc_module(nm), tlm_target<>(clk), NAMED(clk_i), NAMED(rst_i), NAMEDD(spi_regs, regs) { | ||||
| : sc_core::sc_module(nm) | ||||
| , tlm_target<>(clk) | ||||
| , NAMED(clk_i) | ||||
| , NAMED(rst_i) | ||||
| , NAMEDD(spi_regs, regs) { | ||||
|     regs->registerResources(*this); | ||||
|     SC_METHOD(clock_cb); | ||||
|     sensitive << clk_i; | ||||
|   | ||||
| @@ -21,7 +21,11 @@ | ||||
| namespace sysc { | ||||
|  | ||||
| uart::uart(sc_core::sc_module_name nm) | ||||
|     : sc_core::sc_module(nm), tlm_target<>(clk), NAMED(clk_i), NAMED(rst_i), NAMEDD(uart_regs, regs) { | ||||
| : sc_core::sc_module(nm) | ||||
| , tlm_target<>(clk) | ||||
| , NAMED(clk_i) | ||||
| , NAMED(rst_i) | ||||
| , NAMEDD(uart_regs, regs) { | ||||
|     regs->registerResources(*this); | ||||
|     SC_METHOD(clock_cb); | ||||
|     sensitive << clk_i; | ||||
|   | ||||
| @@ -224,19 +224,24 @@ struct vm_info { | ||||
| }; | ||||
|  | ||||
| struct trap_load_access_fault : public trap_access { | ||||
|     trap_load_access_fault(uint64_t badaddr) : trap_access(5 << 16, badaddr) {} | ||||
|     trap_load_access_fault(uint64_t badaddr) | ||||
|     : trap_access(5 << 16, badaddr) {} | ||||
| }; | ||||
| struct illegal_instruction_fault : public trap_access { | ||||
|     illegal_instruction_fault(uint64_t badaddr) : trap_access(2 << 16, badaddr) {} | ||||
|     illegal_instruction_fault(uint64_t badaddr) | ||||
|     : trap_access(2 << 16, badaddr) {} | ||||
| }; | ||||
| struct trap_instruction_page_fault : public trap_access { | ||||
|     trap_instruction_page_fault(uint64_t badaddr) : trap_access(12 << 16, badaddr) {} | ||||
|     trap_instruction_page_fault(uint64_t badaddr) | ||||
|     : trap_access(12 << 16, badaddr) {} | ||||
| }; | ||||
| struct trap_load_page_fault : public trap_access { | ||||
|     trap_load_page_fault(uint64_t badaddr) : trap_access(13 << 16, badaddr) {} | ||||
|     trap_load_page_fault(uint64_t badaddr) | ||||
|     : trap_access(13 << 16, badaddr) {} | ||||
| }; | ||||
| struct trap_store_page_fault : public trap_access { | ||||
|     trap_store_page_fault(uint64_t badaddr) : trap_access(15 << 16, badaddr) {} | ||||
|     trap_store_page_fault(uint64_t badaddr) | ||||
|     : trap_access(15 << 16, badaddr) {} | ||||
| }; | ||||
| } | ||||
|  | ||||
| @@ -277,7 +282,7 @@ using mstatus32_t = union { | ||||
|         uint32_t SD : 1, _WPRI4 : 11, MXR : 1, SUM : 1, _WPRI3 : 1, XS : 2, FS : 2, _WPRI2 : 8, UPIE : 1, _WPRI0 : 3, | ||||
|             UIE : 1; | ||||
|     } u; | ||||
| } ; | ||||
| }; | ||||
|  | ||||
| using mstatus64_t = union { | ||||
|     uint64_t val; | ||||
| @@ -324,7 +329,7 @@ using mstatus64_t = union { | ||||
|             UXL : 2,     // value of XLEN for U-mode | ||||
|             _WPRI3 : 12, MXR : 1, SUM : 1, _WPRI2 : 1, XS : 2, FS : 2, _WPRI1 : 8, UPIE : 1, _WPRI0 : 3, UIE : 1; | ||||
|     } u; | ||||
| } ; | ||||
| }; | ||||
|  | ||||
| template <unsigned L> inline vm_info decode_vm_info(uint32_t state, uint64_t sptbr); | ||||
|  | ||||
| @@ -483,7 +488,10 @@ private: | ||||
|     void check_interrupt(); | ||||
| }; | ||||
|  | ||||
| template <typename BASE> riscv_hart_msu_vp<BASE>::riscv_hart_msu_vp() : mstatus_r(csr[mstatus]), satp_r(csr[satp]) { | ||||
| template <typename BASE> | ||||
| riscv_hart_msu_vp<BASE>::riscv_hart_msu_vp() | ||||
| : mstatus_r(csr[mstatus]) | ||||
| , satp_r(csr[satp]) { | ||||
|     csr[misa] = traits<BASE>::XLEN == 32 ? 1ULL << (traits<BASE>::XLEN - 2) : 2ULL << (traits<BASE>::XLEN - 2); | ||||
|     uart_buf.str(""); | ||||
|     // read-only registers | ||||
|   | ||||
| @@ -28,7 +28,7 @@ | ||||
| // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||||
| // POSSIBILITY OF SUCH DAMAGE. | ||||
| // | ||||
| // Created on: Thu Sep 21 17:01:54 CEST 2017 | ||||
| // Created on: Tue Sep 26 17:41:14 CEST 2017 | ||||
| //             *      rv32imac.h Author: <CoreDSL Generator> | ||||
| // | ||||
| //////////////////////////////////////////////////////////////////////////////// | ||||
| @@ -103,15 +103,15 @@ template <> struct traits<rv32imac> { | ||||
|         ICOUNT | ||||
|     }; | ||||
|  | ||||
|     typedef uint32_t reg_t; | ||||
|     using reg_t = uint32_t; | ||||
|  | ||||
|     typedef uint32_t addr_t; | ||||
|     using addr_t = uint32_t; | ||||
|  | ||||
|     typedef uint32_t code_word_t; // TODO: check removal | ||||
|     using code_word_t = uint32_t; // TODO: check removal | ||||
|  | ||||
|     typedef iss::typed_addr_t<iss::VIRTUAL> virt_addr_t; | ||||
|     using virt_addr_t = iss::typed_addr_t<iss::VIRTUAL>; | ||||
|  | ||||
|     typedef iss::typed_addr_t<iss::PHYSICAL> phys_addr_t; | ||||
|     using phys_addr_t = iss::typed_addr_t<iss::PHYSICAL>; | ||||
|  | ||||
|     constexpr static unsigned reg_bit_width(unsigned r) { | ||||
|         const uint32_t RV32IMAC_reg_size[] = {32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, | ||||
| @@ -142,19 +142,19 @@ struct rv32imac : public arch_if { | ||||
|     rv32imac(); | ||||
|     ~rv32imac(); | ||||
|  | ||||
|     virtual void reset(uint64_t address = 0) override; | ||||
|     void reset(uint64_t address = 0) override; | ||||
|  | ||||
|     virtual uint8_t *get_regs_base_ptr() override; | ||||
|     uint8_t *get_regs_base_ptr() override; | ||||
|     /// deprecated | ||||
|     virtual void get_reg(short idx, std::vector<uint8_t> &value) override {} | ||||
|     virtual void set_reg(short idx, const std::vector<uint8_t> &value) override {} | ||||
|     void get_reg(short idx, std::vector<uint8_t> &value) override {} | ||||
|     void set_reg(short idx, const std::vector<uint8_t> &value) override {} | ||||
|     /// deprecated | ||||
|     virtual bool get_flag(int flag) override { return false; } | ||||
|     virtual void set_flag(int, bool value) override{}; | ||||
|     bool get_flag(int flag) override { return false; } | ||||
|     void set_flag(int, bool value) override{}; | ||||
|     /// deprecated | ||||
|     virtual void update_flags(operations op, uint64_t opr1, uint64_t opr2) override{}; | ||||
|     void update_flags(operations op, uint64_t opr1, uint64_t opr2) override{}; | ||||
|  | ||||
|     virtual void notify_phase(exec_phase phase) { | ||||
|     void notify_phase(exec_phase phase) { | ||||
|         if (phase == ISTART) { | ||||
|             ++reg.icount; | ||||
|             reg.PC = reg.NEXT_PC; | ||||
|   | ||||
| @@ -28,7 +28,7 @@ | ||||
| // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||||
| // POSSIBILITY OF SUCH DAMAGE. | ||||
| // | ||||
| // Created on: Thu Sep 21 17:01:54 CEST 2017 | ||||
| // Created on: Tue Sep 26 17:41:14 CEST 2017 | ||||
| //             *      rv64ia.h Author: <CoreDSL Generator> | ||||
| // | ||||
| //////////////////////////////////////////////////////////////////////////////// | ||||
| @@ -103,15 +103,15 @@ template <> struct traits<rv64ia> { | ||||
|         ICOUNT | ||||
|     }; | ||||
|  | ||||
|     typedef uint64_t reg_t; | ||||
|     using reg_t = uint64_t; | ||||
|  | ||||
|     typedef uint64_t addr_t; | ||||
|     using addr_t = uint64_t; | ||||
|  | ||||
|     typedef uint64_t code_word_t; // TODO: check removal | ||||
|     using code_word_t = uint64_t; // TODO: check removal | ||||
|  | ||||
|     typedef iss::typed_addr_t<iss::VIRTUAL> virt_addr_t; | ||||
|     using virt_addr_t = iss::typed_addr_t<iss::VIRTUAL>; | ||||
|  | ||||
|     typedef iss::typed_addr_t<iss::PHYSICAL> phys_addr_t; | ||||
|     using phys_addr_t = iss::typed_addr_t<iss::PHYSICAL>; | ||||
|  | ||||
|     constexpr static unsigned reg_bit_width(unsigned r) { | ||||
|         const uint32_t RV64IA_reg_size[] = {64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, | ||||
| @@ -141,19 +141,19 @@ struct rv64ia : public arch_if { | ||||
|     rv64ia(); | ||||
|     ~rv64ia(); | ||||
|  | ||||
|     virtual void reset(uint64_t address = 0) override; | ||||
|     void reset(uint64_t address = 0) override; | ||||
|  | ||||
|     virtual uint8_t *get_regs_base_ptr() override; | ||||
|     uint8_t *get_regs_base_ptr() override; | ||||
|     /// deprecated | ||||
|     virtual void get_reg(short idx, std::vector<uint8_t> &value) override {} | ||||
|     virtual void set_reg(short idx, const std::vector<uint8_t> &value) override {} | ||||
|     void get_reg(short idx, std::vector<uint8_t> &value) override {} | ||||
|     void set_reg(short idx, const std::vector<uint8_t> &value) override {} | ||||
|     /// deprecated | ||||
|     virtual bool get_flag(int flag) override { return false; } | ||||
|     virtual void set_flag(int, bool value) override{}; | ||||
|     bool get_flag(int flag) override { return false; } | ||||
|     void set_flag(int, bool value) override{}; | ||||
|     /// deprecated | ||||
|     virtual void update_flags(operations op, uint64_t opr1, uint64_t opr2) override{}; | ||||
|     void update_flags(operations op, uint64_t opr1, uint64_t opr2) override{}; | ||||
|  | ||||
|     virtual void notify_phase(exec_phase phase) { | ||||
|     void notify_phase(exec_phase phase) { | ||||
|         if (phase == ISTART) { | ||||
|             ++reg.icount; | ||||
|             reg.PC = reg.NEXT_PC; | ||||
|   | ||||
							
								
								
									
										317
									
								
								riscv/incl/iss/debugger/riscv_target_adapter.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										317
									
								
								riscv/incl/iss/debugger/riscv_target_adapter.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,317 @@ | ||||
| /* | ||||
|  * riscv_target_adapter.h | ||||
|  * | ||||
|  *  Created on: 26.09.2017 | ||||
|  *      Author: eyck | ||||
|  */ | ||||
|  | ||||
| #ifndef _ISS_DEBUGGER_RISCV_TARGET_ADAPTER_H_ | ||||
| #define _ISS_DEBUGGER_RISCV_TARGET_ADAPTER_H_ | ||||
|  | ||||
| #include "iss/arch_if.h" | ||||
| #include <iss/arch/traits.h> | ||||
| #include <iss/debugger/target_adapter_base.h> | ||||
| #include <iss/iss.h> | ||||
|  | ||||
| #include <memory> | ||||
| #include <util/logging.h> | ||||
|  | ||||
| namespace iss { | ||||
| namespace debugger { | ||||
| using namespace iss::arch; | ||||
| using namespace iss::debugger; | ||||
|  | ||||
| template <typename ARCH> struct riscv_target_adapter : public target_adapter_base { | ||||
|  | ||||
|     riscv_target_adapter(server_if *srv, iss::arch_if *core) | ||||
|     : target_adapter_base(srv) | ||||
|     , core(core) {} | ||||
|  | ||||
|     /*============== Thread Control ===============================*/ | ||||
|  | ||||
|     /* Set generic thread */ | ||||
|     status set_gen_thread(rp_thread_ref &thread) override; | ||||
|  | ||||
|     /* Set control thread */ | ||||
|     status set_ctrl_thread(rp_thread_ref &thread) override; | ||||
|  | ||||
|     /* Get thread status */ | ||||
|     status is_thread_alive(rp_thread_ref &thread, bool &alive) override; | ||||
|  | ||||
|     /*============= Register Access ================================*/ | ||||
|  | ||||
|     /* Read all registers. buf is 4-byte aligned and it is in | ||||
|      target byte order. If  register is not available | ||||
|      corresponding bytes in avail_buf are 0, otherwise | ||||
|      avail buf is 1 */ | ||||
|     status read_registers(std::vector<uint8_t> &data, std::vector<uint8_t> &avail) override; | ||||
|  | ||||
|     /* Write all registers. buf is 4-byte aligned and it is in target | ||||
|      byte order */ | ||||
|     status write_registers(const std::vector<uint8_t> &data) override; | ||||
|  | ||||
|     /* Read one register. buf is 4-byte aligned and it is in | ||||
|      target byte order. If  register is not available | ||||
|      corresponding bytes in avail_buf are 0, otherwise | ||||
|      avail buf is 1 */ | ||||
|     status read_single_register(unsigned int reg_no, std::vector<uint8_t> &buf, | ||||
|                                 std::vector<uint8_t> &avail_buf) override; | ||||
|  | ||||
|     /* Write one register. buf is 4-byte aligned and it is in target byte | ||||
|      order */ | ||||
|     status write_single_register(unsigned int reg_no, const std::vector<uint8_t> &buf) override; | ||||
|  | ||||
|     /*=================== Memory Access =====================*/ | ||||
|  | ||||
|     /* Read memory, buf is 4-bytes aligned and it is in target | ||||
|      byte order */ | ||||
|     status read_mem(uint64_t addr, std::vector<uint8_t> &buf) override; | ||||
|  | ||||
|     /* Write memory, buf is 4-bytes aligned and it is in target | ||||
|      byte order */ | ||||
|     status write_mem(uint64_t addr, const std::vector<uint8_t> &buf) override; | ||||
|  | ||||
|     status process_query(unsigned int &mask, const rp_thread_ref &arg, rp_thread_info &info) override; | ||||
|  | ||||
|     status thread_list_query(int first, const rp_thread_ref &arg, std::vector<rp_thread_ref> &result, size_t max_num, | ||||
|                              size_t &num, bool &done) override; | ||||
|  | ||||
|     status current_thread_query(rp_thread_ref &thread) override; | ||||
|  | ||||
|     status offsets_query(uint64_t &text, uint64_t &data, uint64_t &bss) override; | ||||
|  | ||||
|     status crc_query(uint64_t addr, size_t len, uint32_t &val) override; | ||||
|  | ||||
|     status raw_query(std::string in_buf, std::string &out_buf) override; | ||||
|  | ||||
|     status threadinfo_query(int first, std::string &out_buf) override; | ||||
|  | ||||
|     status threadextrainfo_query(const rp_thread_ref &thread, std::string &out_buf) override; | ||||
|  | ||||
|     status packetsize_query(std::string &out_buf) override; | ||||
|  | ||||
|     status add_break(int type, uint64_t addr, unsigned int length) override; | ||||
|  | ||||
|     status remove_break(int type, uint64_t addr, unsigned int length) override; | ||||
|  | ||||
|     status resume_from_addr(bool step, int sig, uint64_t addr) override; | ||||
|  | ||||
| protected: | ||||
|     static inline constexpr addr_t map_addr(const addr_t &i) { return i; } | ||||
|  | ||||
|     iss::arch_if *core; | ||||
|     rp_thread_ref thread_idx; | ||||
| }; | ||||
|  | ||||
| template <typename ARCH> status riscv_target_adapter<ARCH>::set_gen_thread(rp_thread_ref &thread) { | ||||
|     thread_idx = thread; | ||||
|     return Ok; | ||||
| } | ||||
|  | ||||
| template <typename ARCH> status riscv_target_adapter<ARCH>::set_ctrl_thread(rp_thread_ref &thread) { | ||||
|     thread_idx = thread; | ||||
|     return Ok; | ||||
| } | ||||
|  | ||||
| template <typename ARCH> status riscv_target_adapter<ARCH>::is_thread_alive(rp_thread_ref &thread, bool &alive) { | ||||
|     alive = 1; | ||||
|     return Ok; | ||||
| } | ||||
|  | ||||
| /* List threads. If first is non-zero then start from the first thread, | ||||
|  * otherwise start from arg, result points to array of threads to be | ||||
|  * filled out, result size is number of elements in the result, | ||||
|  * num points to the actual number of threads found, done is | ||||
|  * set if all threads are processed. | ||||
|  */ | ||||
| template <typename ARCH> | ||||
| status riscv_target_adapter<ARCH>::thread_list_query(int first, const rp_thread_ref &arg, | ||||
|                                                      std::vector<rp_thread_ref> &result, size_t max_num, size_t &num, | ||||
|                                                      bool &done) { | ||||
|     if (first == 0) { | ||||
|         result.clear(); | ||||
|         result.push_back(thread_idx); | ||||
|         num = 1; | ||||
|         done = true; | ||||
|         return Ok; | ||||
|     } else | ||||
|         return NotSupported; | ||||
| } | ||||
|  | ||||
| template <typename ARCH> status riscv_target_adapter<ARCH>::current_thread_query(rp_thread_ref &thread) { | ||||
|     thread = thread_idx; | ||||
|     return Ok; | ||||
| } | ||||
|  | ||||
| template <typename ARCH> | ||||
| status riscv_target_adapter<ARCH>::read_registers(std::vector<uint8_t> &data, std::vector<uint8_t> &avail) { | ||||
|     LOG(TRACE) << "reading target registers"; | ||||
|     // return idx<0?:; | ||||
|     data.clear(); | ||||
|     avail.clear(); | ||||
|     const uint8_t *reg_base = core->get_regs_base_ptr(); | ||||
|     for (size_t reg_no = 0; reg_no < arch::traits<ARCH>::NUM_REGS; ++reg_no) { | ||||
|         auto reg_width = arch::traits<ARCH>::reg_bit_width(static_cast<typename arch::traits<ARCH>::reg_e>(reg_no)) / 8; | ||||
|         unsigned offset = traits<ARCH>::reg_byte_offset(reg_no); | ||||
|         for (size_t j = 0; j < reg_width; ++j) { | ||||
|             data.push_back(*(reg_base + offset + j)); | ||||
|             avail.push_back(0xff); | ||||
|         } | ||||
|     } | ||||
|     // work around fill with F type registers | ||||
|     if (arch::traits<ARCH>::NUM_REGS < 65) { | ||||
|         auto reg_width = sizeof(typename arch::traits<ARCH>::reg_t); | ||||
|         for (size_t reg_no = 0; reg_no < 33; ++reg_no) { | ||||
|             for (size_t j = 0; j < reg_width; ++j) { | ||||
|                 data.push_back(0x0); | ||||
|                 avail.push_back(0x00); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|     return Ok; | ||||
| } | ||||
|  | ||||
| template <typename ARCH> status riscv_target_adapter<ARCH>::write_registers(const std::vector<uint8_t> &data) { | ||||
|     auto reg_count = arch::traits<ARCH>::NUM_REGS; | ||||
|     auto *reg_base = core->get_regs_base_ptr(); | ||||
|     auto iter = data.data(); | ||||
|     for (size_t reg_no = 0; reg_no < reg_count; ++reg_no) { | ||||
|         auto reg_width = arch::traits<ARCH>::reg_bit_width(static_cast<typename arch::traits<ARCH>::reg_e>(reg_no)) / 8; | ||||
|         auto offset = traits<ARCH>::reg_byte_offset(reg_no); | ||||
|         std::copy(iter, iter + reg_width, reg_base); | ||||
|         iter += 4; | ||||
|         reg_base += offset; | ||||
|     } | ||||
|     return Ok; | ||||
| } | ||||
|  | ||||
| template <typename ARCH> | ||||
| status riscv_target_adapter<ARCH>::read_single_register(unsigned int reg_no, std::vector<uint8_t> &data, | ||||
|                                                         std::vector<uint8_t> &avail) { | ||||
|     if (reg_no < 65) { | ||||
|         // auto reg_size = arch::traits<ARCH>::reg_bit_width(static_cast<typename | ||||
|         // arch::traits<ARCH>::reg_e>(reg_no))/8; | ||||
|         auto *reg_base = core->get_regs_base_ptr(); | ||||
|         auto reg_width = arch::traits<ARCH>::reg_bit_width(static_cast<typename arch::traits<ARCH>::reg_e>(reg_no)) / 8; | ||||
|         data.resize(reg_width); | ||||
|         avail.resize(reg_width); | ||||
|         auto offset = traits<ARCH>::reg_byte_offset(reg_no); | ||||
|         std::copy(reg_base + offset, reg_base + offset + reg_width, data.begin()); | ||||
|         std::fill(avail.begin(), avail.end(), 0xff); | ||||
|     } else { | ||||
|         typed_addr_t<iss::PHYSICAL> a(iss::DEBUG_READ, traits<ARCH>::CSR, reg_no - 65); | ||||
|         data.resize(sizeof(typename traits<ARCH>::reg_t)); | ||||
|         avail.resize(sizeof(typename traits<ARCH>::reg_t)); | ||||
|         std::fill(avail.begin(), avail.end(), 0xff); | ||||
|         core->read(a, data.size(), data.data()); | ||||
|     } | ||||
|     return data.size() > 0 ? Ok : Err; | ||||
| } | ||||
|  | ||||
| template <typename ARCH> | ||||
| status riscv_target_adapter<ARCH>::write_single_register(unsigned int reg_no, const std::vector<uint8_t> &data) { | ||||
|     if (reg_no < 65) { | ||||
|         auto *reg_base = core->get_regs_base_ptr(); | ||||
|         auto reg_width = arch::traits<ARCH>::reg_bit_width(static_cast<typename arch::traits<ARCH>::reg_e>(reg_no)) / 8; | ||||
|         auto offset = traits<ARCH>::reg_byte_offset(reg_no); | ||||
|         std::copy(data.begin(), data.begin() + reg_width, reg_base + offset); | ||||
|     } else { | ||||
|         typed_addr_t<iss::PHYSICAL> a(iss::DEBUG_WRITE, traits<ARCH>::CSR, reg_no - 65); | ||||
|         core->write(a, data.size(), data.data()); | ||||
|     } | ||||
|     return Ok; | ||||
| } | ||||
|  | ||||
| template <typename ARCH> status riscv_target_adapter<ARCH>::read_mem(uint64_t addr, std::vector<uint8_t> &data) { | ||||
|     auto a = map_addr({iss::DEBUG_READ, iss::VIRTUAL, 0, addr}); | ||||
|     auto f = [&]() -> status { return core->read(a, data.size(), data.data()); }; | ||||
|     return srv->execute_syncronized(f); | ||||
| } | ||||
|  | ||||
| template <typename ARCH> status riscv_target_adapter<ARCH>::write_mem(uint64_t addr, const std::vector<uint8_t> &data) { | ||||
|     auto a = map_addr({iss::DEBUG_READ, iss::VIRTUAL, 0, addr}); | ||||
|     return srv->execute_syncronized(&arch_if::write, core, a, data.size(), data.data()); | ||||
| } | ||||
|  | ||||
| template <typename ARCH> | ||||
| status riscv_target_adapter<ARCH>::process_query(unsigned int &mask, const rp_thread_ref &arg, rp_thread_info &info) { | ||||
|     return NotSupported; | ||||
| } | ||||
|  | ||||
| template <typename ARCH> | ||||
| status riscv_target_adapter<ARCH>::offsets_query(uint64_t &text, uint64_t &data, uint64_t &bss) { | ||||
|     text = 0; | ||||
|     data = 0; | ||||
|     bss = 0; | ||||
|     return Ok; | ||||
| } | ||||
|  | ||||
| template <typename ARCH> status riscv_target_adapter<ARCH>::crc_query(uint64_t addr, size_t len, uint32_t &val) { | ||||
|     return NotSupported; | ||||
| } | ||||
|  | ||||
| template <typename ARCH> status riscv_target_adapter<ARCH>::raw_query(std::string in_buf, std::string &out_buf) { | ||||
|     return NotSupported; | ||||
| } | ||||
|  | ||||
| template <typename ARCH> status riscv_target_adapter<ARCH>::threadinfo_query(int first, std::string &out_buf) { | ||||
|     if (first) { | ||||
|         std::stringstream ss; | ||||
|         ss << "m" << std::hex << thread_idx.val; | ||||
|         out_buf = ss.str(); | ||||
|     } else { | ||||
|         out_buf = "l"; | ||||
|     } | ||||
|     return Ok; | ||||
| } | ||||
|  | ||||
| template <typename ARCH> | ||||
| status riscv_target_adapter<ARCH>::threadextrainfo_query(const rp_thread_ref &thread, std::string &out_buf) { | ||||
|     char buf[20]; | ||||
|     memset(buf, 0, 20); | ||||
|     sprintf(buf, "%02x%02x%02x%02x%02x%02x%02x%02x%02x", 'R', 'u', 'n', 'n', 'a', 'b', 'l', 'e', 0); | ||||
|     out_buf = buf; | ||||
|     return Ok; | ||||
| } | ||||
|  | ||||
| template <typename ARCH> status riscv_target_adapter<ARCH>::packetsize_query(std::string &out_buf) { | ||||
|     out_buf = "PacketSize=1000"; | ||||
|     return Ok; | ||||
| } | ||||
|  | ||||
| template <typename ARCH> status riscv_target_adapter<ARCH>::add_break(int type, uint64_t addr, unsigned int length) { | ||||
|     auto saddr = map_addr({iss::CODE, iss::PHYSICAL, addr}); | ||||
|     auto eaddr = map_addr({iss::CODE, iss::PHYSICAL, addr + length}); | ||||
|     target_adapter_base::bp_lut.addEntry(++target_adapter_base::bp_count, saddr.val, eaddr.val - saddr.val); | ||||
|     LOG(TRACE) << "Adding breakpoint with handle " << target_adapter_base::bp_count << " for addr 0x" << std::hex | ||||
|                << saddr.val << std::dec; | ||||
|     LOG(TRACE) << "Now having " << target_adapter_base::bp_lut.size() << " breakpoints"; | ||||
|     return Ok; | ||||
| } | ||||
|  | ||||
| template <typename ARCH> status riscv_target_adapter<ARCH>::remove_break(int type, uint64_t addr, unsigned int length) { | ||||
|     auto saddr = map_addr({iss::CODE, iss::PHYSICAL, addr}); | ||||
|     unsigned handle = target_adapter_base::bp_lut.getEntry(saddr.val); | ||||
|     // TODO: check length of addr range | ||||
|     if (handle) { | ||||
|         LOG(TRACE) << "Removing breakpoint with handle " << handle << " for addr 0x" << std::hex << saddr.val | ||||
|                    << std::dec; | ||||
|         target_adapter_base::bp_lut.removeEntry(handle); | ||||
|         LOG(TRACE) << "Now having " << target_adapter_base::bp_lut.size() << " breakpoints"; | ||||
|         return Ok; | ||||
|     } | ||||
|     LOG(TRACE) << "Now having " << target_adapter_base::bp_lut.size() << " breakpoints"; | ||||
|     return Err; | ||||
| } | ||||
|  | ||||
| template <typename ARCH> status riscv_target_adapter<ARCH>::resume_from_addr(bool step, int sig, uint64_t addr) { | ||||
|     unsigned reg_no = arch::traits<ARCH>::PC; | ||||
|     std::vector<uint8_t> data(8); | ||||
|     *(reinterpret_cast<uint64_t *>(&data[0])) = addr; | ||||
|     core->set_reg(reg_no, data); | ||||
|     return resume_from_current(step, sig); | ||||
| } | ||||
| } | ||||
| } | ||||
|  | ||||
| #endif /* _ISS_DEBUGGER_RISCV_TARGET_ADAPTER_H_ */ | ||||
| @@ -16,8 +16,8 @@ set(APP_SOURCES main.cpp) | ||||
| set(LIBRARY_NAME risc-v) | ||||
|  | ||||
| # Define the library | ||||
| add_library(${LIBRARY_NAME} ${LIB_SOURCES}) | ||||
|  | ||||
| add_library(${LIBRARY_NAME} SHARED ${LIB_SOURCES}) | ||||
| SET(${LIBRARY_NAME} -Wl,-whole-archive -l${LIBRARY_NAME} -Wl,-no-whole-archive) | ||||
| set_target_properties(${LIBRARY_NAME} PROPERTIES | ||||
|   VERSION ${VERSION}  # ${VERSION} was defined in the main CMakeLists. | ||||
|   FRAMEWORK FALSE | ||||
|   | ||||
| @@ -34,107 +34,24 @@ | ||||
| // | ||||
| //////////////////////////////////////////////////////////////////////////////// | ||||
|  | ||||
| #include <cstring> | ||||
| #include <iss/arch/CORE_DEF_NAME.h> | ||||
| #include <iss/arch/riscv_hart_msu_vp.h> | ||||
| #include <iss/debugger/gdb_session.h> | ||||
| #include <iss/debugger/server.h> | ||||
| #include <iss/iss.h> | ||||
| #include <memory> | ||||
| #include <iss/vm_base.h> | ||||
| #include <util/logging.h> | ||||
|  | ||||
| #include "iss/arch/CORE_DEF_NAME.h" | ||||
| #include "iss/debugger/server.h" | ||||
| #include "iss/vm_base.h" | ||||
|  | ||||
| #include "iss/arch/riscv_hart_msu_vp.h" | ||||
| #include <boost/format.hpp> | ||||
|  | ||||
| #include <iss/debugger/riscv_target_adapter.h> | ||||
|  | ||||
| namespace iss { | ||||
| namespace CORE_DEF_NAME { | ||||
| using namespace iss::arch; | ||||
| using namespace llvm; | ||||
| using namespace iss::debugger; | ||||
|  | ||||
| template <typename ARCH> struct vm_impl; | ||||
|  | ||||
| template <typename ARCH> struct target_adapter : public target_adapter_base { | ||||
|  | ||||
|     target_adapter(server_if *srv, vm_impl<ARCH> *vm) : target_adapter_base(srv), vm(vm) {} | ||||
|  | ||||
|     /*============== Thread Control ===============================*/ | ||||
|  | ||||
|     /* Set generic thread */ | ||||
|     status set_gen_thread(rp_thread_ref &thread) override; | ||||
|  | ||||
|     /* Set control thread */ | ||||
|     status set_ctrl_thread(rp_thread_ref &thread) override; | ||||
|  | ||||
|     /* Get thread status */ | ||||
|     status is_thread_alive(rp_thread_ref &thread, bool &alive) override; | ||||
|  | ||||
|     /*============= Register Access ================================*/ | ||||
|  | ||||
|     /* Read all registers. buf is 4-byte aligned and it is in | ||||
|      target byte order. If  register is not available | ||||
|      corresponding bytes in avail_buf are 0, otherwise | ||||
|      avail buf is 1 */ | ||||
|     status read_registers(std::vector<uint8_t> &data, std::vector<uint8_t> &avail) override; | ||||
|  | ||||
|     /* Write all registers. buf is 4-byte aligned and it is in target | ||||
|      byte order */ | ||||
|     status write_registers(const std::vector<uint8_t> &data) override; | ||||
|  | ||||
|     /* Read one register. buf is 4-byte aligned and it is in | ||||
|      target byte order. If  register is not available | ||||
|      corresponding bytes in avail_buf are 0, otherwise | ||||
|      avail buf is 1 */ | ||||
|     status read_single_register(unsigned int reg_no, std::vector<uint8_t> &buf, | ||||
|                                 std::vector<uint8_t> &avail_buf) override; | ||||
|  | ||||
|     /* Write one register. buf is 4-byte aligned and it is in target byte | ||||
|      order */ | ||||
|     status write_single_register(unsigned int reg_no, const std::vector<uint8_t> &buf) override; | ||||
|  | ||||
|     /*=================== Memory Access =====================*/ | ||||
|  | ||||
|     /* Read memory, buf is 4-bytes aligned and it is in target | ||||
|      byte order */ | ||||
|     status read_mem(uint64_t addr, std::vector<uint8_t> &buf) override; | ||||
|  | ||||
|     /* Write memory, buf is 4-bytes aligned and it is in target | ||||
|      byte order */ | ||||
|     status write_mem(uint64_t addr, const std::vector<uint8_t> &buf) override; | ||||
|  | ||||
|     status process_query(unsigned int &mask, const rp_thread_ref &arg, rp_thread_info &info) override; | ||||
|  | ||||
|     status thread_list_query(int first, const rp_thread_ref &arg, std::vector<rp_thread_ref> &result, size_t max_num, | ||||
|                              size_t &num, bool &done) override; | ||||
|  | ||||
|     status current_thread_query(rp_thread_ref &thread) override; | ||||
|  | ||||
|     status offsets_query(uint64_t &text, uint64_t &data, uint64_t &bss) override; | ||||
|  | ||||
|     status crc_query(uint64_t addr, size_t len, uint32_t &val) override; | ||||
|  | ||||
|     status raw_query(std::string in_buf, std::string &out_buf) override; | ||||
|  | ||||
|     status threadinfo_query(int first, std::string &out_buf) override; | ||||
|  | ||||
|     status threadextrainfo_query(const rp_thread_ref &thread, std::string &out_buf) override; | ||||
|  | ||||
|     status packetsize_query(std::string &out_buf) override; | ||||
|  | ||||
|     status add_break(int type, uint64_t addr, unsigned int length) override; | ||||
|  | ||||
|     status remove_break(int type, uint64_t addr, unsigned int length) override; | ||||
|  | ||||
|     status resume_from_addr(bool step, int sig, uint64_t addr) override; | ||||
|  | ||||
| protected: | ||||
|     static inline constexpr addr_t map_addr(const addr_t &i) { return i; } | ||||
|  | ||||
|     vm_impl<ARCH> *vm; | ||||
|     rp_thread_ref thread_idx; | ||||
| }; | ||||
|  | ||||
| template <typename ARCH> struct vm_impl : public vm::vm_base<ARCH> { | ||||
|     using super = typename vm::vm_base<ARCH>; | ||||
|     using virt_addr_t = typename super::virt_addr_t; | ||||
| @@ -151,7 +68,7 @@ template <typename ARCH> struct vm_impl : public vm::vm_base<ARCH> { | ||||
|     target_adapter_if *accquire_target_adapter(server_if *srv) { | ||||
|         debugger_if::dbg_enabled = true; | ||||
|         if (vm::vm_base<ARCH>::tgt_adapter == nullptr) | ||||
|             vm::vm_base<ARCH>::tgt_adapter = new target_adapter<ARCH>(srv, this); | ||||
|             vm::vm_base<ARCH>::tgt_adapter = new riscv_target_adapter<ARCH>(srv, this->get_arch()); | ||||
|         return vm::vm_base<ARCH>::tgt_adapter; | ||||
|     } | ||||
|  | ||||
| @@ -326,7 +243,9 @@ template <typename CODE_WORD> void debug_fn(CODE_WORD insn) { | ||||
|  | ||||
| template <typename ARCH> vm_impl<ARCH>::vm_impl() { this(new ARCH()); } | ||||
|  | ||||
| template <typename ARCH> vm_impl<ARCH>::vm_impl(ARCH &core, bool dump) : vm::vm_base<ARCH>(core, dump) { | ||||
| template <typename ARCH> | ||||
| vm_impl<ARCH>::vm_impl(ARCH &core, bool dump) | ||||
| : vm::vm_base<ARCH>(core, dump) { | ||||
|     qlut[0] = lut_00.data(); | ||||
|     qlut[1] = lut_01.data(); | ||||
|     qlut[2] = lut_10.data(); | ||||
| @@ -419,232 +338,25 @@ template <typename ARCH> inline void vm_impl<ARCH>::gen_trap_check(llvm::BasicBl | ||||
|  | ||||
| } // namespace CORE_DEF_NAME | ||||
|  | ||||
| #define CREATE_FUNCS(ARCH)                                                                                             \ | ||||
|     template <> std::unique_ptr<vm_if> create<ARCH>(ARCH * core, unsigned short port, bool dump) {                     \ | ||||
|         std::unique_ptr<CORE_DEF_NAME::vm_impl<ARCH>> ret =                                                            \ | ||||
|             std::make_unique<CORE_DEF_NAME::vm_impl<ARCH>>(*core, dump);                                               \ | ||||
|         debugger::server<debugger::gdb_session>::run_server(ret.get(), port);                                          \ | ||||
|         return ret;                                                                                                    \ | ||||
|     }                                                                                                                  \ | ||||
|     template <> std::unique_ptr<vm_if> create<ARCH>(std::string inst_name, unsigned short port, bool dump) {           \ | ||||
|         return create<ARCH>(new arch::riscv_hart_msu_vp<ARCH>(), port, dump); /* FIXME: memory leak!!!!!!! */          \ | ||||
|     }                                                                                                                  \ | ||||
|     template <> std::unique_ptr<vm_if> create<ARCH>(ARCH * core, bool dump) {                                          \ | ||||
|         return std::make_unique<CORE_DEF_NAME::vm_impl<ARCH>>(*core, dump); /* FIXME: memory leak!!!!!!! */            \ | ||||
|     }                                                                                                                  \ | ||||
|     template <> std::unique_ptr<vm_if> create<ARCH>(std::string inst_name, bool dump) {                                \ | ||||
|         return create<ARCH>(new arch::riscv_hart_msu_vp<ARCH>(), dump);                                                \ | ||||
|     } | ||||
|  | ||||
| CREATE_FUNCS(arch::CORE_DEF_NAME) | ||||
|  | ||||
| namespace CORE_DEF_NAME { | ||||
|  | ||||
| template <typename ARCH> status target_adapter<ARCH>::set_gen_thread(rp_thread_ref &thread) { | ||||
|     thread_idx = thread; | ||||
|     return Ok; | ||||
| template <> | ||||
| std::unique_ptr<vm_if> create<arch::CORE_DEF_NAME>(arch::CORE_DEF_NAME *core, unsigned short port, bool dump) { | ||||
|     std::unique_ptr<CORE_DEF_NAME::vm_impl<arch::CORE_DEF_NAME>> ret = | ||||
|         std::make_unique<CORE_DEF_NAME::vm_impl<arch::CORE_DEF_NAME>>(*core, dump); | ||||
|     debugger::server<debugger::gdb_session>::run_server(ret.get(), port); | ||||
|     return ret; | ||||
| } | ||||
|  | ||||
| template <typename ARCH> status target_adapter<ARCH>::set_ctrl_thread(rp_thread_ref &thread) { | ||||
|     thread_idx = thread; | ||||
|     return Ok; | ||||
| template <> std::unique_ptr<vm_if> create<arch::CORE_DEF_NAME>(std::string inst_name, unsigned short port, bool dump) { | ||||
|     return create<arch::CORE_DEF_NAME>(new arch::riscv_hart_msu_vp<arch::CORE_DEF_NAME>(), port, | ||||
|                                        dump); /* FIXME: memory leak!!!!!!! */ | ||||
| } | ||||
|  | ||||
| template <typename ARCH> status target_adapter<ARCH>::is_thread_alive(rp_thread_ref &thread, bool &alive) { | ||||
|     alive = 1; | ||||
|     return Ok; | ||||
| template <> std::unique_ptr<vm_if> create<arch::CORE_DEF_NAME>(arch::CORE_DEF_NAME *core, bool dump) { | ||||
|     return std::make_unique<CORE_DEF_NAME::vm_impl<arch::CORE_DEF_NAME>>(*core, dump); /* FIXME: memory leak!!!!!!! */ | ||||
| } | ||||
|  | ||||
| /* List threads. If first is non-zero then start from the first thread, | ||||
|  * otherwise start from arg, result points to array of threads to be | ||||
|  * filled out, result size is number of elements in the result, | ||||
|  * num points to the actual number of threads found, done is | ||||
|  * set if all threads are processed. | ||||
|  */ | ||||
| template <typename ARCH> | ||||
| status target_adapter<ARCH>::thread_list_query(int first, const rp_thread_ref &arg, std::vector<rp_thread_ref> &result, | ||||
|                                                size_t max_num, size_t &num, bool &done) { | ||||
|     if (first == 0) { | ||||
|         result.clear(); | ||||
|         result.push_back(thread_idx); | ||||
|         num = 1; | ||||
|         done = true; | ||||
|         return Ok; | ||||
|     } else | ||||
|         return NotSupported; | ||||
| template <> std::unique_ptr<vm_if> create<arch::CORE_DEF_NAME>(std::string inst_name, bool dump) { | ||||
|     return create<arch::CORE_DEF_NAME>(new arch::riscv_hart_msu_vp<arch::CORE_DEF_NAME>(), dump); | ||||
| } | ||||
|  | ||||
| template <typename ARCH> status target_adapter<ARCH>::current_thread_query(rp_thread_ref &thread) { | ||||
|     thread = thread_idx; | ||||
|     return Ok; | ||||
| } | ||||
|  | ||||
| template <typename ARCH> | ||||
| status target_adapter<ARCH>::read_registers(std::vector<uint8_t> &data, std::vector<uint8_t> &avail) { | ||||
|     LOG(TRACE) << "reading target registers"; | ||||
|     // return idx<0?:; | ||||
|     data.clear(); | ||||
|     avail.clear(); | ||||
|     const uint8_t* reg_base = vm->get_arch()->get_regs_base_ptr(); | ||||
|     for (size_t reg_no = 0; reg_no < arch::traits<ARCH>::NUM_REGS; ++reg_no) { | ||||
|         auto reg_width = arch::traits<ARCH>::reg_bit_width(static_cast<typename arch::traits<ARCH>::reg_e>(reg_no))/8; | ||||
|         unsigned offset = traits<ARCH>::reg_byte_offset(reg_no); | ||||
|         for (size_t j = 0; j < reg_width; ++j) { | ||||
|             data.push_back(*(reg_base+offset+j)); | ||||
|             avail.push_back(0xff); | ||||
|         } | ||||
|     } | ||||
|     // work around fill with F type registers | ||||
|     if (arch::traits<ARCH>::NUM_REGS < 65) { | ||||
|         auto reg_width = sizeof(typename arch::traits<ARCH>::reg_t); | ||||
|         for (size_t reg_no = 0; reg_no < 33; ++reg_no) { | ||||
|             for (size_t j = 0; j < reg_width; ++j) { | ||||
|                 data.push_back(0x0); | ||||
|                 avail.push_back(0x00); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|     return Ok; | ||||
| } | ||||
|  | ||||
| template <typename ARCH> status target_adapter<ARCH>::write_registers(const std::vector<uint8_t> &data) { | ||||
|     auto reg_count = arch::traits<ARCH>::NUM_REGS; | ||||
|     auto* reg_base = vm->get_arch()->get_regs_base_ptr(); | ||||
|     auto iter = data.data(); | ||||
|     for (size_t reg_no = 0; reg_no < reg_count; ++reg_no) { | ||||
|         auto reg_width = arch::traits<ARCH>::reg_bit_width(static_cast<typename arch::traits<ARCH>::reg_e>(reg_no))/8; | ||||
|         auto offset = traits<ARCH>::reg_byte_offset(reg_no); | ||||
|         std::copy(iter , iter + reg_width, reg_base); | ||||
|         iter+=4; | ||||
|         reg_base+=offset; | ||||
|     } | ||||
|     return Ok; | ||||
| } | ||||
|  | ||||
| template <typename ARCH> | ||||
| status target_adapter<ARCH>::read_single_register(unsigned int reg_no, std::vector<uint8_t> &data, | ||||
|                                                   std::vector<uint8_t> &avail) { | ||||
|     if (reg_no < 65) { | ||||
|         // auto reg_size = arch::traits<ARCH>::reg_bit_width(static_cast<typename | ||||
|         // arch::traits<ARCH>::reg_e>(reg_no))/8; | ||||
|         auto* reg_base = vm->get_arch()->get_regs_base_ptr(); | ||||
|         auto reg_width = arch::traits<ARCH>::reg_bit_width(static_cast<typename arch::traits<ARCH>::reg_e>(reg_no))/8; | ||||
|         data.resize(reg_width); | ||||
|         avail.resize(reg_width); | ||||
|         auto offset = traits<ARCH>::reg_byte_offset(reg_no); | ||||
|         std::copy(reg_base+offset, reg_base+offset+reg_width, data.begin()); | ||||
|         std::fill(avail.begin(), avail.end(), 0xff); | ||||
|     } else { | ||||
|         typed_addr_t<iss::PHYSICAL> a(iss::DEBUG_READ, traits<ARCH>::CSR, reg_no - 65); | ||||
|         data.resize(sizeof(typename traits<ARCH>::reg_t)); | ||||
|         avail.resize(sizeof(typename traits<ARCH>::reg_t)); | ||||
|         std::fill(avail.begin(), avail.end(), 0xff); | ||||
|         vm->get_arch()->read(a, data.size(), data.data()); | ||||
|     } | ||||
|     return data.size() > 0 ? Ok : Err; | ||||
| } | ||||
|  | ||||
| template <typename ARCH> | ||||
| status target_adapter<ARCH>::write_single_register(unsigned int reg_no, const std::vector<uint8_t> &data) { | ||||
|     if (reg_no < 65){ | ||||
|         auto* reg_base = vm->get_arch()->get_regs_base_ptr(); | ||||
|         auto reg_width = arch::traits<ARCH>::reg_bit_width(static_cast<typename arch::traits<ARCH>::reg_e>(reg_no))/8; | ||||
|         auto  offset = traits<ARCH>::reg_byte_offset(reg_no); | ||||
|         std::copy(data.begin(), data.begin() + reg_width, reg_base+offset); | ||||
|     } else { | ||||
|         typed_addr_t<iss::PHYSICAL> a(iss::DEBUG_WRITE, traits<ARCH>::CSR, reg_no - 65); | ||||
|         vm->get_arch()->write(a, data.size(), data.data()); | ||||
|     } | ||||
|     return Ok; | ||||
| } | ||||
|  | ||||
| template <typename ARCH> status target_adapter<ARCH>::read_mem(uint64_t addr, std::vector<uint8_t> &data) { | ||||
|     auto a = map_addr({iss::DEBUG_READ, iss::VIRTUAL, 0, addr}); | ||||
|     auto f = [&]() -> status { return vm->get_arch()->read(a, data.size(), data.data()); }; | ||||
|     return srv->execute_syncronized(f); | ||||
| } | ||||
|  | ||||
| template <typename ARCH> status target_adapter<ARCH>::write_mem(uint64_t addr, const std::vector<uint8_t> &data) { | ||||
|     auto a = map_addr({iss::DEBUG_READ, iss::VIRTUAL, 0, addr}); | ||||
|     return srv->execute_syncronized(&arch_if::write, vm->get_arch(), a, data.size(), data.data()); | ||||
| } | ||||
|  | ||||
| template <typename ARCH> | ||||
| status target_adapter<ARCH>::process_query(unsigned int &mask, const rp_thread_ref &arg, rp_thread_info &info) { | ||||
|     return NotSupported; | ||||
| } | ||||
|  | ||||
| template <typename ARCH> status target_adapter<ARCH>::offsets_query(uint64_t &text, uint64_t &data, uint64_t &bss) { | ||||
|     text = 0; | ||||
|     data = 0; | ||||
|     bss = 0; | ||||
|     return Ok; | ||||
| } | ||||
|  | ||||
| template <typename ARCH> status target_adapter<ARCH>::crc_query(uint64_t addr, size_t len, uint32_t &val) { | ||||
|     return NotSupported; | ||||
| } | ||||
|  | ||||
| template <typename ARCH> status target_adapter<ARCH>::raw_query(std::string in_buf, std::string &out_buf) { | ||||
|     return NotSupported; | ||||
| } | ||||
|  | ||||
| template <typename ARCH> status target_adapter<ARCH>::threadinfo_query(int first, std::string &out_buf) { | ||||
|     if (first) { | ||||
|         std::stringstream ss; | ||||
|         ss << "m" << std::hex << thread_idx.val; | ||||
|         out_buf = ss.str(); | ||||
|     } else { | ||||
|         out_buf = "l"; | ||||
|     } | ||||
|     return Ok; | ||||
| } | ||||
|  | ||||
| template <typename ARCH> | ||||
| status target_adapter<ARCH>::threadextrainfo_query(const rp_thread_ref &thread, std::string &out_buf) { | ||||
|     char buf[20]; | ||||
|     memset(buf, 0, 20); | ||||
|     sprintf(buf, "%02x%02x%02x%02x%02x%02x%02x%02x%02x", 'R', 'u', 'n', 'n', 'a', 'b', 'l', 'e', 0); | ||||
|     out_buf = buf; | ||||
|     return Ok; | ||||
| } | ||||
|  | ||||
| template <typename ARCH> status target_adapter<ARCH>::packetsize_query(std::string &out_buf) { | ||||
|     out_buf = "PacketSize=1000"; | ||||
|     return Ok; | ||||
| } | ||||
|  | ||||
| template <typename ARCH> status target_adapter<ARCH>::add_break(int type, uint64_t addr, unsigned int length) { | ||||
|     auto saddr = map_addr({iss::CODE, iss::PHYSICAL, addr}); | ||||
|     auto eaddr = map_addr({iss::CODE, iss::PHYSICAL, addr + length}); | ||||
|     target_adapter_base::bp_lut.addEntry(++target_adapter_base::bp_count, saddr.val, eaddr.val - saddr.val); | ||||
|     LOG(TRACE) << "Adding breakpoint with handle " << target_adapter_base::bp_count << " for addr 0x" << std::hex | ||||
|                << saddr.val << std::dec; | ||||
|     LOG(TRACE) << "Now having " << target_adapter_base::bp_lut.size() << " breakpoints"; | ||||
|     return Ok; | ||||
| } | ||||
|  | ||||
| template <typename ARCH> status target_adapter<ARCH>::remove_break(int type, uint64_t addr, unsigned int length) { | ||||
|     auto saddr = map_addr({iss::CODE, iss::PHYSICAL, addr}); | ||||
|     unsigned handle = target_adapter_base::bp_lut.getEntry(saddr.val); | ||||
|     // TODO: check length of addr range | ||||
|     if (handle) { | ||||
|         LOG(TRACE) << "Removing breakpoint with handle " << handle << " for addr 0x" << std::hex << saddr.val | ||||
|                    << std::dec; | ||||
|         target_adapter_base::bp_lut.removeEntry(handle); | ||||
|         LOG(TRACE) << "Now having " << target_adapter_base::bp_lut.size() << " breakpoints"; | ||||
|         return Ok; | ||||
|     } | ||||
|     LOG(TRACE) << "Now having " << target_adapter_base::bp_lut.size() << " breakpoints"; | ||||
|     return Err; | ||||
| } | ||||
|  | ||||
| template <typename ARCH> status target_adapter<ARCH>::resume_from_addr(bool step, int sig, uint64_t addr) { | ||||
|     unsigned reg_no = arch::traits<ARCH>::PC; | ||||
|     std::vector<uint8_t> data(8); | ||||
|     *(reinterpret_cast<uint64_t *>(&data[0])) = addr; | ||||
|     vm->get_arch()->set_reg(reg_no, data); | ||||
|     return resume_from_current(step, sig); | ||||
| } | ||||
| } // namespace CORE_DEF_NAME | ||||
| } // namespace iss | ||||
|   | ||||
| @@ -34,107 +34,24 @@ | ||||
| // | ||||
| //////////////////////////////////////////////////////////////////////////////// | ||||
|  | ||||
| #include <cstring> | ||||
| #include <iss/arch/riscv_hart_msu_vp.h> | ||||
| #include <iss/arch/rv32imac.h> | ||||
| #include <iss/debugger/gdb_session.h> | ||||
| #include <iss/debugger/server.h> | ||||
| #include <iss/iss.h> | ||||
| #include <memory> | ||||
| #include <iss/vm_base.h> | ||||
| #include <util/logging.h> | ||||
|  | ||||
| #include "iss/arch/rv32imac.h" | ||||
| #include "iss/debugger/server.h" | ||||
| #include "iss/vm_base.h" | ||||
|  | ||||
| #include "iss/arch/riscv_hart_msu_vp.h" | ||||
| #include <boost/format.hpp> | ||||
|  | ||||
| #include <iss/debugger/riscv_target_adapter.h> | ||||
|  | ||||
| namespace iss { | ||||
| namespace rv32imac { | ||||
| using namespace iss::arch; | ||||
| using namespace llvm; | ||||
| using namespace iss::debugger; | ||||
|  | ||||
| template <typename ARCH> struct vm_impl; | ||||
|  | ||||
| template <typename ARCH> struct target_adapter : public target_adapter_base { | ||||
|  | ||||
|     target_adapter(server_if *srv, vm_impl<ARCH> *vm) : target_adapter_base(srv), vm(vm) {} | ||||
|  | ||||
|     /*============== Thread Control ===============================*/ | ||||
|  | ||||
|     /* Set generic thread */ | ||||
|     status set_gen_thread(rp_thread_ref &thread) override; | ||||
|  | ||||
|     /* Set control thread */ | ||||
|     status set_ctrl_thread(rp_thread_ref &thread) override; | ||||
|  | ||||
|     /* Get thread status */ | ||||
|     status is_thread_alive(rp_thread_ref &thread, bool &alive) override; | ||||
|  | ||||
|     /*============= Register Access ================================*/ | ||||
|  | ||||
|     /* Read all registers. buf is 4-byte aligned and it is in | ||||
|      target byte order. If  register is not available | ||||
|      corresponding bytes in avail_buf are 0, otherwise | ||||
|      avail buf is 1 */ | ||||
|     status read_registers(std::vector<uint8_t> &data, std::vector<uint8_t> &avail) override; | ||||
|  | ||||
|     /* Write all registers. buf is 4-byte aligned and it is in target | ||||
|      byte order */ | ||||
|     status write_registers(const std::vector<uint8_t> &data) override; | ||||
|  | ||||
|     /* Read one register. buf is 4-byte aligned and it is in | ||||
|      target byte order. If  register is not available | ||||
|      corresponding bytes in avail_buf are 0, otherwise | ||||
|      avail buf is 1 */ | ||||
|     status read_single_register(unsigned int reg_no, std::vector<uint8_t> &buf, | ||||
|                                 std::vector<uint8_t> &avail_buf) override; | ||||
|  | ||||
|     /* Write one register. buf is 4-byte aligned and it is in target byte | ||||
|      order */ | ||||
|     status write_single_register(unsigned int reg_no, const std::vector<uint8_t> &buf) override; | ||||
|  | ||||
|     /*=================== Memory Access =====================*/ | ||||
|  | ||||
|     /* Read memory, buf is 4-bytes aligned and it is in target | ||||
|      byte order */ | ||||
|     status read_mem(uint64_t addr, std::vector<uint8_t> &buf) override; | ||||
|  | ||||
|     /* Write memory, buf is 4-bytes aligned and it is in target | ||||
|      byte order */ | ||||
|     status write_mem(uint64_t addr, const std::vector<uint8_t> &buf) override; | ||||
|  | ||||
|     status process_query(unsigned int &mask, const rp_thread_ref &arg, rp_thread_info &info) override; | ||||
|  | ||||
|     status thread_list_query(int first, const rp_thread_ref &arg, std::vector<rp_thread_ref> &result, size_t max_num, | ||||
|                              size_t &num, bool &done) override; | ||||
|  | ||||
|     status current_thread_query(rp_thread_ref &thread) override; | ||||
|  | ||||
|     status offsets_query(uint64_t &text, uint64_t &data, uint64_t &bss) override; | ||||
|  | ||||
|     status crc_query(uint64_t addr, size_t len, uint32_t &val) override; | ||||
|  | ||||
|     status raw_query(std::string in_buf, std::string &out_buf) override; | ||||
|  | ||||
|     status threadinfo_query(int first, std::string &out_buf) override; | ||||
|  | ||||
|     status threadextrainfo_query(const rp_thread_ref &thread, std::string &out_buf) override; | ||||
|  | ||||
|     status packetsize_query(std::string &out_buf) override; | ||||
|  | ||||
|     status add_break(int type, uint64_t addr, unsigned int length) override; | ||||
|  | ||||
|     status remove_break(int type, uint64_t addr, unsigned int length) override; | ||||
|  | ||||
|     status resume_from_addr(bool step, int sig, uint64_t addr) override; | ||||
|  | ||||
| protected: | ||||
|     static inline constexpr addr_t map_addr(const addr_t &i) { return i; } | ||||
|  | ||||
|     vm_impl<ARCH> *vm; | ||||
|     rp_thread_ref thread_idx; | ||||
| }; | ||||
|  | ||||
| template <typename ARCH> struct vm_impl : public vm::vm_base<ARCH> { | ||||
|     using super = typename vm::vm_base<ARCH>; | ||||
|     using virt_addr_t = typename super::virt_addr_t; | ||||
| @@ -151,7 +68,7 @@ template <typename ARCH> struct vm_impl : public vm::vm_base<ARCH> { | ||||
|     target_adapter_if *accquire_target_adapter(server_if *srv) { | ||||
|         debugger_if::dbg_enabled = true; | ||||
|         if (vm::vm_base<ARCH>::tgt_adapter == nullptr) | ||||
|             vm::vm_base<ARCH>::tgt_adapter = new target_adapter<ARCH>(srv, this); | ||||
|             vm::vm_base<ARCH>::tgt_adapter = new riscv_target_adapter<ARCH>(srv, this->get_arch()); | ||||
|         return vm::vm_base<ARCH>::tgt_adapter; | ||||
|     } | ||||
|  | ||||
| @@ -3999,7 +3916,9 @@ template <typename CODE_WORD> void debug_fn(CODE_WORD insn) { | ||||
|  | ||||
| template <typename ARCH> vm_impl<ARCH>::vm_impl() { this(new ARCH()); } | ||||
|  | ||||
| template <typename ARCH> vm_impl<ARCH>::vm_impl(ARCH &core, bool dump) : vm::vm_base<ARCH>(core, dump) { | ||||
| template <typename ARCH> | ||||
| vm_impl<ARCH>::vm_impl(ARCH &core, bool dump) | ||||
| : vm::vm_base<ARCH>(core, dump) { | ||||
|     qlut[0] = lut_00.data(); | ||||
|     qlut[1] = lut_01.data(); | ||||
|     qlut[2] = lut_10.data(); | ||||
| @@ -4092,232 +4011,24 @@ template <typename ARCH> inline void vm_impl<ARCH>::gen_trap_check(llvm::BasicBl | ||||
|  | ||||
| } // namespace rv32imac | ||||
|  | ||||
| #define CREATE_FUNCS(ARCH)                                                                                             \ | ||||
|     template <> std::unique_ptr<vm_if> create<ARCH>(ARCH * core, unsigned short port, bool dump) {                     \ | ||||
|         std::unique_ptr<rv32imac::vm_impl<ARCH>> ret =                                                                 \ | ||||
|             std::make_unique<rv32imac::vm_impl<ARCH>>(*core, dump);                                                    \ | ||||
|         debugger::server<debugger::gdb_session>::run_server(ret.get(), port);                                          \ | ||||
|         return ret;                                                                                                    \ | ||||
|     }                                                                                                                  \ | ||||
|     template <> std::unique_ptr<vm_if> create<ARCH>(std::string inst_name, unsigned short port, bool dump) {           \ | ||||
|         return create<ARCH>(new arch::riscv_hart_msu_vp<ARCH>(), port, dump); /* FIXME: memory leak!!!!!!! */          \ | ||||
|     }                                                                                                                  \ | ||||
|     template <> std::unique_ptr<vm_if> create<ARCH>(ARCH * core, bool dump) {                                          \ | ||||
|         return std::make_unique<rv32imac::vm_impl<ARCH>>(*core, dump); /* FIXME: memory leak!!!!!!! */                 \ | ||||
|     }                                                                                                                  \ | ||||
|     template <> std::unique_ptr<vm_if> create<ARCH>(std::string inst_name, bool dump) {                                \ | ||||
|         return create<ARCH>(new arch::riscv_hart_msu_vp<ARCH>(), dump);                                                \ | ||||
|     } | ||||
|  | ||||
| CREATE_FUNCS(arch::rv32imac) | ||||
|  | ||||
| namespace rv32imac { | ||||
|  | ||||
| template <typename ARCH> status target_adapter<ARCH>::set_gen_thread(rp_thread_ref &thread) { | ||||
|     thread_idx = thread; | ||||
|     return Ok; | ||||
| template <> std::unique_ptr<vm_if> create<arch::rv32imac>(arch::rv32imac *core, unsigned short port, bool dump) { | ||||
|     std::unique_ptr<rv32imac::vm_impl<arch::rv32imac>> ret = | ||||
|         std::make_unique<rv32imac::vm_impl<arch::rv32imac>>(*core, dump); | ||||
|     debugger::server<debugger::gdb_session>::run_server(ret.get(), port); | ||||
|     return ret; | ||||
| } | ||||
|  | ||||
| template <typename ARCH> status target_adapter<ARCH>::set_ctrl_thread(rp_thread_ref &thread) { | ||||
|     thread_idx = thread; | ||||
|     return Ok; | ||||
| template <> std::unique_ptr<vm_if> create<arch::rv32imac>(std::string inst_name, unsigned short port, bool dump) { | ||||
|     return create<arch::rv32imac>(new arch::riscv_hart_msu_vp<arch::rv32imac>(), port, | ||||
|                                   dump); /* FIXME: memory leak!!!!!!! */ | ||||
| } | ||||
|  | ||||
| template <typename ARCH> status target_adapter<ARCH>::is_thread_alive(rp_thread_ref &thread, bool &alive) { | ||||
|     alive = 1; | ||||
|     return Ok; | ||||
| template <> std::unique_ptr<vm_if> create<arch::rv32imac>(arch::rv32imac *core, bool dump) { | ||||
|     return std::make_unique<rv32imac::vm_impl<arch::rv32imac>>(*core, dump); /* FIXME: memory leak!!!!!!! */ | ||||
| } | ||||
|  | ||||
| /* List threads. If first is non-zero then start from the first thread, | ||||
|  * otherwise start from arg, result points to array of threads to be | ||||
|  * filled out, result size is number of elements in the result, | ||||
|  * num points to the actual number of threads found, done is | ||||
|  * set if all threads are processed. | ||||
|  */ | ||||
| template <typename ARCH> | ||||
| status target_adapter<ARCH>::thread_list_query(int first, const rp_thread_ref &arg, std::vector<rp_thread_ref> &result, | ||||
|                                                size_t max_num, size_t &num, bool &done) { | ||||
|     if (first == 0) { | ||||
|         result.clear(); | ||||
|         result.push_back(thread_idx); | ||||
|         num = 1; | ||||
|         done = true; | ||||
|         return Ok; | ||||
|     } else | ||||
|         return NotSupported; | ||||
| template <> std::unique_ptr<vm_if> create<arch::rv32imac>(std::string inst_name, bool dump) { | ||||
|     return create<arch::rv32imac>(new arch::riscv_hart_msu_vp<arch::rv32imac>(), dump); | ||||
| } | ||||
|  | ||||
| template <typename ARCH> status target_adapter<ARCH>::current_thread_query(rp_thread_ref &thread) { | ||||
|     thread = thread_idx; | ||||
|     return Ok; | ||||
| } | ||||
|  | ||||
| template <typename ARCH> | ||||
| status target_adapter<ARCH>::read_registers(std::vector<uint8_t> &data, std::vector<uint8_t> &avail) { | ||||
|     LOG(TRACE) << "reading target registers"; | ||||
|     // return idx<0?:; | ||||
|     data.clear(); | ||||
|     avail.clear(); | ||||
|     const uint8_t* reg_base = vm->get_arch()->get_regs_base_ptr(); | ||||
|     for (size_t reg_no = 0; reg_no < arch::traits<ARCH>::NUM_REGS; ++reg_no) { | ||||
|         auto reg_width = arch::traits<ARCH>::reg_bit_width(static_cast<typename arch::traits<ARCH>::reg_e>(reg_no))/8; | ||||
|         unsigned offset = traits<ARCH>::reg_byte_offset(reg_no); | ||||
|         for (size_t j = 0; j < reg_width; ++j) { | ||||
|             data.push_back(*(reg_base+offset+j)); | ||||
|             avail.push_back(0xff); | ||||
|         } | ||||
|     } | ||||
|     // work around fill with F type registers | ||||
|     if (arch::traits<ARCH>::NUM_REGS < 65) { | ||||
|         auto reg_width = sizeof(typename arch::traits<ARCH>::reg_t); | ||||
|         for (size_t reg_no = 0; reg_no < 33; ++reg_no) { | ||||
|             for (size_t j = 0; j < reg_width; ++j) { | ||||
|                 data.push_back(0x0); | ||||
|                 avail.push_back(0x00); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|     return Ok; | ||||
| } | ||||
|  | ||||
| template <typename ARCH> status target_adapter<ARCH>::write_registers(const std::vector<uint8_t> &data) { | ||||
|     auto reg_count = arch::traits<ARCH>::NUM_REGS; | ||||
|     auto* reg_base = vm->get_arch()->get_regs_base_ptr(); | ||||
|     auto iter = data.data(); | ||||
|     for (size_t reg_no = 0; reg_no < reg_count; ++reg_no) { | ||||
|         auto reg_width = arch::traits<ARCH>::reg_bit_width(static_cast<typename arch::traits<ARCH>::reg_e>(reg_no))/8; | ||||
|         auto offset = traits<ARCH>::reg_byte_offset(reg_no); | ||||
|         std::copy(iter , iter + reg_width, reg_base); | ||||
|         iter+=4; | ||||
|         reg_base+=offset; | ||||
|     } | ||||
|     return Ok; | ||||
| } | ||||
|  | ||||
| template <typename ARCH> | ||||
| status target_adapter<ARCH>::read_single_register(unsigned int reg_no, std::vector<uint8_t> &data, | ||||
|                                                   std::vector<uint8_t> &avail) { | ||||
|     if (reg_no < 65) { | ||||
|         // auto reg_size = arch::traits<ARCH>::reg_bit_width(static_cast<typename | ||||
|         // arch::traits<ARCH>::reg_e>(reg_no))/8; | ||||
|         auto* reg_base = vm->get_arch()->get_regs_base_ptr(); | ||||
|         auto reg_width = arch::traits<ARCH>::reg_bit_width(static_cast<typename arch::traits<ARCH>::reg_e>(reg_no))/8; | ||||
|         data.resize(reg_width); | ||||
|         avail.resize(reg_width); | ||||
|         auto offset = traits<ARCH>::reg_byte_offset(reg_no); | ||||
|         std::copy(reg_base+offset, reg_base+offset+reg_width, data.begin()); | ||||
|         std::fill(avail.begin(), avail.end(), 0xff); | ||||
|     } else { | ||||
|         typed_addr_t<iss::PHYSICAL> a(iss::DEBUG_READ, traits<ARCH>::CSR, reg_no - 65); | ||||
|         data.resize(sizeof(typename traits<ARCH>::reg_t)); | ||||
|         avail.resize(sizeof(typename traits<ARCH>::reg_t)); | ||||
|         std::fill(avail.begin(), avail.end(), 0xff); | ||||
|         vm->get_arch()->read(a, data.size(), data.data()); | ||||
|     } | ||||
|     return data.size() > 0 ? Ok : Err; | ||||
| } | ||||
|  | ||||
| template <typename ARCH> | ||||
| status target_adapter<ARCH>::write_single_register(unsigned int reg_no, const std::vector<uint8_t> &data) { | ||||
|     if (reg_no < 65){ | ||||
|         auto* reg_base = vm->get_arch()->get_regs_base_ptr(); | ||||
|         auto reg_width = arch::traits<ARCH>::reg_bit_width(static_cast<typename arch::traits<ARCH>::reg_e>(reg_no))/8; | ||||
|         auto  offset = traits<ARCH>::reg_byte_offset(reg_no); | ||||
|         std::copy(data.begin(), data.begin() + reg_width, reg_base+offset); | ||||
|     } else { | ||||
|         typed_addr_t<iss::PHYSICAL> a(iss::DEBUG_WRITE, traits<ARCH>::CSR, reg_no - 65); | ||||
|         vm->get_arch()->write(a, data.size(), data.data()); | ||||
|     } | ||||
|     return Ok; | ||||
| } | ||||
|  | ||||
| template <typename ARCH> status target_adapter<ARCH>::read_mem(uint64_t addr, std::vector<uint8_t> &data) { | ||||
|     auto a = map_addr({iss::DEBUG_READ, iss::VIRTUAL, 0, addr}); | ||||
|     auto f = [&]() -> status { return vm->get_arch()->read(a, data.size(), data.data()); }; | ||||
|     return srv->execute_syncronized(f); | ||||
| } | ||||
|  | ||||
| template <typename ARCH> status target_adapter<ARCH>::write_mem(uint64_t addr, const std::vector<uint8_t> &data) { | ||||
|     auto a = map_addr({iss::DEBUG_READ, iss::VIRTUAL, 0, addr}); | ||||
|     return srv->execute_syncronized(&arch_if::write, vm->get_arch(), a, data.size(), data.data()); | ||||
| } | ||||
|  | ||||
| template <typename ARCH> | ||||
| status target_adapter<ARCH>::process_query(unsigned int &mask, const rp_thread_ref &arg, rp_thread_info &info) { | ||||
|     return NotSupported; | ||||
| } | ||||
|  | ||||
| template <typename ARCH> status target_adapter<ARCH>::offsets_query(uint64_t &text, uint64_t &data, uint64_t &bss) { | ||||
|     text = 0; | ||||
|     data = 0; | ||||
|     bss = 0; | ||||
|     return Ok; | ||||
| } | ||||
|  | ||||
| template <typename ARCH> status target_adapter<ARCH>::crc_query(uint64_t addr, size_t len, uint32_t &val) { | ||||
|     return NotSupported; | ||||
| } | ||||
|  | ||||
| template <typename ARCH> status target_adapter<ARCH>::raw_query(std::string in_buf, std::string &out_buf) { | ||||
|     return NotSupported; | ||||
| } | ||||
|  | ||||
| template <typename ARCH> status target_adapter<ARCH>::threadinfo_query(int first, std::string &out_buf) { | ||||
|     if (first) { | ||||
|         std::stringstream ss; | ||||
|         ss << "m" << std::hex << thread_idx.val; | ||||
|         out_buf = ss.str(); | ||||
|     } else { | ||||
|         out_buf = "l"; | ||||
|     } | ||||
|     return Ok; | ||||
| } | ||||
|  | ||||
| template <typename ARCH> | ||||
| status target_adapter<ARCH>::threadextrainfo_query(const rp_thread_ref &thread, std::string &out_buf) { | ||||
|     char buf[20]; | ||||
|     memset(buf, 0, 20); | ||||
|     sprintf(buf, "%02x%02x%02x%02x%02x%02x%02x%02x%02x", 'R', 'u', 'n', 'n', 'a', 'b', 'l', 'e', 0); | ||||
|     out_buf = buf; | ||||
|     return Ok; | ||||
| } | ||||
|  | ||||
| template <typename ARCH> status target_adapter<ARCH>::packetsize_query(std::string &out_buf) { | ||||
|     out_buf = "PacketSize=1000"; | ||||
|     return Ok; | ||||
| } | ||||
|  | ||||
| template <typename ARCH> status target_adapter<ARCH>::add_break(int type, uint64_t addr, unsigned int length) { | ||||
|     auto saddr = map_addr({iss::CODE, iss::PHYSICAL, addr}); | ||||
|     auto eaddr = map_addr({iss::CODE, iss::PHYSICAL, addr + length}); | ||||
|     target_adapter_base::bp_lut.addEntry(++target_adapter_base::bp_count, saddr.val, eaddr.val - saddr.val); | ||||
|     LOG(TRACE) << "Adding breakpoint with handle " << target_adapter_base::bp_count << " for addr 0x" << std::hex | ||||
|                << saddr.val << std::dec; | ||||
|     LOG(TRACE) << "Now having " << target_adapter_base::bp_lut.size() << " breakpoints"; | ||||
|     return Ok; | ||||
| } | ||||
|  | ||||
| template <typename ARCH> status target_adapter<ARCH>::remove_break(int type, uint64_t addr, unsigned int length) { | ||||
|     auto saddr = map_addr({iss::CODE, iss::PHYSICAL, addr}); | ||||
|     unsigned handle = target_adapter_base::bp_lut.getEntry(saddr.val); | ||||
|     // TODO: check length of addr range | ||||
|     if (handle) { | ||||
|         LOG(TRACE) << "Removing breakpoint with handle " << handle << " for addr 0x" << std::hex << saddr.val | ||||
|                    << std::dec; | ||||
|         target_adapter_base::bp_lut.removeEntry(handle); | ||||
|         LOG(TRACE) << "Now having " << target_adapter_base::bp_lut.size() << " breakpoints"; | ||||
|         return Ok; | ||||
|     } | ||||
|     LOG(TRACE) << "Now having " << target_adapter_base::bp_lut.size() << " breakpoints"; | ||||
|     return Err; | ||||
| } | ||||
|  | ||||
| template <typename ARCH> status target_adapter<ARCH>::resume_from_addr(bool step, int sig, uint64_t addr) { | ||||
|     unsigned reg_no = arch::traits<ARCH>::PC; | ||||
|     std::vector<uint8_t> data(8); | ||||
|     *(reinterpret_cast<uint64_t *>(&data[0])) = addr; | ||||
|     vm->get_arch()->set_reg(reg_no, data); | ||||
|     return resume_from_current(step, sig); | ||||
| } | ||||
| } // namespace rv32imac | ||||
| } // namespace iss | ||||
|   | ||||
| @@ -34,107 +34,24 @@ | ||||
| // | ||||
| //////////////////////////////////////////////////////////////////////////////// | ||||
|  | ||||
| #include <cstring> | ||||
| #include <iss/arch/riscv_hart_msu_vp.h> | ||||
| #include <iss/arch/rv64ia.h> | ||||
| #include <iss/debugger/gdb_session.h> | ||||
| #include <iss/debugger/server.h> | ||||
| #include <iss/iss.h> | ||||
| #include <memory> | ||||
| #include <iss/vm_base.h> | ||||
| #include <util/logging.h> | ||||
|  | ||||
| #include "iss/arch/rv64ia.h" | ||||
| #include "iss/debugger/server.h" | ||||
| #include "iss/vm_base.h" | ||||
|  | ||||
| #include "iss/arch/riscv_hart_msu_vp.h" | ||||
| #include <boost/format.hpp> | ||||
|  | ||||
| #include <iss/debugger/riscv_target_adapter.h> | ||||
|  | ||||
| namespace iss { | ||||
| namespace rv64ia { | ||||
| using namespace iss::arch; | ||||
| using namespace llvm; | ||||
| using namespace iss::debugger; | ||||
|  | ||||
| template <typename ARCH> struct vm_impl; | ||||
|  | ||||
| template <typename ARCH> struct target_adapter : public target_adapter_base { | ||||
|  | ||||
|     target_adapter(server_if *srv, vm_impl<ARCH> *vm) : target_adapter_base(srv), vm(vm) {} | ||||
|  | ||||
|     /*============== Thread Control ===============================*/ | ||||
|  | ||||
|     /* Set generic thread */ | ||||
|     status set_gen_thread(rp_thread_ref &thread) override; | ||||
|  | ||||
|     /* Set control thread */ | ||||
|     status set_ctrl_thread(rp_thread_ref &thread) override; | ||||
|  | ||||
|     /* Get thread status */ | ||||
|     status is_thread_alive(rp_thread_ref &thread, bool &alive) override; | ||||
|  | ||||
|     /*============= Register Access ================================*/ | ||||
|  | ||||
|     /* Read all registers. buf is 4-byte aligned and it is in | ||||
|      target byte order. If  register is not available | ||||
|      corresponding bytes in avail_buf are 0, otherwise | ||||
|      avail buf is 1 */ | ||||
|     status read_registers(std::vector<uint8_t> &data, std::vector<uint8_t> &avail) override; | ||||
|  | ||||
|     /* Write all registers. buf is 4-byte aligned and it is in target | ||||
|      byte order */ | ||||
|     status write_registers(const std::vector<uint8_t> &data) override; | ||||
|  | ||||
|     /* Read one register. buf is 4-byte aligned and it is in | ||||
|      target byte order. If  register is not available | ||||
|      corresponding bytes in avail_buf are 0, otherwise | ||||
|      avail buf is 1 */ | ||||
|     status read_single_register(unsigned int reg_no, std::vector<uint8_t> &buf, | ||||
|                                 std::vector<uint8_t> &avail_buf) override; | ||||
|  | ||||
|     /* Write one register. buf is 4-byte aligned and it is in target byte | ||||
|      order */ | ||||
|     status write_single_register(unsigned int reg_no, const std::vector<uint8_t> &buf) override; | ||||
|  | ||||
|     /*=================== Memory Access =====================*/ | ||||
|  | ||||
|     /* Read memory, buf is 4-bytes aligned and it is in target | ||||
|      byte order */ | ||||
|     status read_mem(uint64_t addr, std::vector<uint8_t> &buf) override; | ||||
|  | ||||
|     /* Write memory, buf is 4-bytes aligned and it is in target | ||||
|      byte order */ | ||||
|     status write_mem(uint64_t addr, const std::vector<uint8_t> &buf) override; | ||||
|  | ||||
|     status process_query(unsigned int &mask, const rp_thread_ref &arg, rp_thread_info &info) override; | ||||
|  | ||||
|     status thread_list_query(int first, const rp_thread_ref &arg, std::vector<rp_thread_ref> &result, size_t max_num, | ||||
|                              size_t &num, bool &done) override; | ||||
|  | ||||
|     status current_thread_query(rp_thread_ref &thread) override; | ||||
|  | ||||
|     status offsets_query(uint64_t &text, uint64_t &data, uint64_t &bss) override; | ||||
|  | ||||
|     status crc_query(uint64_t addr, size_t len, uint32_t &val) override; | ||||
|  | ||||
|     status raw_query(std::string in_buf, std::string &out_buf) override; | ||||
|  | ||||
|     status threadinfo_query(int first, std::string &out_buf) override; | ||||
|  | ||||
|     status threadextrainfo_query(const rp_thread_ref &thread, std::string &out_buf) override; | ||||
|  | ||||
|     status packetsize_query(std::string &out_buf) override; | ||||
|  | ||||
|     status add_break(int type, uint64_t addr, unsigned int length) override; | ||||
|  | ||||
|     status remove_break(int type, uint64_t addr, unsigned int length) override; | ||||
|  | ||||
|     status resume_from_addr(bool step, int sig, uint64_t addr) override; | ||||
|  | ||||
| protected: | ||||
|     static inline constexpr addr_t map_addr(const addr_t &i) { return i; } | ||||
|  | ||||
|     vm_impl<ARCH> *vm; | ||||
|     rp_thread_ref thread_idx; | ||||
| }; | ||||
|  | ||||
| template <typename ARCH> struct vm_impl : public vm::vm_base<ARCH> { | ||||
|     using super = typename vm::vm_base<ARCH>; | ||||
|     using virt_addr_t = typename super::virt_addr_t; | ||||
| @@ -151,7 +68,7 @@ template <typename ARCH> struct vm_impl : public vm::vm_base<ARCH> { | ||||
|     target_adapter_if *accquire_target_adapter(server_if *srv) { | ||||
|         debugger_if::dbg_enabled = true; | ||||
|         if (vm::vm_base<ARCH>::tgt_adapter == nullptr) | ||||
|             vm::vm_base<ARCH>::tgt_adapter = new target_adapter<ARCH>(srv, this); | ||||
|             vm::vm_base<ARCH>::tgt_adapter = new riscv_target_adapter<ARCH>(srv, this->get_arch()); | ||||
|         return vm::vm_base<ARCH>::tgt_adapter; | ||||
|     } | ||||
|  | ||||
| @@ -3087,7 +3004,9 @@ template <typename CODE_WORD> void debug_fn(CODE_WORD insn) { | ||||
|  | ||||
| template <typename ARCH> vm_impl<ARCH>::vm_impl() { this(new ARCH()); } | ||||
|  | ||||
| template <typename ARCH> vm_impl<ARCH>::vm_impl(ARCH &core, bool dump) : vm::vm_base<ARCH>(core, dump) { | ||||
| template <typename ARCH> | ||||
| vm_impl<ARCH>::vm_impl(ARCH &core, bool dump) | ||||
| : vm::vm_base<ARCH>(core, dump) { | ||||
|     qlut[0] = lut_00.data(); | ||||
|     qlut[1] = lut_01.data(); | ||||
|     qlut[2] = lut_10.data(); | ||||
| @@ -3180,227 +3099,23 @@ template <typename ARCH> inline void vm_impl<ARCH>::gen_trap_check(llvm::BasicBl | ||||
|  | ||||
| } // namespace rv64ia | ||||
|  | ||||
| #define CREATE_FUNCS(ARCH)                                                                                             \ | ||||
|     template <> std::unique_ptr<vm_if> create<ARCH>(ARCH * core, unsigned short port, bool dump) {                     \ | ||||
|         std::unique_ptr<rv64ia::vm_impl<ARCH>> ret = std::make_unique<rv64ia::vm_impl<ARCH>>(*core, dump);             \ | ||||
|         debugger::server<debugger::gdb_session>::run_server(ret.get(), port);                                          \ | ||||
|         return ret;                                                                                                    \ | ||||
|     }                                                                                                                  \ | ||||
|     template <> std::unique_ptr<vm_if> create<ARCH>(std::string inst_name, unsigned short port, bool dump) {           \ | ||||
|         return create<ARCH>(new arch::riscv_hart_msu_vp<ARCH>(), port, dump); /* FIXME: memory leak!!!!!!! */          \ | ||||
|     }                                                                                                                  \ | ||||
|     template <> std::unique_ptr<vm_if> create<ARCH>(ARCH * core, bool dump) {                                          \ | ||||
|         return std::make_unique<rv64ia::vm_impl<ARCH>>(*core, dump); /* FIXME: memory leak!!!!!!! */                   \ | ||||
|     }                                                                                                                  \ | ||||
|     template <> std::unique_ptr<vm_if> create<ARCH>(std::string inst_name, bool dump) {                                \ | ||||
|         return create<ARCH>(new arch::riscv_hart_msu_vp<ARCH>(), dump);                                                \ | ||||
|     } | ||||
|  | ||||
| CREATE_FUNCS(arch::rv64ia) | ||||
|  | ||||
| namespace rv64ia { | ||||
|  | ||||
| template <typename ARCH> status target_adapter<ARCH>::set_gen_thread(rp_thread_ref &thread) { | ||||
|     thread_idx = thread; | ||||
|     return Ok; | ||||
| template <> std::unique_ptr<vm_if> create<arch::rv64ia>(arch::rv64ia *core, unsigned short port, bool dump) { | ||||
|     std::unique_ptr<rv64ia::vm_impl<arch::rv64ia>> ret = std::make_unique<rv64ia::vm_impl<arch::rv64ia>>(*core, dump); | ||||
|     debugger::server<debugger::gdb_session>::run_server(ret.get(), port); | ||||
|     return ret; | ||||
| } | ||||
|  | ||||
| template <typename ARCH> status target_adapter<ARCH>::set_ctrl_thread(rp_thread_ref &thread) { | ||||
|     thread_idx = thread; | ||||
|     return Ok; | ||||
| template <> std::unique_ptr<vm_if> create<arch::rv64ia>(std::string inst_name, unsigned short port, bool dump) { | ||||
|     return create<arch::rv64ia>(new arch::riscv_hart_msu_vp<arch::rv64ia>(), port, | ||||
|                                 dump); /* FIXME: memory leak!!!!!!! */ | ||||
| } | ||||
|  | ||||
| template <typename ARCH> status target_adapter<ARCH>::is_thread_alive(rp_thread_ref &thread, bool &alive) { | ||||
|     alive = 1; | ||||
|     return Ok; | ||||
| template <> std::unique_ptr<vm_if> create<arch::rv64ia>(arch::rv64ia *core, bool dump) { | ||||
|     return std::make_unique<rv64ia::vm_impl<arch::rv64ia>>(*core, dump); /* FIXME: memory leak!!!!!!! */ | ||||
| } | ||||
|  | ||||
| /* List threads. If first is non-zero then start from the first thread, | ||||
|  * otherwise start from arg, result points to array of threads to be | ||||
|  * filled out, result size is number of elements in the result, | ||||
|  * num points to the actual number of threads found, done is | ||||
|  * set if all threads are processed. | ||||
|  */ | ||||
| template <typename ARCH> | ||||
| status target_adapter<ARCH>::thread_list_query(int first, const rp_thread_ref &arg, std::vector<rp_thread_ref> &result, | ||||
|                                                size_t max_num, size_t &num, bool &done) { | ||||
|     if (first == 0) { | ||||
|         result.clear(); | ||||
|         result.push_back(thread_idx); | ||||
|         num = 1; | ||||
|         done = true; | ||||
|         return Ok; | ||||
|     } else | ||||
|         return NotSupported; | ||||
| template <> std::unique_ptr<vm_if> create<arch::rv64ia>(std::string inst_name, bool dump) { | ||||
|     return create<arch::rv64ia>(new arch::riscv_hart_msu_vp<arch::rv64ia>(), dump); | ||||
| } | ||||
|  | ||||
| template <typename ARCH> status target_adapter<ARCH>::current_thread_query(rp_thread_ref &thread) { | ||||
|     thread = thread_idx; | ||||
|     return Ok; | ||||
| } | ||||
|  | ||||
| template <typename ARCH> | ||||
| status target_adapter<ARCH>::read_registers(std::vector<uint8_t> &data, std::vector<uint8_t> &avail) { | ||||
|     LOG(TRACE) << "reading target registers"; | ||||
|     // return idx<0?:; | ||||
|     data.clear(); | ||||
|     avail.clear(); | ||||
|     std::vector<uint8_t> reg_data; | ||||
|     for (size_t reg_no = 0; reg_no < arch::traits<ARCH>::NUM_REGS; ++reg_no) { | ||||
|         auto reg_bit_width = arch::traits<ARCH>::reg_bit_width(static_cast<typename arch::traits<ARCH>::reg_e>(reg_no)); | ||||
|         auto reg_width = reg_bit_width / 8; | ||||
|         reg_data.resize(reg_width); | ||||
|         vm->get_arch()->get_reg(reg_no, reg_data); | ||||
|         for (size_t j = 0; j < reg_data.size(); ++j) { | ||||
|             data.push_back(reg_data[j]); | ||||
|             avail.push_back(0xff); | ||||
|         } | ||||
|     } | ||||
|     // work around fill with F type registers | ||||
|     if (arch::traits<ARCH>::NUM_REGS < 65) { | ||||
|         auto reg_width = sizeof(typename arch::traits<ARCH>::reg_t); | ||||
|         for (size_t reg_no = 0; reg_no < 33; ++reg_no) { | ||||
|             for (size_t j = 0; j < reg_width; ++j) { | ||||
|                 data.push_back(0x0); | ||||
|                 avail.push_back(0x00); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|     return Ok; | ||||
| } | ||||
|  | ||||
| template <typename ARCH> status target_adapter<ARCH>::write_registers(const std::vector<uint8_t> &data) { | ||||
|     size_t data_index = 0; | ||||
|     auto reg_count = arch::traits<ARCH>::NUM_REGS; | ||||
|     std::vector<uint8_t> reg_data; | ||||
|     for (size_t reg_no = 0; reg_no < reg_count; ++reg_no) { | ||||
|         auto reg_bit_width = arch::traits<ARCH>::reg_bit_width(static_cast<typename arch::traits<ARCH>::reg_e>(reg_no)); | ||||
|         auto reg_width = reg_bit_width / 8; | ||||
|         vm->get_arch()->set_reg(reg_no, | ||||
|                                 std::vector<uint8_t>(data.begin() + data_index, data.begin() + data_index + reg_width)); | ||||
|         data_index += reg_width; | ||||
|     } | ||||
|     return Ok; | ||||
| } | ||||
|  | ||||
| template <typename ARCH> | ||||
| status target_adapter<ARCH>::read_single_register(unsigned int reg_no, std::vector<uint8_t> &data, | ||||
|                                                   std::vector<uint8_t> &avail) { | ||||
|     if (reg_no < 65) { | ||||
|         // auto reg_size = arch::traits<ARCH>::reg_bit_width(static_cast<typename | ||||
|         // arch::traits<ARCH>::reg_e>(reg_no))/8; | ||||
|         data.resize(0); | ||||
|         vm->get_arch()->get_reg(reg_no, data); | ||||
|         avail.resize(data.size()); | ||||
|         std::fill(avail.begin(), avail.end(), 0xff); | ||||
|     } else { | ||||
|         typed_addr_t<iss::PHYSICAL> a(iss::DEBUG_READ, traits<ARCH>::CSR, reg_no - 65); | ||||
|         data.resize(sizeof(typename traits<ARCH>::reg_t)); | ||||
|         avail.resize(sizeof(typename traits<ARCH>::reg_t)); | ||||
|         std::fill(avail.begin(), avail.end(), 0xff); | ||||
|         vm->get_arch()->read(a, data.size(), data.data()); | ||||
|     } | ||||
|     return data.size() > 0 ? Ok : Err; | ||||
| } | ||||
|  | ||||
| template <typename ARCH> | ||||
| status target_adapter<ARCH>::write_single_register(unsigned int reg_no, const std::vector<uint8_t> &data) { | ||||
|     if (reg_no < 65) | ||||
|         vm->get_arch()->set_reg(reg_no, data); | ||||
|     else { | ||||
|         typed_addr_t<iss::PHYSICAL> a(iss::DEBUG_WRITE, traits<ARCH>::CSR, reg_no - 65); | ||||
|         vm->get_arch()->write(a, data.size(), data.data()); | ||||
|     } | ||||
|     return Ok; | ||||
| } | ||||
|  | ||||
| template <typename ARCH> status target_adapter<ARCH>::read_mem(uint64_t addr, std::vector<uint8_t> &data) { | ||||
|     auto a = map_addr({iss::DEBUG_READ, iss::VIRTUAL, 0, addr}); | ||||
|     auto f = [&]() -> status { return vm->get_arch()->read(a, data.size(), data.data()); }; | ||||
|     return srv->execute_syncronized(f); | ||||
| } | ||||
|  | ||||
| template <typename ARCH> status target_adapter<ARCH>::write_mem(uint64_t addr, const std::vector<uint8_t> &data) { | ||||
|     auto a = map_addr({iss::DEBUG_READ, iss::VIRTUAL, 0, addr}); | ||||
|     return srv->execute_syncronized(&arch_if::write, vm->get_arch(), a, data.size(), data.data()); | ||||
| } | ||||
|  | ||||
| template <typename ARCH> | ||||
| status target_adapter<ARCH>::process_query(unsigned int &mask, const rp_thread_ref &arg, rp_thread_info &info) { | ||||
|     return NotSupported; | ||||
| } | ||||
|  | ||||
| template <typename ARCH> status target_adapter<ARCH>::offsets_query(uint64_t &text, uint64_t &data, uint64_t &bss) { | ||||
|     text = 0; | ||||
|     data = 0; | ||||
|     bss = 0; | ||||
|     return Ok; | ||||
| } | ||||
|  | ||||
| template <typename ARCH> status target_adapter<ARCH>::crc_query(uint64_t addr, size_t len, uint32_t &val) { | ||||
|     return NotSupported; | ||||
| } | ||||
|  | ||||
| template <typename ARCH> status target_adapter<ARCH>::raw_query(std::string in_buf, std::string &out_buf) { | ||||
|     return NotSupported; | ||||
| } | ||||
|  | ||||
| template <typename ARCH> status target_adapter<ARCH>::threadinfo_query(int first, std::string &out_buf) { | ||||
|     if (first) { | ||||
|         std::stringstream ss; | ||||
|         ss << "m" << std::hex << thread_idx.val; | ||||
|         out_buf = ss.str(); | ||||
|     } else { | ||||
|         out_buf = "l"; | ||||
|     } | ||||
|     return Ok; | ||||
| } | ||||
|  | ||||
| template <typename ARCH> | ||||
| status target_adapter<ARCH>::threadextrainfo_query(const rp_thread_ref &thread, std::string &out_buf) { | ||||
|     char buf[20]; | ||||
|     memset(buf, 0, 20); | ||||
|     sprintf(buf, "%02x%02x%02x%02x%02x%02x%02x%02x%02x", 'R', 'u', 'n', 'n', 'a', 'b', 'l', 'e', 0); | ||||
|     out_buf = buf; | ||||
|     return Ok; | ||||
| } | ||||
|  | ||||
| template <typename ARCH> status target_adapter<ARCH>::packetsize_query(std::string &out_buf) { | ||||
|     out_buf = "PacketSize=1000"; | ||||
|     return Ok; | ||||
| } | ||||
|  | ||||
| template <typename ARCH> status target_adapter<ARCH>::add_break(int type, uint64_t addr, unsigned int length) { | ||||
|     auto saddr = map_addr({iss::CODE, iss::PHYSICAL, addr}); | ||||
|     auto eaddr = map_addr({iss::CODE, iss::PHYSICAL, addr + length}); | ||||
|     target_adapter_base::bp_lut.addEntry(++target_adapter_base::bp_count, saddr.val, eaddr.val - saddr.val); | ||||
|     LOG(TRACE) << "Adding breakpoint with handle " << target_adapter_base::bp_count << " for addr 0x" << std::hex | ||||
|                << saddr.val << std::dec; | ||||
|     LOG(TRACE) << "Now having " << target_adapter_base::bp_lut.size() << " breakpoints"; | ||||
|     return Ok; | ||||
| } | ||||
|  | ||||
| template <typename ARCH> status target_adapter<ARCH>::remove_break(int type, uint64_t addr, unsigned int length) { | ||||
|     auto saddr = map_addr({iss::CODE, iss::PHYSICAL, addr}); | ||||
|     unsigned handle = target_adapter_base::bp_lut.getEntry(saddr.val); | ||||
|     // TODO: check length of addr range | ||||
|     if (handle) { | ||||
|         LOG(TRACE) << "Removing breakpoint with handle " << handle << " for addr 0x" << std::hex << saddr.val | ||||
|                    << std::dec; | ||||
|         target_adapter_base::bp_lut.removeEntry(handle); | ||||
|         LOG(TRACE) << "Now having " << target_adapter_base::bp_lut.size() << " breakpoints"; | ||||
|         return Ok; | ||||
|     } | ||||
|     LOG(TRACE) << "Now having " << target_adapter_base::bp_lut.size() << " breakpoints"; | ||||
|     return Err; | ||||
| } | ||||
|  | ||||
| template <typename ARCH> status target_adapter<ARCH>::resume_from_addr(bool step, int sig, uint64_t addr) { | ||||
|     unsigned reg_no = arch::traits<ARCH>::PC; | ||||
|     std::vector<uint8_t> data(8); | ||||
|     *(reinterpret_cast<uint64_t *>(&data[0])) = addr; | ||||
|     vm->get_arch()->set_reg(reg_no, data); | ||||
|     return resume_from_current(step, sig); | ||||
| } | ||||
| } // namespace rv64ia | ||||
| } // namespace iss | ||||
|   | ||||
 Submodule sc-components updated: cab7505af9...3693b05536
									
								
							
		Reference in New Issue
	
	Block a user