From a92b84bef4abaa37a50f9ebdbc100384e57d50cb Mon Sep 17 00:00:00 2001 From: Eyck Jentzsch Date: Mon, 25 Apr 2022 14:18:19 +0200 Subject: [PATCH] add code word access for ISS plugins --- gen_input/TGC_C.core_desc | 6 +++--- gen_input/templates/CORENAME.cpp.gtl | 2 +- gen_input/templates/CORENAME.h.gtl | 6 ++++-- gen_input/templates/interp/CORENAME.cpp.gtl | 7 ++++--- incl/iss/arch/riscv_hart_m_p.h | 8 +++---- incl/iss/arch/tgc_c.h | 14 +++++++------ src/iss/tgc_c.cpp | 4 ++-- src/plugin/pctrace.cpp | 5 ++++- src/vm/interp/vm_tgc_c.cpp | 23 +++++++++++---------- 9 files changed, 42 insertions(+), 33 deletions(-) diff --git a/gen_input/TGC_C.core_desc b/gen_input/TGC_C.core_desc index d3a529e..72f549d 100644 --- a/gen_input/TGC_C.core_desc +++ b/gen_input/TGC_C.core_desc @@ -1,6 +1,6 @@ -import "CoreDSL-Instruction-Set-Description/RV32I.core_desc" -import "CoreDSL-Instruction-Set-Description/RVM.core_desc" -import "CoreDSL-Instruction-Set-Description/RVC.core_desc" +import "RV32I.core_desc" +import "RVM.core_desc" +import "RVC.core_desc" Core TGC_C provides RV32I, Zicsr, Zifencei, RV32M, RV32IC { architectural_state { diff --git a/gen_input/templates/CORENAME.cpp.gtl b/gen_input/templates/CORENAME.cpp.gtl index 6bb5c4e..ead228a 100644 --- a/gen_input/templates/CORENAME.cpp.gtl +++ b/gen_input/templates/CORENAME.cpp.gtl @@ -33,7 +33,7 @@ def getRegisterSizes(){ def regs = registers.collect{it.size} regs[-1]=64 // correct for NEXT_PC - regs+=[32, 32, 64, 64, 64] // append TRAP_STATE, PENDING_TRAP, ICOUNT, CYCLE, INSTRET + regs+=[32, 32, 64, 64, 64, 32] // append TRAP_STATE, PENDING_TRAP, ICOUNT, CYCLE, INSTRET, INSTRUCTION return regs } %> diff --git a/gen_input/templates/CORENAME.h.gtl b/gen_input/templates/CORENAME.h.gtl index dbe4c82..c114cec 100644 --- a/gen_input/templates/CORENAME.h.gtl +++ b/gen_input/templates/CORENAME.h.gtl @@ -37,7 +37,7 @@ def nativeTypeSize(int size){ } def getRegisterSizes(){ def regs = registers.collect{nativeTypeSize(it.size)} - regs+=[32,32, 64, 64, 64] // append TRAP_STATE, PENDING_TRAP, ICOUNT, CYCLE, INSTRET + regs+=[32,32, 64, 64, 64, 32] // append TRAP_STATE, PENDING_TRAP, ICOUNT, CYCLE, INSTRET, INSTRUCTION return regs } def getRegisterOffsets(){ @@ -96,7 +96,8 @@ template <> struct traits<${coreDef.name.toLowerCase()}> { PENDING_TRAP, ICOUNT, CYCLE, - INSTRET + INSTRET, + INSTRUCTION }; using reg_t = uint${addrDataWidth}_t; @@ -170,6 +171,7 @@ struct ${coreDef.name.toLowerCase()}: public arch_if { uint32_t trap_state = 0, pending_trap = 0; uint64_t icount = 0; uint64_t instret = 0; + uint32_t instruction = 0; uint32_t last_branch; } reg; #pragma pack(pop) diff --git a/gen_input/templates/interp/CORENAME.cpp.gtl b/gen_input/templates/interp/CORENAME.cpp.gtl index 98817ce..9883e16 100644 --- a/gen_input/templates/interp/CORENAME.cpp.gtl +++ b/gen_input/templates/interp/CORENAME.cpp.gtl @@ -277,9 +277,6 @@ typename arch::traits::opcode_e vm_impl::decode_inst_id(code_word_t template typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e cond, virt_addr_t start, uint64_t icount_limit){ - // we fetch at max 4 byte, alignment is 2 - code_word_t instr = 0; - auto *const data = (uint8_t *)&instr; auto pc=start; auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); @@ -287,6 +284,10 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); auto* icount = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::ICOUNT]); auto* instret = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRET]); + auto *const instruction = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRUCTION]); + // we fetch at max 4 byte, alignment is 2 + auto *const data = reinterpret_cast(instruction); + auto& instr = *instruction; while(!this->core.should_stop() && !(is_count_limit_enabled(cond) && this->core.get_icount() >= icount_limit)){ diff --git a/incl/iss/arch/riscv_hart_m_p.h b/incl/iss/arch/riscv_hart_m_p.h index bff635d..7a798bf 100644 --- a/incl/iss/arch/riscv_hart_m_p.h +++ b/incl/iss/arch/riscv_hart_m_p.h @@ -235,9 +235,11 @@ protected: */ const std::string core_type_name() const override { return traits::core_type; } - uint64_t get_pc() override { return arch.get_pc(); }; + uint64_t get_pc() override { return arch.reg.PC; }; - uint64_t get_next_pc() override { return arch.get_next_pc(); }; + uint64_t get_next_pc() override { return arch.reg.NEXT_PC; }; + + uint64_t get_instr_word() override { return arch.reg.instruction; } uint64_t get_instr_count() { return arch.reg.icount; } @@ -249,8 +251,6 @@ protected: }; friend struct riscv_instrumentation_if; - addr_t get_pc() { return this->reg.PC; } - addr_t get_next_pc() { return this->reg.NEXT_PC; } virtual iss::status read_mem(phys_addr_t addr, unsigned length, uint8_t *const data); virtual iss::status write_mem(phys_addr_t addr, unsigned length, const uint8_t *const data); diff --git a/incl/iss/arch/tgc_c.h b/incl/iss/arch/tgc_c.h index 619034d..9640ae9 100644 --- a/incl/iss/arch/tgc_c.h +++ b/incl/iss/arch/tgc_c.h @@ -53,7 +53,7 @@ template <> struct traits { static constexpr std::array reg_aliases{ {"ZERO", "RA", "SP", "GP", "TP", "T0", "T1", "T2", "S0", "S1", "A0", "A1", "A2", "A3", "A4", "A5", "A6", "A7", "S2", "S3", "S4", "S5", "S6", "S7", "S8", "S9", "S10", "S11", "T3", "T4", "T5", "T6", "PC", "NEXT_PC", "PRIV", "DPC"}}; - enum constants {MISA_VAL=0b01000000000000000001000100000100, MARCHID_VAL=0x80000003, RFS=32, INSTR_ALIGNMENT=2, XLEN=32, CSR_SIZE=4096, fence=0, fencei=1, fencevmal=2, fencevmau=3, MUL_LEN=64}; + enum constants {MISA_VAL=0b01000000000000000001000100000100, MARCHID_VAL=0x80000003, RFS=32, XLEN=32, CSR_SIZE=4096, INSTR_ALIGNMENT=2, fence=0, fencei=1, fencevmal=2, fencevmau=3, MUL_LEN=64}; constexpr static unsigned FP_REGS_SIZE = 0; @@ -63,7 +63,8 @@ template <> struct traits { PENDING_TRAP, ICOUNT, CYCLE, - INSTRET + INSTRET, + INSTRUCTION }; using reg_t = uint32_t; @@ -76,11 +77,11 @@ template <> struct traits { using phys_addr_t = iss::typed_addr_t; - static constexpr std::array reg_bit_widths{ - {32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,8,32,32,32,64,64,64}}; + static constexpr std::array reg_bit_widths{ + {32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,8,32,32,32,64,64,64,32}}; - static constexpr std::array reg_byte_offsets{ - {0,4,8,12,16,20,24,28,32,36,40,44,48,52,56,60,64,68,72,76,80,84,88,92,96,100,104,108,112,116,120,124,128,132,136,137,141,145,149,157,165}}; + static constexpr std::array reg_byte_offsets{ + {0,4,8,12,16,20,24,28,32,36,40,44,48,52,56,60,64,68,72,76,80,84,88,92,96,100,104,108,112,116,120,124,128,132,136,137,141,145,149,157,165,173}}; static const uint64_t addr_mask = (reg_t(1) << (XLEN - 1)) | ((reg_t(1) << (XLEN - 1)) - 1); @@ -259,6 +260,7 @@ struct tgc_c: public arch_if { uint32_t trap_state = 0, pending_trap = 0; uint64_t icount = 0; uint64_t instret = 0; + uint32_t instruction = 0; uint32_t last_branch; } reg; #pragma pack(pop) diff --git a/src/iss/tgc_c.cpp b/src/iss/tgc_c.cpp index b5e8fed..3c6fcd0 100644 --- a/src/iss/tgc_c.cpp +++ b/src/iss/tgc_c.cpp @@ -41,8 +41,8 @@ using namespace iss::arch; constexpr std::array iss::arch::traits::reg_names; constexpr std::array iss::arch::traits::reg_aliases; -constexpr std::array iss::arch::traits::reg_bit_widths; -constexpr std::array iss::arch::traits::reg_byte_offsets; +constexpr std::array iss::arch::traits::reg_bit_widths; +constexpr std::array iss::arch::traits::reg_byte_offsets; tgc_c::tgc_c() { reg.icount = 0; diff --git a/src/plugin/pctrace.cpp b/src/plugin/pctrace.cpp index e178072..4c6ea1a 100644 --- a/src/plugin/pctrace.cpp +++ b/src/plugin/pctrace.cpp @@ -1,6 +1,7 @@ #include #include #include +#include #include #include #include "rapidjson/writer.h" @@ -123,7 +124,9 @@ void iss::plugin::cov::callback(instr_info_t iinfo, const exec_info& einfo) { //source code for the full output auto delay = 0; - auto entry = delays[iinfo.instr_id]; + size_t id = iinfo.instr_id; + auto entry = delays[id]; + auto call = (id==2 || id==3) && bit_sub<7,5>(instr_if->get_instr_word())!=0; bool taken = einfo.branch_taken; if (einfo.branch_taken) delay = entry.taken; diff --git a/src/vm/interp/vm_tgc_c.cpp b/src/vm/interp/vm_tgc_c.cpp index ea76eaf..435389d 100644 --- a/src/vm/interp/vm_tgc_c.cpp +++ b/src/vm/interp/vm_tgc_c.cpp @@ -358,9 +358,6 @@ typename arch::traits::opcode_e vm_impl::decode_inst_id(code_word_t template typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e cond, virt_addr_t start, uint64_t icount_limit){ - // we fetch at max 4 byte, alignment is 2 - code_word_t instr = 0; - auto *const data = (uint8_t *)&instr; auto pc=start; auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); @@ -368,6 +365,10 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); auto* icount = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::ICOUNT]); auto* instret = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRET]); + auto *const instruction = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRUCTION]); + // we fetch at max 4 byte, alignment is 2 + auto *const data = reinterpret_cast(instruction); + auto& instr = *instruction; while(!this->core.should_stop() && !(is_count_limit_enabled(cond) && this->core.get_icount() >= icount_limit)){ @@ -2001,7 +2002,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co // execute instruction try { { - uint8_t rs1_idx = rs1 + 8; + uint32_t rs1_idx = rs1 + 8; *(X+rs1_idx) = *(X+rs1_idx) >> shamt; } } catch(...){} @@ -2024,11 +2025,11 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co // execute instruction try { if(shamt) { - uint8_t rs1_idx = rs1 + 8; + uint32_t rs1_idx = rs1 + 8; *(X+rs1_idx) = ((int32_t)*(X+rs1_idx)) >> shamt; } else if(traits::XLEN == 128) { - uint8_t rs1_idx = rs1 + 8; + uint32_t rs1_idx = rs1 + 8; *(X+rs1_idx) = ((int32_t)*(X+rs1_idx)) >> 64; } } catch(...){} @@ -2051,7 +2052,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co // execute instruction try { { - uint8_t rs1_idx = rs1 + 8; + uint32_t rs1_idx = rs1 + 8; *(X+rs1_idx) = *(X+rs1_idx) & (int8_t)sext<6>(imm); } } catch(...){} @@ -2074,7 +2075,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co // execute instruction try { { - uint8_t rd_idx = rd + 8; + uint32_t rd_idx = rd + 8; *(X+rd_idx) = *(X+rd_idx) - *(X+rs2 + 8); } } catch(...){} @@ -2097,7 +2098,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co // execute instruction try { { - uint8_t rd_idx = rd + 8; + uint32_t rd_idx = rd + 8; *(X+rd_idx) = *(X+rd_idx) ^ *(X+rs2 + 8); } } catch(...){} @@ -2120,7 +2121,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co // execute instruction try { { - uint8_t rd_idx = rd + 8; + uint32_t rd_idx = rd + 8; *(X+rd_idx) = *(X+rd_idx) | *(X+rs2 + 8); } } catch(...){} @@ -2143,7 +2144,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co // execute instruction try { { - uint8_t rd_idx = rd + 8; + uint32_t rd_idx = rd + 8; *(X+rd_idx) = *(X+rd_idx) & *(X+rs2 + 8); } } catch(...){}