diff --git a/.gitignore b/.gitignore index 37563ca..cebb65a 100644 --- a/.gitignore +++ b/.gitignore @@ -31,3 +31,4 @@ language.settings.xml /*.out /dump.json /src-gen/ +/*.yaml diff --git a/CMakeLists.txt b/CMakeLists.txt index f5d7912..7577443 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -40,24 +40,38 @@ set(LIB_SOURCES ) if(WITH_LLVM) - set(LIB_SOURCES ${LIB_SOURCES} - src/vm/llvm/fp_impl.cpp - #src/vm/llvm/vm_tgf_b.cpp - #src/vm/llvm/vm_tgf_c.cpp - ) + FILE(GLOB TGC_LLVM_SOURCES + ${CMAKE_CURRENT_SOURCE_DIR}/src/vm/llvm/vm_*.cpp + ) + list(APPEND LIB_SOURCES ${TGC_LLVM_SOURCES}) +endif() + +if(WITH_TCC) + FILE(GLOB TGC_TCC_SOURCES + ${CMAKE_CURRENT_SOURCE_DIR}/src/vm/tcc/vm_*.cpp + ) + list(APPEND LIB_SOURCES ${TGC_TCC_SOURCES}) endif() # Define the library -add_library(${PROJECT_NAME} SHARED ${LIB_SOURCES}) +add_library(${PROJECT_NAME} ${LIB_SOURCES}) # list code gen dependencies if(TARGET ${CORE_NAME}_cpp) add_dependencies(${PROJECT_NAME} ${CORE_NAME}_cpp) endif() -target_compile_options(${PROJECT_NAME} PRIVATE -Wno-shift-count-overflow) +if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") + target_compile_options(${PROJECT_NAME} PRIVATE -Wno-shift-count-overflow) +elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") + target_compile_options(${PROJECT_NAME} PRIVATE /wd4293) +endif() target_include_directories(${PROJECT_NAME} PUBLIC incl) target_link_libraries(${PROJECT_NAME} PUBLIC softfloat scc-util jsoncpp) -target_link_libraries(${PROJECT_NAME} PUBLIC -Wl,--whole-archive dbt-core -Wl,--no-whole-archive) +if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") + target_link_libraries(${PROJECT_NAME} PUBLIC -Wl,--whole-archive dbt-core -Wl,--no-whole-archive) +else() + target_link_libraries(${PROJECT_NAME} PUBLIC dbt-core) +endif() if(TARGET CONAN_PKG::elfio) target_link_libraries(${PROJECT_NAME} PUBLIC CONAN_PKG::elfio) elseif(TARGET elfio::elfio) @@ -98,16 +112,15 @@ if(WITH_LLVM) target_link_libraries(${PROJECT_NAME} PUBLIC ${llvm_libs}) endif() # Links the target exe against the libraries -target_link_libraries(${PROJECT_NAME} dbt-rise-tgc) -#target_link_libraries(${PROJECT_NAME} jsoncpp) +target_link_libraries(${PROJECT_NAME} PUBLIC dbt-rise-tgc) if(TARGET Boost::program_options) - target_link_libraries(${PROJECT_NAME} Boost::program_options Boost::thread) + target_link_libraries(${PROJECT_NAME} PUBLIC Boost::program_options) else() - target_link_libraries(${PROJECT_NAME} ${BOOST_program_options_LIBRARY} ${BOOST_thread_LIBRARY}) + target_link_libraries(${PROJECT_NAME} PUBLIC ${BOOST_program_options_LIBRARY}) endif() -target_link_libraries(${PROJECT_NAME} ${CMAKE_DL_LIBS}) +target_link_libraries(${PROJECT_NAME} PUBLIC ${CMAKE_DL_LIBS}) if (Tcmalloc_FOUND) - target_link_libraries(${PROJECT_NAME} ${Tcmalloc_LIBRARIES}) + target_link_libraries(${PROJECT_NAME} PUBLIC ${Tcmalloc_LIBRARIES}) endif(Tcmalloc_FOUND) install(TARGETS tgc-sim diff --git a/gen_input/CoreDSL-Instruction-Set-Description b/gen_input/CoreDSL-Instruction-Set-Description index 8d9a0fb..b005607 160000 --- a/gen_input/CoreDSL-Instruction-Set-Description +++ b/gen_input/CoreDSL-Instruction-Set-Description @@ -1 +1 @@ -Subproject commit 8d9a0fb1493b762014c330c71ac8cef96753d302 +Subproject commit b005607fc30c4467683b6044eaca7eb378061b53 diff --git a/gen_input/TGC_B.core_desc b/gen_input/TGC_B.core_desc new file mode 100644 index 0000000..3686002 --- /dev/null +++ b/gen_input/TGC_B.core_desc @@ -0,0 +1,14 @@ +import "CoreDSL-Instruction-Set-Description/RV32I.core_desc" +import "CoreDSL-Instruction-Set-Description/RVM.core_desc" +import "CoreDSL-Instruction-Set-Description/RVC.core_desc" + +Core TGC_B provides RV32I, Zicsr, Zifencei { + architectural_state { + XLEN=32; + // definitions for the architecture wrapper + // XL ZYXWVUTSRQPONMLKJIHGFEDCBA + unsigned MISA_VAL = 0b01000000000000000000000100000000; + unsigned MARCHID_VAL = 0x80000002; + } +} + diff --git a/gen_input/TGC_C.core_desc b/gen_input/TGC_C.core_desc new file mode 100644 index 0000000..d3a529e --- /dev/null +++ b/gen_input/TGC_C.core_desc @@ -0,0 +1,13 @@ +import "CoreDSL-Instruction-Set-Description/RV32I.core_desc" +import "CoreDSL-Instruction-Set-Description/RVM.core_desc" +import "CoreDSL-Instruction-Set-Description/RVC.core_desc" + +Core TGC_C provides RV32I, Zicsr, Zifencei, RV32M, RV32IC { + architectural_state { + XLEN=32; + // definitions for the architecture wrapper + // XL ZYXWVUTSRQPONMLKJIHGFEDCBA + unsigned MISA_VAL = 0b01000000000000000001000100000100; + unsigned MARCHID_VAL = 0x80000003; + } +} diff --git a/gen_input/TGC_D.core_desc b/gen_input/TGC_D.core_desc new file mode 100644 index 0000000..c4d9c54 --- /dev/null +++ b/gen_input/TGC_D.core_desc @@ -0,0 +1,13 @@ +import "CoreDSL-Instruction-Set-Description/RV32I.core_desc" +import "CoreDSL-Instruction-Set-Description/RVM.core_desc" +import "CoreDSL-Instruction-Set-Description/RVC.core_desc" + +Core TGC_D provides RV32I, Zicsr, Zifencei, RV32M, RV32IC { + architectural_state { + XLEN=32; + // definitions for the architecture wrapper + // XL ZYXWVUTSRQPONMLKJIHGFEDCBA + unsigned MISA_VAL = 0b01000000000100000011000100000100; + unsigned MARCHID_VAL = 0x80000004; + } +} diff --git a/gen_input/TGC_D_XRB_MAC.core_desc b/gen_input/TGC_D_XRB_MAC.core_desc new file mode 100644 index 0000000..972b111 --- /dev/null +++ b/gen_input/TGC_D_XRB_MAC.core_desc @@ -0,0 +1,73 @@ +import "CoreDSL-Instruction-Set-Description/RISCVBase.core_desc" +import "CoreDSL-Instruction-Set-Description/RV32I.core_desc" +import "CoreDSL-Instruction-Set-Description/RVM.core_desc" +import "CoreDSL-Instruction-Set-Description/RVC.core_desc" + +InstructionSet X_RB_MAC extends RISCVBase { + architectural_state { + register unsigned<64> ACC; + } + + instructions { + RESET_ACC { // v-- funct7 v-- funct3 + encoding: 7'd0 :: 10'b0 :: 3'd0 :: 5'b0 :: 7'b0001011; + behavior: ACC = 0; + } + + GET_ACC_LO { + encoding: 7'd1 :: 10'b0 :: 3'd0 :: rd[4:0] :: 7'b0001011; + behavior: if (rd != 0) X[rd] = ACC[31:0]; + } + + GET_ACC_HI { + encoding: 7'd2 :: 10'b0 :: 3'd0 :: rd[4:0] :: 7'b0001011; + behavior: if (rd != 0) X[rd] = ACC[63:32]; + } + + MACU_32 { + encoding: 7'd0 :: rs2[4:0] :: rs1[4:0] :: 3'd1 :: 5'b0 :: 7'b0001011; + behavior: { + unsigned<64> mul = X[rs1] * X[rs2]; + unsigned<33> add = mul[31:0] + ACC[31:0]; + ACC = add[31:0]; + } + } + + MACS_32 { + encoding: 7'd1 :: rs2[4:0] :: rs1[4:0] :: 3'd1 :: 5'b0 :: 7'b0001011; + behavior: { + signed<64> mul = ((signed) X[rs1]) * ((signed) X[rs2]); + signed<33> add = ((signed) mul[31:0]) + ((signed) ACC[31:0]); + ACC = add[31:0]; // bit range always yields unsigned type + } + } + + MACU_64 { + encoding: 7'd0 :: rs2[4:0] :: rs1[4:0] :: 3'd2 :: 5'b0 :: 7'b0001011; + behavior: { + unsigned<64> mul = X[rs1] * X[rs2]; + unsigned<65> add = mul + ACC; + ACC = add[63:0]; + } + } + + MACS_64 { + encoding: 7'd1 :: rs2[4:0] :: rs1[4:0] :: 3'd2 :: 5'b0 :: 7'b0001011; + behavior: { + signed<64> mul = ((signed) X[rs1]) * ((signed) X[rs2]); + signed<65> add = mul + ((signed) ACC); + ACC = add[63:0]; + } + } + } +} + +Core TGC_D_XRB_MAC provides RV32I, Zicsr, Zifencei, RV32M, RV32IC, X_RB_MAC { + architectural_state { + XLEN=32; + // definitions for the architecture wrapper + // XL ZYXWVUTSRQPONMLKJIHGFEDCBA + unsigned MISA_VAL = 0b01000000000000000001000100000100; + unsigned MARCHID_VAL = 0x80000004; + } +} diff --git a/gen_input/TGC_D_XRB_NN.core_desc b/gen_input/TGC_D_XRB_NN.core_desc new file mode 100644 index 0000000..bec4c2f --- /dev/null +++ b/gen_input/TGC_D_XRB_NN.core_desc @@ -0,0 +1,133 @@ +import "CoreDSL-Instruction-Set-Description/RISCVBase.core_desc" +import "CoreDSL-Instruction-Set-Description/RV32I.core_desc" +import "CoreDSL-Instruction-Set-Description/RVM.core_desc" +import "CoreDSL-Instruction-Set-Description/RVC.core_desc" + +InstructionSet X_RB_NN extends RISCVBase { + + instructions { + + // signed saturate with pre-shift + SSAT { + // instruction format: R-type + // opcode space: custom-1 (inst[6:2] = 01010) + // opcode = 0b0101011, func3 = 0b000, func7 = + encoding: sat_bit_pos[6:0] :: rs2[4:0] :: rs1[4:0] :: 0b000 :: rd[4:0] :: 0b0101011; + args_disass:"{name(rd)}, {name(rs1)}, {name(rs2)}, {name(sat_bit_pos)}"; + behavior: { + signed val_s = (signed)X[rs1]; + unsigned pre_shift = (unsigned)X[rs2]; + unsigned sat_limit; + signed upper_limit; + signed lower_limit; + + if((rd != 0) && (sat_bit_pos > 0) && (sat_bit_pos <= 32) && (pre_shift < 32)) { + sat_limit = (unsigned)(1 << (sat_bit_pos - 1)); + upper_limit = (signed)sat_limit - 1; + lower_limit = (signed)sat_limit * (-1); + + // important: arithmetical shift right + val_s = val_s >> pre_shift; + X[rd] = (val_s > upper_limit) ? (upper_limit) : ( (val_s < lower_limit) ? (lower_limit) : (val_s) ); + } + } + } + + // custom packed dot product with accumulation (4x8bit) + PDOT8 { + // instruction format: R-type + // opcode space: custom-1 (inst[6:2] = 01010) + // opcode = 0b0101011, func3 = 0b001, func7 = 0b0000000 + encoding: 0b0000000 :: rs2[4:0] :: rs1[4:0] :: 0b001 :: rd[4:0] :: 0b0101011; + args_disass:"{name(rd)}, {name(rs1)}, {name(rs2)}"; + behavior: { + signed<8> op1_0 = (signed<8>)X[rs1][ 7: 0]; + signed<8> op1_1 = (signed<8>)X[rs1][15: 8]; + signed<8> op1_2 = (signed<8>)X[rs1][23:16]; + signed<8> op1_3 = (signed<8>)X[rs1][31:24]; + + signed<8> op2_0 = (signed<8>)X[rs2][ 7: 0]; + signed<8> op2_1 = (signed<8>)X[rs2][15: 8]; + signed<8> op2_2 = (signed<8>)X[rs2][23:16]; + signed<8> op2_3 = (signed<8>)X[rs2][31:24]; + + signed op3 = (signed)X[rd]; + + signed<16> mul0 = op1_0 * op2_0; + signed<16> mul1 = op1_1 * op2_1; + signed<16> mul2 = op1_2 * op2_2; + signed<16> mul3 = op1_3 * op2_3; + + signed<19> sum_tmp = mul0 + mul1 + mul2 + mul3; + + signed<33> result = op3 + sum_tmp; + + if(rd != 0) X[rd] = result[31:0]; + } + } + + // standard signed multiply accumulate with 32 bit operands and 32 bit result + MAC { + // instruction format: R-type + // opcode space: custom-1 (inst[6:2] = 01010) + // opcode = 0b0101011, func3 = 0b010, func7 = 0b0000000 + encoding: 0b0000000 :: rs2[4:0] :: rs1[4:0] :: 0b010 :: rd[4:0] :: 0b0101011; + args_disass:"{name(rd)}, {name(rs1)}, {name(rs2)}"; + behavior: { + signed<65> result = (signed)X[rs1] * (signed)X[rs2] + (signed)X[rd]; + if(rd != 0) X[rd] = result[31:0]; + } + } + + + // WARNING: The following two HW loop instructions are not fully specified or implemented. The idea is to design the HW loops identical to the RI5CY core (current naming: CV32E40P) + // See "Short Hardware Loop Setup Instructions" from RI5CY specification document from April 2019, revision 4.0: https://www.pulp-platform.org/docs/ri5cy_user_manual.pdf -> page 38, chapter 14.2 + // Specific CSRs are introduced to support the HW loops (see page 17, chapter 7). + + // lp.setup HW loop (Short Hardware Loop Setup Instruction) + LOOP { + // instruction format: I-type + // opcode space: custom-3 (inst[6:2] = 11110) + // opcode = 0b1111011, func3 = 0b100 + // uimmL[11:0] src1 100 0000 L 111 1011 -> lp.setup L,rs1, uimmL + encoding: imm[11:0] :: rs1[4:0] :: 0b100 :: 0b0000 :: L[0:0] :: 0b1111011; + args_disass:"{name(L)}, {name(rs1)}, {imm}"; + behavior: { + // L: loop level (two loop levels would be sufficient); L=0 has higher priority and is considered as the inner loop. + /* + lpstart[L] = PC + 4; + lpend[L] = PC + ((unsigned<12>)imm << 1); + lpcount[L] = rs1; + */ + } + } + + // lp.setupi HW loop (Short Hardware Loop Setup Instruction with immediate value for loop count) + LOOPI { + // instruction format: I-type + // opcode space: custom-3 (inst[6:2] = 11110) + // opcode = 0b1111011, func3 = 0b101 + // uimmL[11:0] uimmS[4:0] 101 0000 L 111 1011 -> lp.setupi L, uimmS, uimmL + encoding: imm2[11:0] :: imm1[4:0] :: 0b101 :: 0b0000 :: L[0:0] :: 0b1111011; + args_disass:"{name(L)}, {imm1}, {imm2}"; + behavior: { + // L: loop level (two loop levels would be sufficient); L=0 has higher priority and is considered as the inner loop. + /* + lpstart[L] = PC + 4; + lpend[L] = PC + ((unsigned<5>)imm1 << 1); + lpcount[L] = (unsigned<12>)imm2; + */ + } + } + } +} + +Core TGC_D_XRB_NN provides RV32I, Zicsr, Zifencei, RV32M, RV32IC, X_RB_NN { + architectural_state { + XLEN=32; + // definitions for the architecture wrapper + // XL ZYXWVUTSRQPONMLKJIHGFEDCBA + unsigned MISA_VAL = 0b01000000100100000011000100000100; + unsigned MARCHID_VAL = 0x80000004; + } +} diff --git a/gen_input/TGFS.core_desc b/gen_input/TGFS.core_desc deleted file mode 100644 index ba2a63f..0000000 --- a/gen_input/TGFS.core_desc +++ /dev/null @@ -1,37 +0,0 @@ -import "CoreDSL-Instruction-Set-Description/RV32I.core_desc" -import "CoreDSL-Instruction-Set-Description/RVM.core_desc" -import "CoreDSL-Instruction-Set-Description/RVC.core_desc" - -Core TGC_B provides RV32I { - architectural_state { - unsigned XLEN=32; - unsigned PCLEN=32; - // definitions for the architecture wrapper - // XL ZYXWVUTSRQPONMLKJIHGFEDCBA - unsigned MISA_VAL = 0b01000000000000000000000100000000; - unsigned PGSIZE = 0x1000; //1 << 12; - unsigned PGMASK = 0xfff; //PGSIZE-1 - } -} - -Core TGC_C provides RV32I, RV32M, RV32IC { - architectural_state { - unsigned XLEN=32; - unsigned PCLEN=32; - // definitions for the architecture wrapper - // XL ZYXWVUTSRQPONMLKJIHGFEDCBA - unsigned MISA_VAL = 0b01000000000000000001000100000100; - unsigned PGSIZE = 0x1000; //1 << 12; - unsigned PGMASK = 0xfff; //PGSIZE-1 - } -} - -Core TGC_D provides RV32I, RV32M, RV32IC { - architectural_state { - unsigned XLEN=32; - unsigned PCLEN=32; - // definitions for the architecture wrapper - // XL ZYXWVUTSRQPONMLKJIHGFEDCBA - unsigned MISA_VAL = 0b01000000000000000001000100000100; - } -} diff --git a/gen_input/templates/CORENAME.cpp.gtl b/gen_input/templates/CORENAME.cpp.gtl index 9729bc2..6bb5c4e 100644 --- a/gen_input/templates/CORENAME.cpp.gtl +++ b/gen_input/templates/CORENAME.cpp.gtl @@ -58,7 +58,9 @@ ${coreDef.name.toLowerCase()}::${coreDef.name.toLowerCase()}() { ${coreDef.name.toLowerCase()}::~${coreDef.name.toLowerCase()}() = default; void ${coreDef.name.toLowerCase()}::reset(uint64_t address) { - for(size_t i=0; i::NUM_REGS; ++i) set_reg(i, std::vector(sizeof(traits<${coreDef.name.toLowerCase()}>::reg_t),0)); + auto base_ptr = reinterpret_cast::reg_t*>(get_regs_base_ptr()); + for(size_t i=0; i::NUM_REGS; ++i) + *(base_ptr+i)=0; reg.PC=address; reg.NEXT_PC=reg.PC; reg.PRIV=0x3; diff --git a/gen_input/templates/CORENAME.h.gtl b/gen_input/templates/CORENAME.h.gtl index 4358777..2105569 100644 --- a/gen_input/templates/CORENAME.h.gtl +++ b/gen_input/templates/CORENAME.h.gtl @@ -140,14 +140,6 @@ struct ${coreDef.name.toLowerCase()}: public arch_if { void reset(uint64_t address=0) override; uint8_t* get_regs_base_ptr() override; - /// deprecated - void get_reg(short idx, std::vector& value) override {} - void set_reg(short idx, const std::vector& value) override {} - /// deprecated - bool get_flag(int flag) override {return false;} - void set_flag(int, bool value) override {}; - /// deprecated - void update_flags(operations op, uint64_t opr1, uint64_t opr2) override {}; inline uint64_t get_icount() { return reg.icount; } diff --git a/gen_input/templates/CORENAME_instr.yaml.gtl b/gen_input/templates/CORENAME_instr.yaml.gtl new file mode 100644 index 0000000..122be5e --- /dev/null +++ b/gen_input/templates/CORENAME_instr.yaml.gtl @@ -0,0 +1,16 @@ +<% def getInstructionGroups() { + def instrGroups = [:] + instructions.each { + def groupName = it['instruction'].eContainer().name + if(!instrGroups.containsKey(groupName)) { + instrGroups[groupName]=[] + } + instrGroups[groupName]+=it; + } + instrGroups +}%><%getInstructionGroups().each{name, instrList -> %> +${name}: <% instrList.findAll{!it.instruction.name.startsWith("__")}.each { %> + - ${it.instruction.name}: + encoding: ${it.encoding} + mask: ${it.mask}<%}}%> + diff --git a/gen_input/templates/interp/CORENAME.cpp.gtl b/gen_input/templates/interp/CORENAME.cpp.gtl index 65d3b5b..7cf5c47 100644 --- a/gen_input/templates/interp/CORENAME.cpp.gtl +++ b/gen_input/templates/interp/CORENAME.cpp.gtl @@ -29,7 +29,13 @@ * POSSIBILITY OF SUCH DAMAGE. * *******************************************************************************/ +<% +import com.minres.coredsl.util.BigIntegerWithRadix +def nativeTypeSize(int size){ + if(size<=8) return 8; else if(size<=16) return 16; else if(size<=32) return 32; else return 64; +} +%> #include "../fp_functions.h" #include #include @@ -64,7 +70,7 @@ public: using addr_t = typename super::addr_t; using reg_t = typename traits::reg_t; using mem_type_e = typename traits::mem_type_e; - + vm_impl(); vm_impl(ARCH &core, unsigned core_id = 0, unsigned cluster_id = 0); @@ -92,7 +98,10 @@ protected: // enum { MASK16 = 0b1111110001100011, MASK32 = 0b11111111111100000111000001111111 }; enum { MASK16 = 0b1111111111111111, MASK32 = 0b11111111111100000111000001111111 }; enum { EXTR_MASK16 = MASK16 >> 2, EXTR_MASK32 = MASK32 >> 2 }; - enum { LUT_SIZE = 1 << util::bit_count(EXTR_MASK32), LUT_SIZE_C = 1 << util::bit_count(EXTR_MASK16) }; + enum { + LUT_SIZE = 1 << util::bit_count(static_cast(EXTR_MASK32)), + LUT_SIZE_C = 1 << util::bit_count(static_cast(EXTR_MASK16)) + }; std::array lut; @@ -201,8 +210,8 @@ private: } // used registers<%instr.usedVariables.each{ k,v-> if(v.isArray) {%> - auto* ${k} = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::${k}0]);<% }else{ %> - auto* ${k} = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::${k}]); + auto* ${k} = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::${k}0]);<% }else{ %> + auto* ${k} = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::${k}]); <%}}%>// calculate next pc value *NEXT_PC = *PC + ${instr.length/8}; // execute instruction @@ -243,7 +252,7 @@ private: return pc; } - static constexpr typename traits::addr_t upper_bits = ~traits::PGMASK; + //static constexpr typename traits::addr_t upper_bits = ~traits::PGMASK; iss::status fetch_ins(virt_addr_t pc, uint8_t * data){ auto phys_pc = this->core.v2p(pc); //if ((pc.val & upper_bits) != ((pc.val + 2) & upper_bits)) { // we may cross a page boundary @@ -324,6 +333,7 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co if (is_jump_to_self_enabled(cond) && (insn == 0x0000006f || (insn&0xffff)==0xa001)) throw simulation_stopped(0); // 'J 0' or 'C.J 0' auto f = decode_inst(insn); + auto old_pc = pc.val; pc = (this->*f)(pc, insn); } } diff --git a/incl/iss/arch/riscv_hart_common.h b/incl/iss/arch/riscv_hart_common.h index 7cd6f72..ffe87bc 100644 --- a/incl/iss/arch/riscv_hart_common.h +++ b/incl/iss/arch/riscv_hart_common.h @@ -43,6 +43,8 @@ namespace arch { enum { tohost_dflt = 0xF0001000, fromhost_dflt = 0xF0001040 }; +enum features_e{FEAT_NONE, FEAT_PMP=1, FEAT_EXT_N=2, FEAT_CLIC=4, FEAT_DEBUG=8}; + enum riscv_csr { /* user-level CSR */ // User Trap Setup @@ -164,7 +166,8 @@ enum riscv_csr { // Debug Mode Registers dcsr = 0x7B0, dpc = 0x7B1, - dscratch = 0x7B2 + dscratch0 = 0x7B2, + dscratch1 = 0x7B3 }; diff --git a/incl/iss/arch/riscv_hart_m_p.h b/incl/iss/arch/riscv_hart_m_p.h index 0104e2c..4a7046a 100644 --- a/incl/iss/arch/riscv_hart_m_p.h +++ b/incl/iss/arch/riscv_hart_m_p.h @@ -66,7 +66,7 @@ namespace iss { namespace arch { -template class riscv_hart_m_p : public BASE { +template class riscv_hart_m_p : public BASE { protected: const std::array lvl = {{'U', 'S', 'H', 'M'}}; const std::array trap_str = {{"" @@ -92,7 +92,7 @@ protected: "User external interrupt", "Supervisor external interrupt", "Reserved", "Machine external interrupt"}}; public: using core = BASE; - using this_class = riscv_hart_m_p; + using this_class = riscv_hart_m_p; using phys_addr_t = typename core::phys_addr_t; using reg_t = typename core::reg_t; using addr_t = typename core::addr_t; @@ -221,7 +221,7 @@ public: protected: struct riscv_instrumentation_if : public iss::instrumentation_if { - riscv_instrumentation_if(riscv_hart_m_p &arch) + riscv_instrumentation_if(riscv_hart_m_p &arch) : arch(arch) {} /** * get the name of this architecture @@ -236,7 +236,7 @@ protected: virtual void set_curr_instr_cycles(unsigned cycles) { arch.cycle_offset += cycles - 1; }; - riscv_hart_m_p &arch; + riscv_hart_m_p &arch; }; friend struct riscv_instrumentation_if; @@ -246,6 +246,9 @@ protected: 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); + iss::status read_clic(uint64_t addr, unsigned length, uint8_t *const data); + iss::status write_clic(uint64_t addr, unsigned length, const uint8_t *const data); + virtual iss::status read_csr(unsigned addr, reg_t &val); virtual iss::status write_csr(unsigned addr, reg_t val); @@ -270,10 +273,22 @@ protected: std::unordered_map atomic_reservation; std::unordered_map csr_rd_cb; std::unordered_map csr_wr_cb; + uint8_t clic_cfg_reg{0}; + uint32_t clic_info_reg{0}; + std::array clic_inttrig_reg; + union clic_int_reg_t { + struct{ + uint8_t ip; + uint8_t ie; + uint8_t attr; + uint8_t ctl; + }; + uint32_t raw; + }; + std::vector clic_int_reg; -private: - iss::status read_reg(unsigned addr, reg_t &val); - iss::status write_reg(unsigned addr, reg_t val); + iss::status read_csr_reg(unsigned addr, reg_t &val); + iss::status write_csr_reg(unsigned addr, reg_t val); iss::status read_null(unsigned addr, reg_t &val); iss::status write_null(unsigned addr, reg_t val){return iss::status::Ok;} iss::status read_cycle(unsigned addr, reg_t &val); @@ -291,50 +306,63 @@ private: iss::status write_ip(unsigned addr, reg_t val); iss::status read_hartid(unsigned addr, reg_t &val); iss::status write_epc(unsigned addr, reg_t val); + iss::status write_intstatus(unsigned addr, reg_t val); + iss::status write_intthresh(unsigned addr, reg_t val); + iss::status write_dcsr_dcsr(unsigned addr, reg_t val); + iss::status read_dcsr_reg(unsigned addr, reg_t &val); + iss::status write_dcsr_reg(unsigned addr, reg_t val); + iss::status read_dpc_reg(unsigned addr, reg_t &val); + iss::status write_dpc_reg(unsigned addr, reg_t val); reg_t mhartid_reg{0x0}; std::functionmem_read_cb; std::function mem_write_cb; -protected: void check_interrupt(); + bool pmp_check(const access_type type, const uint64_t addr, const unsigned len); + uint64_t clic_base_addr{0}; + unsigned clic_num_irq{0}; + unsigned clic_num_trigger{0}; + unsigned mcause_max_irq{16}; + inline bool debug_mode_active() {return this->reg.PRIV&0x4;} }; -template -riscv_hart_m_p::riscv_hart_m_p() +template +riscv_hart_m_p::riscv_hart_m_p() : state() , instr_if(*this) { // reset values csr[misa] = traits::MISA_VAL; csr[mvendorid] = 0x669; - csr[marchid] = 0x80000003; + csr[marchid] = traits::MARCHID_VAL; csr[mimpid] = 1; + csr[mclicbase] = 0xc0000000; // TODO: should be taken from YAML file uart_buf.str(""); for (unsigned addr = mhpmcounter3; addr <= mhpmcounter31; ++addr){ csr_rd_cb[addr] = &this_class::read_null; - csr_wr_cb[addr] = &this_class::write_reg; + csr_wr_cb[addr] = &this_class::write_csr_reg; } for (unsigned addr = mhpmcounter3h; addr <= mhpmcounter31h; ++addr){ csr_rd_cb[addr] = &this_class::read_null; - csr_wr_cb[addr] = &this_class::write_reg; + csr_wr_cb[addr] = &this_class::write_csr_reg; } for (unsigned addr = mhpmevent3; addr <= mhpmevent31; ++addr){ csr_rd_cb[addr] = &this_class::read_null; - csr_wr_cb[addr] = &this_class::write_reg; + csr_wr_cb[addr] = &this_class::write_csr_reg; } for (unsigned addr = hpmcounter3; addr <= hpmcounter31; ++addr){ csr_rd_cb[addr] = &this_class::read_null; } for (unsigned addr = hpmcounter3h; addr <= hpmcounter31h; ++addr){ csr_rd_cb[addr] = &this_class::read_null; - //csr_wr_cb[addr] = &this_class::write_reg; + //csr_wr_cb[addr] = &this_class::write_csr_reg; } // common regs const std::array addrs{{misa, mvendorid, marchid, mimpid, mepc, mtvec, mscratch, mcause, mtval, mscratch}}; for(auto addr: addrs) { - csr_rd_cb[addr] = &this_class::read_reg; - csr_wr_cb[addr] = &this_class::write_reg; + csr_rd_cb[addr] = &this_class::read_csr_reg; + csr_wr_cb[addr] = &this_class::write_csr_reg; } // special handling & overrides csr_rd_cb[time] = &this_class::read_time; @@ -362,15 +390,23 @@ riscv_hart_m_p::riscv_hart_m_p() csr_rd_cb[mie] = &this_class::read_ie; csr_wr_cb[mie] = &this_class::write_ie; csr_rd_cb[mhartid] = &this_class::read_hartid; - csr_rd_cb[mcounteren] = &this_class::read_null; - csr_wr_cb[mcounteren] = &this_class::write_null; csr_wr_cb[misa] = &this_class::write_null; csr_wr_cb[mvendorid] = &this_class::write_null; csr_wr_cb[marchid] = &this_class::write_null; csr_wr_cb[mimpid] = &this_class::write_null; + if(FEAT & FEAT_DEBUG){ + csr_wr_cb[dscratch0] = &this_class::write_dcsr_reg; + csr_rd_cb[dscratch0] = &this_class::read_dcsr_reg; + csr_wr_cb[dscratch1] = &this_class::write_dcsr_reg; + csr_rd_cb[dscratch1] = &this_class::read_dcsr_reg; + csr_wr_cb[dpc] = &this_class::write_dpc_reg; + csr_rd_cb[dpc] = &this_class::read_dpc_reg; + csr_wr_cb[dcsr] = &this_class::write_dcsr_dcsr; + csr_rd_cb[dcsr] = &this_class::read_dcsr_reg; + } } -template std::pair riscv_hart_m_p::load_file(std::string name, int type) { +template std::pair riscv_hart_m_p::load_file(std::string name, int type) { FILE *fp = fopen(name.c_str(), "r"); if (fp) { std::array buf; @@ -397,7 +433,7 @@ template std::pair riscv_hart_m_p::load_fi traits::MEM, pseg->get_physical_address(), fsize, reinterpret_cast(seg_data)); if (res != iss::Ok) - LOG(ERROR) << "problem writing " << fsize << "bytes to 0x" << std::hex + LOG(ERR) << "problem writing " << fsize << "bytes to 0x" << std::hex << pseg->get_physical_address(); } } @@ -436,8 +472,8 @@ template std::pair riscv_hart_m_p::load_fi throw std::runtime_error("memory load file not found"); } -template -iss::status riscv_hart_m_p::read(const address_type type, const access_type access, const uint32_t space, +template +iss::status riscv_hart_m_p::read(const address_type type, const access_type access, const uint32_t space, const uint64_t addr, const unsigned length, uint8_t *const data) { #ifndef NDEBUG if (access && iss::access_type::DEBUG) { @@ -505,8 +541,8 @@ iss::status riscv_hart_m_p::read(const address_type type, const access_typ } } -template -iss::status riscv_hart_m_p::write(const address_type type, const access_type access, const uint32_t space, +template +iss::status riscv_hart_m_p::write(const address_type type, const access_type access, const uint32_t space, const uint64_t addr, const unsigned length, const uint8_t *const data) { #ifndef NDEBUG const char *prefix = (access && iss::access_type::DEBUG) ? "debug " : ""; @@ -621,7 +657,7 @@ iss::status riscv_hart_m_p::write(const address_type type, const access_ty } } -template iss::status riscv_hart_m_p::read_csr(unsigned addr, reg_t &val) { +template iss::status riscv_hart_m_p::read_csr(unsigned addr, reg_t &val) { if (addr >= csr.size()) return iss::Err; auto req_priv_lvl = (addr >> 8) & 0x3; if (this->reg.PRIV < req_priv_lvl) // not having required privileges @@ -632,7 +668,7 @@ template iss::status riscv_hart_m_p::read_csr(unsigned add return (this->*(it->second))(addr, val); } -template iss::status riscv_hart_m_p::write_csr(unsigned addr, reg_t val) { +template iss::status riscv_hart_m_p::write_csr(unsigned addr, reg_t val) { if (addr >= csr.size()) return iss::Err; auto req_priv_lvl = (addr >> 8) & 0x3; if (this->reg.PRIV < req_priv_lvl) // not having required privileges @@ -645,22 +681,22 @@ template iss::status riscv_hart_m_p::write_csr(unsigned ad return (this->*(it->second))(addr, val); } -template iss::status riscv_hart_m_p::read_reg(unsigned addr, reg_t &val) { +template iss::status riscv_hart_m_p::read_csr_reg(unsigned addr, reg_t &val) { val = csr[addr]; return iss::Ok; } -template iss::status riscv_hart_m_p::read_null(unsigned addr, reg_t &val) { +template iss::status riscv_hart_m_p::read_null(unsigned addr, reg_t &val) { val = 0; return iss::Ok; } -template iss::status riscv_hart_m_p::write_reg(unsigned addr, reg_t val) { +template iss::status riscv_hart_m_p::write_csr_reg(unsigned addr, reg_t val) { csr[addr] = val; return iss::Ok; } -template iss::status riscv_hart_m_p::read_cycle(unsigned addr, reg_t &val) { +template iss::status riscv_hart_m_p::read_cycle(unsigned addr, reg_t &val) { auto cycle_val = this->reg.icount + cycle_offset; if (addr == mcycle) { val = static_cast(cycle_val); @@ -671,7 +707,7 @@ template iss::status riscv_hart_m_p::read_cycle(unsigned a return iss::Ok; } -template iss::status riscv_hart_m_p::write_cycle(unsigned addr, reg_t val) { +template iss::status riscv_hart_m_p::write_cycle(unsigned addr, reg_t val) { if (sizeof(typename traits::reg_t) != 4) { if (addr == mcycleh) return iss::Err; @@ -687,7 +723,7 @@ template iss::status riscv_hart_m_p::write_cycle(unsigned return iss::Ok; } -template iss::status riscv_hart_m_p::read_instret(unsigned addr, reg_t &val) { +template iss::status riscv_hart_m_p::read_instret(unsigned addr, reg_t &val) { if ((addr&0xff) == (minstret&0xff)) { val = static_cast(this->reg.instret); } else if ((addr&0xff) == (minstreth&0xff)) { @@ -697,7 +733,7 @@ template iss::status riscv_hart_m_p::read_instret(unsigned return iss::Ok; } -template iss::status riscv_hart_m_p::write_instret(unsigned addr, reg_t val) { +template iss::status riscv_hart_m_p::write_instret(unsigned addr, reg_t val) { if (sizeof(typename traits::reg_t) != 4) { if ((addr&0xff) == (minstreth&0xff)) return iss::Err; @@ -713,7 +749,7 @@ template iss::status riscv_hart_m_p::write_instret(unsigne return iss::Ok; } -template iss::status riscv_hart_m_p::read_time(unsigned addr, reg_t &val) { +template iss::status riscv_hart_m_p::read_time(unsigned addr, reg_t &val) { uint64_t time_val = this->reg.icount / (100000000 / 32768 - 1); //-> ~3052; if (addr == time) { val = static_cast(time_val); @@ -724,64 +760,105 @@ template iss::status riscv_hart_m_p::read_time(unsigned ad return iss::Ok; } -template iss::status riscv_hart_m_p::read_tvec(unsigned addr, reg_t &val) { +template iss::status riscv_hart_m_p::read_tvec(unsigned addr, reg_t &val) { val = csr[mtvec] & ~2; return iss::Ok; } -template iss::status riscv_hart_m_p::read_status(unsigned addr, reg_t &val) { +template iss::status riscv_hart_m_p::read_status(unsigned addr, reg_t &val) { val = state.mstatus & hart_state_type::get_mask(); return iss::Ok; } -template iss::status riscv_hart_m_p::write_status(unsigned addr, reg_t val) { +template iss::status riscv_hart_m_p::write_status(unsigned addr, reg_t val) { state.write_mstatus(val); check_interrupt(); return iss::Ok; } -template iss::status riscv_hart_m_p::write_cause(unsigned addr, reg_t val) { +template iss::status riscv_hart_m_p::write_cause(unsigned addr, reg_t val) { csr[mcause] = val & ((1UL<<(traits::XLEN-1))|0xf); //TODO: make exception code size configurable return iss::Ok; } -template iss::status riscv_hart_m_p::read_ie(unsigned addr, reg_t &val) { - val = csr[mie]; - return iss::Ok; -} - -template iss::status riscv_hart_m_p::read_hartid(unsigned addr, reg_t &val) { +template iss::status riscv_hart_m_p::read_hartid(unsigned addr, reg_t &val) { val = mhartid_reg; return iss::Ok; } -template iss::status riscv_hart_m_p::write_ie(unsigned addr, reg_t val) { +template iss::status riscv_hart_m_p::read_ie(unsigned addr, reg_t &val) { + auto mask = get_irq_mask(); + val = csr[mie] & mask; + return iss::Ok; +} + +template iss::status riscv_hart_m_p::write_ie(unsigned addr, reg_t val) { auto mask = get_irq_mask(); csr[mie] = (csr[mie] & ~mask) | (val & mask); check_interrupt(); return iss::Ok; } -template iss::status riscv_hart_m_p::read_ip(unsigned addr, reg_t &val) { - val = csr[mip]; +template iss::status riscv_hart_m_p::read_ip(unsigned addr, reg_t &val) { + auto mask = get_irq_mask(); + val = csr[mip] & mask; return iss::Ok; } -template iss::status riscv_hart_m_p::write_ip(unsigned addr, reg_t val) { +template iss::status riscv_hart_m_p::write_ip(unsigned addr, reg_t val) { auto mask = get_irq_mask(); - mask &= ~(1 << 7); // MTIP is read only + mask &= 0xf; // only xSIP is writable csr[mip] = (csr[mip] & ~mask) | (val & mask); check_interrupt(); return iss::Ok; } -template iss::status riscv_hart_m_p::write_epc(unsigned addr, reg_t val) { +template iss::status riscv_hart_m_p::write_epc(unsigned addr, reg_t val) { csr[addr] = val & get_pc_mask(); return iss::Ok; } -template -iss::status riscv_hart_m_p::read_mem(phys_addr_t paddr, unsigned length, uint8_t *const data) { +template iss::status riscv_hart_m_p::write_dcsr_dcsr(unsigned addr, reg_t val) { + if(!debug_mode_active()) + throw illegal_instruction_fault(this->fault_data); + // +-------------- ebreakm + // | +---------- stepi + // | | +++----- cause + // | | ||| +- step + csr[addr] = val & 0b1000100111000100U; + return iss::Ok; +} + +template iss::status riscv_hart_m_p::read_dcsr_reg(unsigned addr, reg_t &val) { + if(!debug_mode_active()) + throw illegal_instruction_fault(this->fault_data); + val = csr[addr]; + return iss::Ok; +} + +template iss::status riscv_hart_m_p::write_dcsr_reg(unsigned addr, reg_t val) { + if(!debug_mode_active()) + throw illegal_instruction_fault(this->fault_data); + csr[addr] = val; + return iss::Ok; +} + +template iss::status riscv_hart_m_p::read_dpc_reg(unsigned addr, reg_t &val) { + if(!debug_mode_active()) + throw illegal_instruction_fault(this->fault_data); + val = this->reg.DPC; + return iss::Ok; +} + +template iss::status riscv_hart_m_p::write_dpc_reg(unsigned addr, reg_t val) { + if(!debug_mode_active()) + throw illegal_instruction_fault(this->fault_data); + this->reg.DPC = val; + return iss::Ok; +} + +template +iss::status riscv_hart_m_p::read_mem(phys_addr_t paddr, unsigned length, uint8_t *const data) { if(mem_read_cb) return mem_read_cb(paddr, length, data); switch (paddr.val) { case 0x0200BFF8: { // CLINT base, mtime reg @@ -805,8 +882,8 @@ iss::status riscv_hart_m_p::read_mem(phys_addr_t paddr, unsigned length, u return iss::Ok; } -template -iss::status riscv_hart_m_p::write_mem(phys_addr_t paddr, unsigned length, const uint8_t *const data) { +template +iss::status riscv_hart_m_p::write_mem(phys_addr_t paddr, unsigned length, const uint8_t *const data) { if(mem_write_cb) return mem_write_cb(paddr, length, data); switch (paddr.val) { case 0x10013000: // UART0 base, TXFIFO reg @@ -883,12 +960,12 @@ iss::status riscv_hart_m_p::write_mem(phys_addr_t paddr, unsigned length, return iss::Ok; } -template inline void riscv_hart_m_p::reset(uint64_t address) { +template inline void riscv_hart_m_p::reset(uint64_t address) { BASE::reset(address); state.mstatus = hart_state_type::mstatus_reset_val; } -template void riscv_hart_m_p::check_interrupt() { +template void riscv_hart_m_p::check_interrupt() { //auto ideleg = csr[mideleg]; // Multiple simultaneous interrupts and traps at the same privilege level are // handled in the following decreasing priority order: @@ -910,17 +987,43 @@ template void riscv_hart_m_p::check_interrupt() { } } -template uint64_t riscv_hart_m_p::enter_trap(uint64_t flags, uint64_t addr, uint64_t instr) { +template uint64_t riscv_hart_m_p::enter_trap(uint64_t flags, uint64_t addr, uint64_t instr) { // flags are ACTIVE[31:31], CAUSE[30:16], TRAPID[15:0] // calculate and write mcause val auto trap_id = bit_sub<0, 16>(flags); auto cause = bit_sub<16, 15>(flags); - if (trap_id == 0 && cause == 11) cause = 0x8 + PRIV_M; // adjust environment call cause // calculate effective privilege level if (trap_id == 0) { // exception + if (cause == 11) cause = 0x8 + PRIV_M; // adjust environment call cause // store ret addr in xepc register csr[mepc] = static_cast(addr) & get_pc_mask(); // store actual address instruction of exception - csr[mtval] = cause==2?((instr & 0x3)==3?instr:instr&0xffff):fault_data; + /* + * write mtval if new_priv=M_MODE, spec says: + * When a hardware breakpoint is triggered, or an instruction-fetch, load, + * or store address-misaligned, + * access, or page-fault exception occurs, mtval is written with the + * faulting effective address. + */ + switch(cause){ + case 0: + csr[mtval] = static_cast(addr); + break; + case 2: + csr[mtval] = (instr & 0x3)==3?instr:instr&0xffff; + break; + case 3: + //TODO: implement debug mode behavior + // csr[dpc] = addr; + // csr[dcsr] = (csr[dcsr] & ~0x1c3) | (1<<6) | PRIV_M; //FIXME: cause should not be 4 (stepi) + csr[mtval] = 0; + break; + case 4: + case 6: + csr[mtval] = fault_data; + break; + default: + csr[mtval] = 0; + } fault_data = 0; } else { csr[mepc] = this->reg.NEXT_PC & get_pc_mask(); // store next address if interrupt @@ -948,7 +1051,11 @@ template uint64_t riscv_hart_m_p::enter_trap(uint64_t flag this->reg.PRIV = PRIV_M; this->reg.trap_state = 0; std::array buffer; +#if defined(_MSC_VER) + sprintf(buffer.data(), "0x%016llx", addr); +#else sprintf(buffer.data(), "0x%016lx", addr); +#endif if((flags&0xffffffff) != 0xffffffff) CLOG(INFO, disass) << (trap_id ? "Interrupt" : "Trap") << " with cause '" << (trap_id ? irq_str[cause] : trap_str[cause]) << "' (" << cause << ")" @@ -956,7 +1063,7 @@ template uint64_t riscv_hart_m_p::enter_trap(uint64_t flag return this->reg.NEXT_PC; } -template uint64_t riscv_hart_m_p::leave_trap(uint64_t flags) { +template uint64_t riscv_hart_m_p::leave_trap(uint64_t flags) { state.mstatus.MIE = state.mstatus.MPIE; state.mstatus.MPIE = 1; // sets the pc to the value stored in the x epc register. diff --git a/incl/iss/arch/riscv_hart_msu_vp.h b/incl/iss/arch/riscv_hart_msu_vp.h index ff1ed78..aa88e6d 100644 --- a/incl/iss/arch/riscv_hart_msu_vp.h +++ b/incl/iss/arch/riscv_hart_msu_vp.h @@ -145,7 +145,7 @@ public: mstatus_t mstatus; - static const reg_t mstatus_reset_val = 0; + static const reg_t mstatus_reset_val = 0x1800; void write_mstatus(T val, unsigned priv_lvl) { auto mask = get_mask(priv_lvl); @@ -398,7 +398,7 @@ private: iss::status read_ip(unsigned addr, reg_t &val); iss::status write_ip(unsigned addr, reg_t val); iss::status read_hartid(unsigned addr, reg_t &val); - iss::status write_mepc(unsigned addr, reg_t val); + iss::status write_epc(unsigned addr, reg_t val); iss::status read_satp(unsigned addr, reg_t &val); iss::status write_satp(unsigned addr, reg_t val); iss::status read_fcsr(unsigned addr, reg_t &val); @@ -419,7 +419,7 @@ riscv_hart_msu_vp::riscv_hart_msu_vp() // reset values csr[misa] = traits::MISA_VAL; csr[mvendorid] = 0x669; - csr[marchid] = 0x80000003; + csr[marchid] = traits::MARCHID_VAL; csr[mimpid] = 1; uart_buf.str(""); @@ -954,8 +954,8 @@ template iss::status riscv_hart_msu_vp::write_ip(unsigned return iss::Ok; } -template iss::status riscv_hart_m_p::write_epc(unsigned addr, reg_t val) { - csr[addr] = val & get_pc_mask(); +template iss::status riscv_hart_msu_vp::write_epc(unsigned addr, reg_t val) { + csr[addr] = val & get_pc_mask(); return iss::Ok; } diff --git a/incl/iss/arch/riscv_hart_mu_p.h b/incl/iss/arch/riscv_hart_mu_p.h index 8d01c3f..2444cd7 100644 --- a/incl/iss/arch/riscv_hart_mu_p.h +++ b/incl/iss/arch/riscv_hart_mu_p.h @@ -66,8 +66,6 @@ namespace iss { namespace arch { -enum features_e{FEAT_NONE, FEAT_PMP, FEAT_EXT_N, FEAT_CLIC}; - template class riscv_hart_mu_p : public BASE { protected: const std::array lvl = {{'U', 'S', 'H', 'M'}}; @@ -146,7 +144,7 @@ public: mstatus_t mstatus; - static const reg_t mstatus_reset_val = 0; + static const reg_t mstatus_reset_val = 0x1800; // MPP set to 1 void write_mstatus(T val, unsigned priv_lvl) { auto mask = get_mask(priv_lvl); @@ -183,7 +181,7 @@ public: }; using hart_state_type = hart_state; - constexpr reg_t get_irq_wrmask(size_t mode) { + constexpr reg_t get_irq_mask(size_t mode) { std::array m = {{ 0b000100010001, // U mode 0b001100110011, // S mode @@ -304,7 +302,6 @@ protected: }; std::vector clic_int_reg; -private: iss::status read_csr_reg(unsigned addr, reg_t &val); iss::status write_csr_reg(unsigned addr, reg_t val); iss::status read_null(unsigned addr, reg_t &val); @@ -328,18 +325,23 @@ private: iss::status write_epc(unsigned addr, reg_t val); iss::status write_intstatus(unsigned addr, reg_t val); iss::status write_intthresh(unsigned addr, reg_t val); + iss::status write_dcsr_dcsr(unsigned addr, reg_t val); + iss::status read_dcsr_reg(unsigned addr, reg_t &val); + iss::status write_dcsr_reg(unsigned addr, reg_t val); + iss::status read_dpc_reg(unsigned addr, reg_t &val); + iss::status write_dpc_reg(unsigned addr, reg_t val); reg_t mhartid_reg{0x0}; std::functionmem_read_cb; std::function mem_write_cb; -protected: void check_interrupt(); bool pmp_check(const access_type type, const uint64_t addr, const unsigned len); uint64_t clic_base_addr{0}; unsigned clic_num_irq{0}; unsigned clic_num_trigger{0}; unsigned mcause_max_irq{16}; + inline bool debug_mode_active() {return this->reg.PRIV&0x4;} }; template @@ -349,7 +351,7 @@ riscv_hart_mu_p::riscv_hart_mu_p() // reset values csr[misa] = traits::MISA_VAL; csr[mvendorid] = 0x669; - csr[marchid] = 0x80000004; + csr[marchid] = traits::MARCHID_VAL; csr[mimpid] = 1; csr[mclicbase] = 0xc0000000; // TODO: should be taken from YAML file @@ -464,6 +466,16 @@ riscv_hart_mu_p::riscv_hart_mu_p() clic_info_reg = (/*CLICINTCTLBITS*/ 4U<<21) + clic_num_irq; mcause_max_irq=clic_num_irq+16; } + if(FEAT & FEAT_DEBUG){ + csr_wr_cb[dscratch0] = &this_class::write_dcsr_reg; + csr_rd_cb[dscratch0] = &this_class::read_dcsr_reg; + csr_wr_cb[dscratch1] = &this_class::write_dcsr_reg; + csr_rd_cb[dscratch1] = &this_class::read_dcsr_reg; + csr_wr_cb[dpc] = &this_class::write_dpc_reg; + csr_rd_cb[dpc] = &this_class::read_dpc_reg; + csr_wr_cb[dcsr] = &this_class::write_dcsr_dcsr; + csr_rd_cb[dcsr] = &this_class::read_dcsr_reg; + } } template std::pair riscv_hart_mu_p::load_file(std::string name, int type) { @@ -493,7 +505,7 @@ template std::pair riscv_hart_m traits::MEM, pseg->get_physical_address(), fsize, reinterpret_cast(seg_data)); if (res != iss::Ok) - LOG(ERROR) << "problem writing " << fsize << "bytes to 0x" << std::hex + LOG(ERR) << "problem writing " << fsize << "bytes to 0x" << std::hex << pseg->get_physical_address(); } } @@ -543,25 +555,27 @@ template bool riscv_hart_mu_p::pmp_ constexpr auto PMP_NA4 =0x2U; constexpr auto PMP_NAPOT =0x3U; reg_t base = 0; + auto any_active = false; for (size_t i = 0; i < 16; i++) { reg_t tor = csr[pmpaddr0+i] << PMP_SHIFT; uint8_t cfg = csr[pmpcfg0+(i/4)]>>(i%4); if (cfg & PMP_A) { + any_active=true; auto pmp_a = (cfg & PMP_A) >> 3; - bool is_tor = pmp_a == PMP_TOR; - bool is_na4 = pmp_a == PMP_NA4; + auto is_tor = pmp_a == PMP_TOR; + auto is_na4 = pmp_a == PMP_NA4; reg_t mask = (csr[pmpaddr0+i] << 1) | (!is_na4); mask = ~(mask & ~(mask + 1)) << PMP_SHIFT; // Check each 4-byte sector of the access - bool any_match = false; - bool all_match = true; + auto any_match = false; + auto all_match = true; for (reg_t offset = 0; offset < len; offset += 1 << PMP_SHIFT) { reg_t cur_addr = addr + offset; - bool napot_match = ((cur_addr ^ tor) & mask) == 0; - bool tor_match = base <= cur_addr && cur_addr < tor; - bool match = is_tor ? tor_match : napot_match; + auto napot_match = ((cur_addr ^ tor) & mask) == 0; + auto tor_match = base <= cur_addr && cur_addr < tor; + auto match = is_tor ? tor_match : napot_match; any_match |= match; all_match &= match; } @@ -577,7 +591,38 @@ template bool riscv_hart_mu_p::pmp_ } base = tor; } - return this->reg.PRIV == PRIV_M; +// constexpr auto pmp_num_regs = 16; +// reg_t tor_base = 0; +// auto any_active = false; +// auto lower_addr = addr >>2; +// auto upper_addr = (addr+len-1)>>2; +// for (size_t i = 0; i < pmp_num_regs; i++) { +// uint8_t cfg = csr[pmpcfg0+(i/4)]>>(i%4); +// uint8_t cfg_next = i==(pmp_num_regs-1)? 0 : csr[pmpcfg0+((i+1)/4)]>>((i+1)%4); +// auto pmpaddr = csr[pmpaddr0+i]; +// if (cfg & PMP_A) { +// any_active=true; +// auto is_tor = bit_sub<3, 2>(cfg) == PMP_TOR; +// auto is_napot = bit_sub<4, 1>(cfg) && bit_sub<3, 2>(cfg_next)!= PMP_TOR; +// if(is_napot) { +// reg_t mask = bit_sub<3, 1>(cfg)?~( pmpaddr & ~(pmpaddr + 1)): 0x3fffffff; +// auto mpmpaddr = pmpaddr & mask; +// if((lower_addr&mask) == mpmpaddr && (upper_addr&mask)==mpmpaddr) +// return (this->reg.PRIV == PRIV_M && !(cfg & PMP_L)) || +// (type == access_type::READ && (cfg & PMP_R)) || +// (type == access_type::WRITE && (cfg & PMP_W)) || +// (type == access_type::FETCH && (cfg & PMP_X)); +// } else if(is_tor) { +// if(lower_addr>=tor_base && upper_addr<=pmpaddr) +// return (this->reg.PRIV == PRIV_M && !(cfg & PMP_L)) || +// (type == access_type::READ && (cfg & PMP_R)) || +// (type == access_type::WRITE && (cfg & PMP_W)) || +// (type == access_type::FETCH && (cfg & PMP_X)); +// } +// } +// tor_base = pmpaddr; +// } + return !any_active || this->reg.PRIV == PRIV_M; } @@ -917,7 +962,7 @@ template iss::status riscv_hart_mu_p iss::status riscv_hart_mu_p::read_ie(unsigned addr, reg_t &val) { - auto mask = get_irq_wrmask((addr >> 8) & 0x3); + auto mask = get_irq_mask((addr >> 8) & 0x3); val = csr[mie] & mask; if(this->reg.PRIV!=3) val &= csr[mideleg]; @@ -925,16 +970,14 @@ template iss::status riscv_hart_mu_p iss::status riscv_hart_mu_p::write_ie(unsigned addr, reg_t val) { - auto mask = get_irq_wrmask((addr >> 8) & 0x3); - if(this->reg.PRIV==0) - mask&= ~(0xff<<4); // STIE and UTIE are read only in user and supervisor mode + auto mask = get_irq_mask((addr >> 8) & 0x3); csr[mie] = (csr[mie] & ~mask) | (val & mask); check_interrupt(); return iss::Ok; } template iss::status riscv_hart_mu_p::read_ip(unsigned addr, reg_t &val) { - auto mask = get_irq_wrmask((addr >> 8) & 0x3); + auto mask = get_irq_mask((addr >> 8) & 0x3); val = csr[mip] & mask; if(this->reg.PRIV!=3) val &= csr[mideleg]; @@ -942,10 +985,8 @@ template iss::status riscv_hart_mu_p iss::status riscv_hart_mu_p::write_ip(unsigned addr, reg_t val) { - auto mask = get_irq_wrmask((addr >> 8) & 0x3); - mask &= ~(8 << 4); // MTIP is read only - if(this->reg.PRIV!=3) - mask &= ~(3 << 4); // STIP and UTIP are read only in user and supervisor mode + auto mask = get_irq_mask((addr >> 8) & 0x3); + mask &= 0xf; // only xSIP is writable csr[mip] = (csr[mip] & ~mask) | (val & mask); check_interrupt(); return iss::Ok; @@ -968,6 +1009,45 @@ template iss::status riscv_hart_mu_p iss::status riscv_hart_mu_p::write_dcsr_dcsr(unsigned addr, reg_t val) { + if(!debug_mode_active()) + throw illegal_instruction_fault(this->fault_data); + // +-------------- ebreakm + // | +---------- stepi + // | | +++----- cause + // | | ||| +- step + csr[addr] = val & 0b1000100111000100U; + return iss::Ok; +} + +template iss::status riscv_hart_mu_p::read_dcsr_reg(unsigned addr, reg_t &val) { + if(!debug_mode_active()) + throw illegal_instruction_fault(this->fault_data); + val = csr[addr]; + return iss::Ok; +} + +template iss::status riscv_hart_mu_p::write_dcsr_reg(unsigned addr, reg_t val) { + if(!debug_mode_active()) + throw illegal_instruction_fault(this->fault_data); + csr[addr] = val; + return iss::Ok; +} + +template iss::status riscv_hart_mu_p::read_dpc_reg(unsigned addr, reg_t &val) { + if(!debug_mode_active()) + throw illegal_instruction_fault(this->fault_data); + val = this->reg.DPC; + return iss::Ok; +} + +template iss::status riscv_hart_mu_p::write_dpc_reg(unsigned addr, reg_t val) { + if(!debug_mode_active()) + throw illegal_instruction_fault(this->fault_data); + this->reg.DPC = val; + return iss::Ok; +} + template iss::status riscv_hart_mu_p::write_intthresh(unsigned addr, reg_t val) { csr[addr]= val &0xff; @@ -1203,7 +1283,27 @@ template uint64_t riscv_hart_mu_p:: * access, or page-fault exception occurs, mtval is written with the * faulting effective address. */ - csr[utval | (new_priv << 8)] = cause==2?((instr & 0x3)==3?instr:instr&0xffff):fault_data; + switch(cause){ + case 0: + csr[utval | (new_priv << 8)] = static_cast(addr); + break; + case 2: + csr[utval | (new_priv << 8)] = (instr & 0x3)==3?instr:instr&0xffff; + break; + case 3: + //TODO: implement debug mode behavior + // csr[dpc] = addr; + // csr[dcsr] = (csr[dcsr] & ~0x1c3) | (1<<6) | PRIV_M; //FIXME: cause should not be 4 (stepi) + csr[utval | (new_priv << 8)] = 0; + break; + case 4: + case 6: + case 7: + csr[utval | (new_priv << 8)] = fault_data; + break; + default: + csr[utval | (new_priv << 8)] = 0; + } fault_data = 0; } else { if (this->reg.PRIV != PRIV_M && ((csr[mideleg] >> cause) & 0x1) != 0) @@ -1256,27 +1356,33 @@ template uint64_t riscv_hart_mu_p:: template uint64_t riscv_hart_mu_p::leave_trap(uint64_t flags) { auto cur_priv = this->reg.PRIV; auto inst_priv = (flags & 0x3)? 3:0; - auto status = state.mstatus; - // pop the relevant lower-privilege interrupt enable and privilege mode stack - // clear respective yIE - switch (inst_priv) { - case PRIV_M: - this->reg.PRIV = state.mstatus.MPP; - state.mstatus.MPP = 0; // clear mpp to U mode - state.mstatus.MIE = state.mstatus.MPIE; - state.mstatus.MPIE = 1; - break; - case PRIV_U: - this->reg.PRIV = 0; - state.mstatus.UIE = state.mstatus.UPIE; - state.mstatus.UPIE = 1; - break; + if(inst_priv>cur_priv){ + auto trap_val = 0x80ULL << 24 | (2 << 16); // illegal instruction + this->reg.trap_state = trap_val; + this->reg.NEXT_PC = std::numeric_limits::max(); + } else { + auto status = state.mstatus; + // pop the relevant lower-privilege interrupt enable and privilege mode stack + // clear respective yIE + switch (inst_priv) { + case PRIV_M: + this->reg.PRIV = state.mstatus.MPP; + state.mstatus.MPP = 0; // clear mpp to U mode + state.mstatus.MIE = state.mstatus.MPIE; + state.mstatus.MPIE = 1; + break; + case PRIV_U: + this->reg.PRIV = 0; + state.mstatus.UIE = state.mstatus.UPIE; + state.mstatus.UPIE = 1; + break; + } + // sets the pc to the value stored in the x epc register. + this->reg.NEXT_PC = csr[uepc | inst_priv << 8]; + CLOG(INFO, disass) << "Executing xRET , changing privilege level from " << lvl[cur_priv] << " to " + << lvl[this->reg.PRIV]; + check_interrupt(); } - // sets the pc to the value stored in the x epc register. - this->reg.NEXT_PC = csr[uepc | inst_priv << 8]; - CLOG(INFO, disass) << "Executing xRET , changing privilege level from " << lvl[cur_priv] << " to " - << lvl[this->reg.PRIV]; - check_interrupt(); return this->reg.NEXT_PC; } diff --git a/incl/iss/arch/tgc_c.h b/incl/iss/arch/tgc_c.h index 16fa1b4..2efcaf9 100644 --- a/incl/iss/arch/tgc_c.h +++ b/incl/iss/arch/tgc_c.h @@ -47,18 +47,18 @@ template <> struct traits { constexpr static char const* const core_type = "TGC_C"; - static constexpr std::array reg_names{ - {"X0", "X1", "X2", "X3", "X4", "X5", "X6", "X7", "X8", "X9", "X10", "X11", "X12", "X13", "X14", "X15", "X16", "X17", "X18", "X19", "X20", "X21", "X22", "X23", "X24", "X25", "X26", "X27", "X28", "X29", "X30", "X31", "PC", "NEXT_PC", "PRIV"}}; + static constexpr std::array reg_names{ + {"X0", "X1", "X2", "X3", "X4", "X5", "X6", "X7", "X8", "X9", "X10", "X11", "X12", "X13", "X14", "X15", "X16", "X17", "X18", "X19", "X20", "X21", "X22", "X23", "X24", "X25", "X26", "X27", "X28", "X29", "X30", "X31", "PC", "NEXT_PC", "PRIV", "DPC"}}; - static constexpr std::array reg_aliases{ - {"X0", "X1", "X2", "X3", "X4", "X5", "X6", "X7", "X8", "X9", "X10", "X11", "X12", "X13", "X14", "X15", "X16", "X17", "X18", "X19", "X20", "X21", "X22", "X23", "X24", "X25", "X26", "X27", "X28", "X29", "X30", "X31", "PC", "NEXT_PC", "PRIV"}}; + 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 {XLEN=32, PCLEN=32, MISA_VAL=0b01000000000000000001000100000100, PGSIZE=0x1000, PGMASK=0b111111111111, CSR_SIZE=4096, fence=0, fencei=1, fencevmal=2, fencevmau=3, MUL_LEN=64}; + enum constants {MISA_VAL=0b01000000000000000001000100000100, MARCHID_VAL=0x80000003, 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; enum reg_e { - X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, X30, X31, PC, NEXT_PC, PRIV, NUM_REGS, + X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, X30, X31, PC, NEXT_PC, PRIV, DPC, NUM_REGS, TRAP_STATE=NUM_REGS, PENDING_TRAP, ICOUNT, @@ -76,11 +76,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,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}}; - 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,153,161}}; + 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 const uint64_t addr_mask = (reg_t(1) << (XLEN - 1)) | ((reg_t(1) << (XLEN - 1)) - 1); @@ -133,50 +133,52 @@ template <> struct traits { SRET = 41, MRET = 42, WFI = 43, - CSRRW = 44, - CSRRS = 45, - CSRRC = 46, - CSRRWI = 47, - CSRRSI = 48, - CSRRCI = 49, - MUL = 50, - MULH = 51, - MULHSU = 52, - MULHU = 53, - DIV = 54, - DIVU = 55, - REM = 56, - REMU = 57, - CADDI4SPN = 58, - CLW = 59, - CSW = 60, - CADDI = 61, - CNOP = 62, - CJAL = 63, - CLI = 64, - CLUI = 65, - CADDI16SP = 66, - __reserved_clui = 67, - CSRLI = 68, - CSRAI = 69, - CANDI = 70, - CSUB = 71, - CXOR = 72, - COR = 73, - CAND = 74, - CJ = 75, - CBEQZ = 76, - CBNEZ = 77, - CSLLI = 78, - CLWSP = 79, - CMV = 80, - CJR = 81, - __reserved_cmv = 82, - CADD = 83, - CJALR = 84, - CEBREAK = 85, - CSWSP = 86, - DII = 87, + DRET = 44, + CSRRW = 45, + CSRRS = 46, + CSRRC = 47, + CSRRWI = 48, + CSRRSI = 49, + CSRRCI = 50, + FENCE_I = 51, + MUL = 52, + MULH = 53, + MULHSU = 54, + MULHU = 55, + DIV = 56, + DIVU = 57, + REM = 58, + REMU = 59, + CADDI4SPN = 60, + CLW = 61, + CSW = 62, + CADDI = 63, + CNOP = 64, + CJAL = 65, + CLI = 66, + CLUI = 67, + CADDI16SP = 68, + __reserved_clui = 69, + CSRLI = 70, + CSRAI = 71, + CANDI = 72, + CSUB = 73, + CXOR = 74, + COR = 75, + CAND = 76, + CJ = 77, + CBEQZ = 78, + CBNEZ = 79, + CSLLI = 80, + CLWSP = 81, + CMV = 82, + CJR = 83, + __reserved_cmv = 84, + CADD = 85, + CJALR = 86, + CEBREAK = 87, + CSWSP = 88, + DII = 89, MAX_OPCODE }; }; @@ -194,14 +196,6 @@ struct tgc_c: public arch_if { void reset(uint64_t address=0) override; uint8_t* get_regs_base_ptr() override; - /// deprecated - void get_reg(short idx, std::vector& value) override {} - void set_reg(short idx, const std::vector& value) override {} - /// deprecated - bool get_flag(int flag) override {return false;} - void set_flag(int, bool value) override {}; - /// deprecated - void update_flags(operations op, uint64_t opr1, uint64_t opr2) override {}; inline uint64_t get_icount() { return reg.icount; } @@ -260,7 +254,8 @@ protected: uint32_t X31 = 0; uint32_t PC = 0; uint32_t NEXT_PC = 0; - uint8_t PRIV = 0; + uint8_t PRIV = 0; + uint32_t DPC = 0; uint32_t trap_state = 0, pending_trap = 0; uint64_t icount = 0; uint64_t cycle = 0; diff --git a/incl/sysc/core_complex.h b/incl/sysc/core_complex.h index 4668837..33db30b 100644 --- a/incl/sysc/core_complex.h +++ b/incl/sysc/core_complex.h @@ -48,6 +48,9 @@ #include #include +namespace iss { + class vm_plugin; +} namespace sysc { class tlm_dmi_ext : public tlm::tlm_dmi { @@ -99,6 +102,8 @@ public: cci::cci_param mhartid{"mhartid", 0}; + cci::cci_param plugins{"plugins", ""}; + core_complex(sc_core::sc_module_name const& name); #else @@ -122,6 +127,8 @@ public: scml_property mhartid{"mhartid", 0}; + scml_property plugins{"plugins", ""}; + core_complex(sc_core::sc_module_name const& name) : sc_module(name) , local_irq_i{"local_irq_i", 16} @@ -185,6 +192,8 @@ protected: std::unique_ptr t2t; private: void init(); + std::vector plugin_list; + }; } /* namespace SiFive */ } /* namespace sysc */ diff --git a/softfloat/build/Linux-x86_64-GCC/platform.h b/softfloat/build/Linux-x86_64-GCC/platform.h index 337ca99..92c3044 100644 --- a/softfloat/build/Linux-x86_64-GCC/platform.h +++ b/softfloat/build/Linux-x86_64-GCC/platform.h @@ -49,7 +49,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. /*---------------------------------------------------------------------------- *----------------------------------------------------------------------------*/ +#ifdef __GNUC__ #define SOFTFLOAT_BUILTIN_CLZ 1 #define SOFTFLOAT_INTRINSIC_INT128 1 +#endif #include "opts-GCC.h" diff --git a/src/iss/tgc_c.cpp b/src/iss/tgc_c.cpp index 31ac7b7..b5e8fed 100644 --- a/src/iss/tgc_c.cpp +++ b/src/iss/tgc_c.cpp @@ -39,10 +39,10 @@ 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_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; tgc_c::tgc_c() { reg.icount = 0; @@ -51,7 +51,9 @@ tgc_c::tgc_c() { tgc_c::~tgc_c() = default; void tgc_c::reset(uint64_t address) { - for(size_t i=0; i::NUM_REGS; ++i) set_reg(i, std::vector(sizeof(traits::reg_t),0)); + auto base_ptr = reinterpret_cast::reg_t*>(get_regs_base_ptr()); + for(size_t i=0; i::NUM_REGS; ++i) + *(base_ptr+i)=0; reg.PC=address; reg.NEXT_PC=reg.PC; reg.PRIV=0x3; diff --git a/src/main.cpp b/src/main.cpp index ac139d1..358d4a1 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -49,12 +49,21 @@ using tgc_b_plat_type = iss::arch::riscv_hart_m_p; #include "iss/arch/tgc_d.h" using tgc_d_plat_type = iss::arch::riscv_hart_mu_p; #endif +#ifdef CORE_TGC_D_XRB_MAC +#include "iss/arch/riscv_hart_mu_p.h" +#include "iss/arch/tgc_d_xrb_mac.h" +using tgc_d_xrb_mac_plat_type = iss::arch::riscv_hart_mu_p; +#endif #ifdef WITH_LLVM #include #endif #include #include #include +#include +#if defined(HAS_LUA) +#include +#endif namespace po = boost::program_options; @@ -138,9 +147,15 @@ int main(int argc, char *argv[]) { std::tie(cpu, vm) = iss::create_cpu(clim["backend"].as(), clim["gdb-port"].as()); } else +#endif +#ifdef CORE_TGC_D_XRB_MAC + if (isa_opt == "tgc_d_xrb_mac") { + std::tie(cpu, vm) = + iss::create_cpu(clim["backend"].as(), clim["gdb-port"].as()); + } else #endif { - LOG(ERROR) << "Illegal argument value for '--isa': " << clim["isa"].as() << std::endl; + LOG(ERR) << "Illegal argument value for '--isa': " << clim["isa"].as() << std::endl; return 127; } if (clim.count("plugin")) { @@ -161,8 +176,16 @@ int main(int argc, char *argv[]) { vm->register_plugin(*ce_plugin); plugin_list.push_back(ce_plugin); } else { - LOG(ERROR) << "Unknown plugin name: " << plugin_name << ", valid names are 'ce', 'ic'" << std::endl; - return 127; + std::array a{{filename.c_str()}}; + iss::plugin::loader l(plugin_name, {{"initPlugin"}}); + auto* plugin = l.call_function("initPlugin", a.size(), a.data()); + if(plugin){ + vm->register_plugin(*plugin); + plugin_list.push_back(plugin); + } else { + LOG(ERR) << "Unknown plugin name: " << plugin_name << ", valid names are 'ce', 'ic'" << std::endl; + return 127; + } } } } @@ -196,7 +219,7 @@ int main(int argc, char *argv[]) { auto cycles = clim["instructions"].as(); res = vm->start(cycles, dump); } catch (std::exception &e) { - LOG(ERROR) << "Unhandled Exception reached the top of main: " << e.what() << ", application will now exit" + LOG(ERR) << "Unhandled Exception reached the top of main: " << e.what() << ", application will now exit" << std::endl; res = 2; } diff --git a/src/plugin/GCOV.cpp b/src/plugin/GCOV.cpp deleted file mode 100644 index 6ce6440..0000000 --- a/src/plugin/GCOV.cpp +++ /dev/null @@ -1,821 +0,0 @@ -//===- GCOV.cpp - LLVM coverage tool --------------------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// GCOV implements the interface to read and write coverage files that use -// 'gcov' format. -// -//===----------------------------------------------------------------------===// - -#include "GCOV.h" -#include "llvm/ADT/STLExtras.h" -#include "llvm/Support/Debug.h" -#include "llvm/Support/FileSystem.h" -#include "llvm/Support/Format.h" -#include "llvm/Support/Path.h" -#include "llvm/Support/raw_ostream.h" -#include -#include - -using namespace llvm; - -//===----------------------------------------------------------------------===// -// GCOVFile implementation. - -/// readGCNO - Read GCNO buffer. -bool GCOVFile::readGCNO(GCOVBuffer &Buffer) { - if (!Buffer.readGCNOFormat()) - return false; - if (!Buffer.readGCOVVersion(Version)) - return false; - - if (!Buffer.readInt(Checksum)) - return false; - while (true) { - if (!Buffer.readFunctionTag()) - break; - auto GFun = make_unique(*this); - if (!GFun->readGCNO(Buffer, Version)) - return false; - Functions.push_back(std::move(GFun)); - } - - GCNOInitialized = true; - return true; -} - -/// readGCDA - Read GCDA buffer. It is required that readGCDA() can only be -/// called after readGCNO(). -bool GCOVFile::readGCDA(GCOVBuffer &Buffer) { - assert(GCNOInitialized && "readGCDA() can only be called after readGCNO()"); - if (!Buffer.readGCDAFormat()) - return false; - GCOV::GCOVVersion GCDAVersion; - if (!Buffer.readGCOVVersion(GCDAVersion)) - return false; - if (Version != GCDAVersion) { - errs() << "GCOV versions do not match.\n"; - return false; - } - - uint32_t GCDAChecksum; - if (!Buffer.readInt(GCDAChecksum)) - return false; - if (Checksum != GCDAChecksum) { - errs() << "File checksums do not match: " << Checksum - << " != " << GCDAChecksum << ".\n"; - return false; - } - for (size_t i = 0, e = Functions.size(); i < e; ++i) { - if (!Buffer.readFunctionTag()) { - errs() << "Unexpected number of functions.\n"; - return false; - } - if (!Functions[i]->readGCDA(Buffer, Version)) - return false; - } - if (Buffer.readObjectTag()) { - uint32_t Length; - uint32_t Dummy; - if (!Buffer.readInt(Length)) - return false; - if (!Buffer.readInt(Dummy)) - return false; // checksum - if (!Buffer.readInt(Dummy)) - return false; // num - if (!Buffer.readInt(RunCount)) - return false; - Buffer.advanceCursor(Length - 3); - } - while (Buffer.readProgramTag()) { - uint32_t Length; - if (!Buffer.readInt(Length)) - return false; - Buffer.advanceCursor(Length); - ++ProgramCount; - } - - return true; -} - -void GCOVFile::print(raw_ostream &OS) const { - for (const auto &FPtr : Functions) - FPtr->print(OS); -} - -#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) -/// dump - Dump GCOVFile content to dbgs() for debugging purposes. -LLVM_DUMP_METHOD void GCOVFile::dump() const { - print(dbgs()); -} -#endif - -/// collectLineCounts - Collect line counts. This must be used after -/// reading .gcno and .gcda files. -void GCOVFile::collectLineCounts(FileInfo &FI) { - for (const auto &FPtr : Functions) - FPtr->collectLineCounts(FI); - FI.setRunCount(RunCount); - FI.setProgramCount(ProgramCount); -} - -//===----------------------------------------------------------------------===// -// GCOVFunction implementation. - -/// readGCNO - Read a function from the GCNO buffer. Return false if an error -/// occurs. -bool GCOVFunction::readGCNO(GCOVBuffer &Buff, GCOV::GCOVVersion Version) { - uint32_t Dummy; - if (!Buff.readInt(Dummy)) - return false; // Function header length - if (!Buff.readInt(Ident)) - return false; - if (!Buff.readInt(Checksum)) - return false; - if (Version != GCOV::V402) { - uint32_t CfgChecksum; - if (!Buff.readInt(CfgChecksum)) - return false; - if (Parent.getChecksum() != CfgChecksum) { - errs() << "File checksums do not match: " << Parent.getChecksum() - << " != " << CfgChecksum << " in (" << Name << ").\n"; - return false; - } - } - if (!Buff.readString(Name)) - return false; - if (!Buff.readString(Filename)) - return false; - if (!Buff.readInt(LineNumber)) - return false; - - // read blocks. - if (!Buff.readBlockTag()) { - errs() << "Block tag not found.\n"; - return false; - } - uint32_t BlockCount; - if (!Buff.readInt(BlockCount)) - return false; - for (uint32_t i = 0, e = BlockCount; i != e; ++i) { - if (!Buff.readInt(Dummy)) - return false; // Block flags; - Blocks.push_back(make_unique(*this, i)); - } - - // read edges. - while (Buff.readEdgeTag()) { - uint32_t EdgeCount; - if (!Buff.readInt(EdgeCount)) - return false; - EdgeCount = (EdgeCount - 1) / 2; - uint32_t BlockNo; - if (!Buff.readInt(BlockNo)) - return false; - if (BlockNo >= BlockCount) { - errs() << "Unexpected block number: " << BlockNo << " (in " << Name - << ").\n"; - return false; - } - for (uint32_t i = 0, e = EdgeCount; i != e; ++i) { - uint32_t Dst; - if (!Buff.readInt(Dst)) - return false; - Edges.push_back(make_unique(*Blocks[BlockNo], *Blocks[Dst])); - GCOVEdge *Edge = Edges.back().get(); - Blocks[BlockNo]->addDstEdge(Edge); - Blocks[Dst]->addSrcEdge(Edge); - if (!Buff.readInt(Dummy)) - return false; // Edge flag - } - } - - // read line table. - while (Buff.readLineTag()) { - uint32_t LineTableLength; - // Read the length of this line table. - if (!Buff.readInt(LineTableLength)) - return false; - uint32_t EndPos = Buff.getCursor() + LineTableLength * 4; - uint32_t BlockNo; - // Read the block number this table is associated with. - if (!Buff.readInt(BlockNo)) - return false; - if (BlockNo >= BlockCount) { - errs() << "Unexpected block number: " << BlockNo << " (in " << Name - << ").\n"; - return false; - } - GCOVBlock &Block = *Blocks[BlockNo]; - // Read the word that pads the beginning of the line table. This may be a - // flag of some sort, but seems to always be zero. - if (!Buff.readInt(Dummy)) - return false; - - // Line information starts here and continues up until the last word. - if (Buff.getCursor() != (EndPos - sizeof(uint32_t))) { - StringRef F; - // Read the source file name. - if (!Buff.readString(F)) - return false; - if (Filename != F) { - errs() << "Multiple sources for a single basic block: " << Filename - << " != " << F << " (in " << Name << ").\n"; - return false; - } - // Read lines up to, but not including, the null terminator. - while (Buff.getCursor() < (EndPos - 2 * sizeof(uint32_t))) { - uint32_t Line; - if (!Buff.readInt(Line)) - return false; - // Line 0 means this instruction was injected by the compiler. Skip it. - if (!Line) - continue; - Block.addLine(Line); - } - // Read the null terminator. - if (!Buff.readInt(Dummy)) - return false; - } - // The last word is either a flag or padding, it isn't clear which. Skip - // over it. - if (!Buff.readInt(Dummy)) - return false; - } - return true; -} - -/// readGCDA - Read a function from the GCDA buffer. Return false if an error -/// occurs. -bool GCOVFunction::readGCDA(GCOVBuffer &Buff, GCOV::GCOVVersion Version) { - uint32_t HeaderLength; - if (!Buff.readInt(HeaderLength)) - return false; // Function header length - - uint64_t EndPos = Buff.getCursor() + HeaderLength * sizeof(uint32_t); - - uint32_t GCDAIdent; - if (!Buff.readInt(GCDAIdent)) - return false; - if (Ident != GCDAIdent) { - errs() << "Function identifiers do not match: " << Ident - << " != " << GCDAIdent << " (in " << Name << ").\n"; - return false; - } - - uint32_t GCDAChecksum; - if (!Buff.readInt(GCDAChecksum)) - return false; - if (Checksum != GCDAChecksum) { - errs() << "Function checksums do not match: " << Checksum - << " != " << GCDAChecksum << " (in " << Name << ").\n"; - return false; - } - - uint32_t CfgChecksum; - if (Version != GCOV::V402) { - if (!Buff.readInt(CfgChecksum)) - return false; - if (Parent.getChecksum() != CfgChecksum) { - errs() << "File checksums do not match: " << Parent.getChecksum() - << " != " << CfgChecksum << " (in " << Name << ").\n"; - return false; - } - } - - if (Buff.getCursor() < EndPos) { - StringRef GCDAName; - if (!Buff.readString(GCDAName)) - return false; - if (Name != GCDAName) { - errs() << "Function names do not match: " << Name << " != " << GCDAName - << ".\n"; - return false; - } - } - - if (!Buff.readArcTag()) { - errs() << "Arc tag not found (in " << Name << ").\n"; - return false; - } - - uint32_t Count; - if (!Buff.readInt(Count)) - return false; - Count /= 2; - - // This for loop adds the counts for each block. A second nested loop is - // required to combine the edge counts that are contained in the GCDA file. - for (uint32_t BlockNo = 0; Count > 0; ++BlockNo) { - // The last block is always reserved for exit block - if (BlockNo >= Blocks.size()) { - errs() << "Unexpected number of edges (in " << Name << ").\n"; - return false; - } - if (BlockNo == Blocks.size() - 1) - errs() << "(" << Name << ") has arcs from exit block.\n"; - GCOVBlock &Block = *Blocks[BlockNo]; - for (size_t EdgeNo = 0, End = Block.getNumDstEdges(); EdgeNo < End; - ++EdgeNo) { - if (Count == 0) { - errs() << "Unexpected number of edges (in " << Name << ").\n"; - return false; - } - uint64_t ArcCount; - if (!Buff.readInt64(ArcCount)) - return false; - Block.addCount(EdgeNo, ArcCount); - --Count; - } - Block.sortDstEdges(); - } - return true; -} - -/// getEntryCount - Get the number of times the function was called by -/// retrieving the entry block's count. -uint64_t GCOVFunction::getEntryCount() const { - return Blocks.front()->getCount(); -} - -/// getExitCount - Get the number of times the function returned by retrieving -/// the exit block's count. -uint64_t GCOVFunction::getExitCount() const { - return Blocks.back()->getCount(); -} - -void GCOVFunction::print(raw_ostream &OS) const { - OS << "===== " << Name << " (" << Ident << ") @ " << Filename << ":" - << LineNumber << "\n"; - for (const auto &Block : Blocks) - Block->print(OS); -} - -#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) -/// dump - Dump GCOVFunction content to dbgs() for debugging purposes. -LLVM_DUMP_METHOD void GCOVFunction::dump() const { - print(dbgs()); -} -#endif - -/// collectLineCounts - Collect line counts. This must be used after -/// reading .gcno and .gcda files. -void GCOVFunction::collectLineCounts(FileInfo &FI) { - // If the line number is zero, this is a function that doesn't actually appear - // in the source file, so there isn't anything we can do with it. - if (LineNumber == 0) - return; - - for (const auto &Block : Blocks) - Block->collectLineCounts(FI); - FI.addFunctionLine(Filename, LineNumber, this); -} - -//===----------------------------------------------------------------------===// -// GCOVBlock implementation. - -/// ~GCOVBlock - Delete GCOVBlock and its content. -GCOVBlock::~GCOVBlock() { - SrcEdges.clear(); - DstEdges.clear(); - Lines.clear(); -} - -/// addCount - Add to block counter while storing the edge count. If the -/// destination has no outgoing edges, also update that block's count too. -void GCOVBlock::addCount(size_t DstEdgeNo, uint64_t N) { - assert(DstEdgeNo < DstEdges.size()); // up to caller to ensure EdgeNo is valid - DstEdges[DstEdgeNo]->Count = N; - Counter += N; - if (!DstEdges[DstEdgeNo]->Dst.getNumDstEdges()) - DstEdges[DstEdgeNo]->Dst.Counter += N; -} - -/// sortDstEdges - Sort destination edges by block number, nop if already -/// sorted. This is required for printing branch info in the correct order. -void GCOVBlock::sortDstEdges() { - if (!DstEdgesAreSorted) { - SortDstEdgesFunctor SortEdges; - std::stable_sort(DstEdges.begin(), DstEdges.end(), SortEdges); - } -} - -/// collectLineCounts - Collect line counts. This must be used after -/// reading .gcno and .gcda files. -void GCOVBlock::collectLineCounts(FileInfo &FI) { - for (uint32_t N : Lines) - FI.addBlockLine(Parent.getFilename(), N, this); -} - -void GCOVBlock::print(raw_ostream &OS) const { - OS << "Block : " << Number << " Counter : " << Counter << "\n"; - if (!SrcEdges.empty()) { - OS << "\tSource Edges : "; - for (const GCOVEdge *Edge : SrcEdges) - OS << Edge->Src.Number << " (" << Edge->Count << "), "; - OS << "\n"; - } - if (!DstEdges.empty()) { - OS << "\tDestination Edges : "; - for (const GCOVEdge *Edge : DstEdges) - OS << Edge->Dst.Number << " (" << Edge->Count << "), "; - OS << "\n"; - } - if (!Lines.empty()) { - OS << "\tLines : "; - for (uint32_t N : Lines) - OS << (N) << ","; - OS << "\n"; - } -} - -#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) -/// dump - Dump GCOVBlock content to dbgs() for debugging purposes. -LLVM_DUMP_METHOD void GCOVBlock::dump() const { - print(dbgs()); -} -#endif - -//===----------------------------------------------------------------------===// -// FileInfo implementation. - -// Safe integer division, returns 0 if numerator is 0. -static uint32_t safeDiv(uint64_t Numerator, uint64_t Divisor) { - if (!Numerator) - return 0; - return Numerator / Divisor; -} - -// This custom division function mimics gcov's branch ouputs: -// - Round to closest whole number -// - Only output 0% or 100% if it's exactly that value -static uint32_t branchDiv(uint64_t Numerator, uint64_t Divisor) { - if (!Numerator) - return 0; - if (Numerator == Divisor) - return 100; - - uint8_t Res = (Numerator * 100 + Divisor / 2) / Divisor; - if (Res == 0) - return 1; - if (Res == 100) - return 99; - return Res; -} - -namespace { -struct formatBranchInfo { - formatBranchInfo(const GCOV::Options &Options, uint64_t Count, uint64_t Total) - : Options(Options), Count(Count), Total(Total) {} - - void print(raw_ostream &OS) const { - if (!Total) - OS << "never executed"; - else if (Options.BranchCount) - OS << "taken " << Count; - else - OS << "taken " << branchDiv(Count, Total) << "%"; - } - - const GCOV::Options &Options; - uint64_t Count; - uint64_t Total; -}; - -static raw_ostream &operator<<(raw_ostream &OS, const formatBranchInfo &FBI) { - FBI.print(OS); - return OS; -} - -class LineConsumer { - std::unique_ptr Buffer; - StringRef Remaining; - -public: - LineConsumer(StringRef Filename) { - ErrorOr> BufferOrErr = - MemoryBuffer::getFileOrSTDIN(Filename); - if (std::error_code EC = BufferOrErr.getError()) { - errs() << Filename << ": " << EC.message() << "\n"; - Remaining = ""; - } else { - Buffer = std::move(BufferOrErr.get()); - Remaining = Buffer->getBuffer(); - } - } - bool empty() { return Remaining.empty(); } - void printNext(raw_ostream &OS, uint32_t LineNum) { - StringRef Line; - if (empty()) - Line = "/*EOF*/"; - else - std::tie(Line, Remaining) = Remaining.split("\n"); - OS << format("%5u:", LineNum) << Line << "\n"; - } -}; -} // end anonymous namespace - -/// Convert a path to a gcov filename. If PreservePaths is true, this -/// translates "/" to "#", ".." to "^", and drops ".", to match gcov. -static std::string mangleCoveragePath(StringRef Filename, bool PreservePaths) { - if (!PreservePaths) - return sys::path::filename(Filename).str(); - - // This behaviour is defined by gcov in terms of text replacements, so it's - // not likely to do anything useful on filesystems with different textual - // conventions. - llvm::SmallString<256> Result(""); - StringRef::iterator I, S, E; - for (I = S = Filename.begin(), E = Filename.end(); I != E; ++I) { - if (*I != '/') - continue; - - if (I - S == 1 && *S == '.') { - // ".", the current directory, is skipped. - } else if (I - S == 2 && *S == '.' && *(S + 1) == '.') { - // "..", the parent directory, is replaced with "^". - Result.append("^#"); - } else { - if (S < I) - // Leave other components intact, - Result.append(S, I); - // And separate with "#". - Result.push_back('#'); - } - S = I + 1; - } - - if (S < I) - Result.append(S, I); - return Result.str(); -} - -std::string FileInfo::getCoveragePath(StringRef Filename, - StringRef MainFilename) { - if (Options.NoOutput) - // This is probably a bug in gcov, but when -n is specified, paths aren't - // mangled at all, and the -l and -p options are ignored. Here, we do the - // same. - return Filename; - - std::string CoveragePath; - if (Options.LongFileNames && !Filename.equals(MainFilename)) - CoveragePath = - mangleCoveragePath(MainFilename, Options.PreservePaths) + "##"; - CoveragePath += mangleCoveragePath(Filename, Options.PreservePaths) + ".gcov"; - return CoveragePath; -} - -std::unique_ptr -FileInfo::openCoveragePath(StringRef CoveragePath) { - if (Options.NoOutput) - return llvm::make_unique(); - - std::error_code EC; - auto OS = llvm::make_unique(CoveragePath, EC, - sys::fs::F_Text); - if (EC) { - errs() << EC.message() << "\n"; - return llvm::make_unique(); - } - return std::move(OS); -} - -/// print - Print source files with collected line count information. -void FileInfo::print(raw_ostream &InfoOS, StringRef MainFilename, - StringRef GCNOFile, StringRef GCDAFile) { - SmallVector Filenames; - for (const auto &LI : LineInfo) - Filenames.push_back(LI.first()); - std::sort(Filenames.begin(), Filenames.end()); - - for (StringRef Filename : Filenames) { - auto AllLines = LineConsumer(Filename); - - std::string CoveragePath = getCoveragePath(Filename, MainFilename); - std::unique_ptr CovStream = openCoveragePath(CoveragePath); - raw_ostream &CovOS = *CovStream; - - CovOS << " -: 0:Source:" << Filename << "\n"; - CovOS << " -: 0:Graph:" << GCNOFile << "\n"; - CovOS << " -: 0:Data:" << GCDAFile << "\n"; - CovOS << " -: 0:Runs:" << RunCount << "\n"; - CovOS << " -: 0:Programs:" << ProgramCount << "\n"; - - const LineData &Line = LineInfo[Filename]; - GCOVCoverage FileCoverage(Filename); - for (uint32_t LineIndex = 0; LineIndex < Line.LastLine || !AllLines.empty(); - ++LineIndex) { - if (Options.BranchInfo) { - FunctionLines::const_iterator FuncsIt = Line.Functions.find(LineIndex); - if (FuncsIt != Line.Functions.end()) - printFunctionSummary(CovOS, FuncsIt->second); - } - - BlockLines::const_iterator BlocksIt = Line.Blocks.find(LineIndex); - if (BlocksIt == Line.Blocks.end()) { - // No basic blocks are on this line. Not an executable line of code. - CovOS << " -:"; - AllLines.printNext(CovOS, LineIndex + 1); - } else { - const BlockVector &Blocks = BlocksIt->second; - - // Add up the block counts to form line counts. - DenseMap LineExecs; - uint64_t LineCount = 0; - for (const GCOVBlock *Block : Blocks) { - if (Options.AllBlocks) { - // Only take the highest block count for that line. - uint64_t BlockCount = Block->getCount(); - LineCount = LineCount > BlockCount ? LineCount : BlockCount; - } else { - // Sum up all of the block counts. - LineCount += Block->getCount(); - } - - if (Options.FuncCoverage) { - // This is a slightly convoluted way to most accurately gather line - // statistics for functions. Basically what is happening is that we - // don't want to count a single line with multiple blocks more than - // once. However, we also don't simply want to give the total line - // count to every function that starts on the line. Thus, what is - // happening here are two things: - // 1) Ensure that the number of logical lines is only incremented - // once per function. - // 2) If there are multiple blocks on the same line, ensure that the - // number of lines executed is incremented as long as at least - // one of the blocks are executed. - const GCOVFunction *Function = &Block->getParent(); - if (FuncCoverages.find(Function) == FuncCoverages.end()) { - std::pair KeyValue( - Function, GCOVCoverage(Function->getName())); - FuncCoverages.insert(KeyValue); - } - GCOVCoverage &FuncCoverage = FuncCoverages.find(Function)->second; - - if (LineExecs.find(Function) == LineExecs.end()) { - if (Block->getCount()) { - ++FuncCoverage.LinesExec; - LineExecs[Function] = true; - } else { - LineExecs[Function] = false; - } - ++FuncCoverage.LogicalLines; - } else if (!LineExecs[Function] && Block->getCount()) { - ++FuncCoverage.LinesExec; - LineExecs[Function] = true; - } - } - } - - if (LineCount == 0) - CovOS << " #####:"; - else { - CovOS << format("%9" PRIu64 ":", LineCount); - ++FileCoverage.LinesExec; - } - ++FileCoverage.LogicalLines; - - AllLines.printNext(CovOS, LineIndex + 1); - - uint32_t BlockNo = 0; - uint32_t EdgeNo = 0; - for (const GCOVBlock *Block : Blocks) { - // Only print block and branch information at the end of the block. - if (Block->getLastLine() != LineIndex + 1) - continue; - if (Options.AllBlocks) - printBlockInfo(CovOS, *Block, LineIndex, BlockNo); - if (Options.BranchInfo) { - size_t NumEdges = Block->getNumDstEdges(); - if (NumEdges > 1) - printBranchInfo(CovOS, *Block, FileCoverage, EdgeNo); - else if (Options.UncondBranch && NumEdges == 1) - printUncondBranchInfo(CovOS, EdgeNo, - (*Block->dst_begin())->Count); - } - } - } - } - FileCoverages.push_back(std::make_pair(CoveragePath, FileCoverage)); - } - - // FIXME: There is no way to detect calls given current instrumentation. - if (Options.FuncCoverage) - printFuncCoverage(InfoOS); - printFileCoverage(InfoOS); -} - -/// printFunctionSummary - Print function and block summary. -void FileInfo::printFunctionSummary(raw_ostream &OS, - const FunctionVector &Funcs) const { - for (const GCOVFunction *Func : Funcs) { - uint64_t EntryCount = Func->getEntryCount(); - uint32_t BlocksExec = 0; - for (const GCOVBlock &Block : Func->blocks()) - if (Block.getNumDstEdges() && Block.getCount()) - ++BlocksExec; - - OS << "function " << Func->getName() << " called " << EntryCount - << " returned " << safeDiv(Func->getExitCount() * 100, EntryCount) - << "% blocks executed " - << safeDiv(BlocksExec * 100, Func->getNumBlocks() - 1) << "%\n"; - } -} - -/// printBlockInfo - Output counts for each block. -void FileInfo::printBlockInfo(raw_ostream &OS, const GCOVBlock &Block, - uint32_t LineIndex, uint32_t &BlockNo) const { - if (Block.getCount() == 0) - OS << " $$$$$:"; - else - OS << format("%9" PRIu64 ":", Block.getCount()); - OS << format("%5u-block %2u\n", LineIndex + 1, BlockNo++); -} - -/// printBranchInfo - Print conditional branch probabilities. -void FileInfo::printBranchInfo(raw_ostream &OS, const GCOVBlock &Block, - GCOVCoverage &Coverage, uint32_t &EdgeNo) { - SmallVector BranchCounts; - uint64_t TotalCounts = 0; - for (const GCOVEdge *Edge : Block.dsts()) { - BranchCounts.push_back(Edge->Count); - TotalCounts += Edge->Count; - if (Block.getCount()) - ++Coverage.BranchesExec; - if (Edge->Count) - ++Coverage.BranchesTaken; - ++Coverage.Branches; - - if (Options.FuncCoverage) { - const GCOVFunction *Function = &Block.getParent(); - GCOVCoverage &FuncCoverage = FuncCoverages.find(Function)->second; - if (Block.getCount()) - ++FuncCoverage.BranchesExec; - if (Edge->Count) - ++FuncCoverage.BranchesTaken; - ++FuncCoverage.Branches; - } - } - - for (uint64_t N : BranchCounts) - OS << format("branch %2u ", EdgeNo++) - << formatBranchInfo(Options, N, TotalCounts) << "\n"; -} - -/// printUncondBranchInfo - Print unconditional branch probabilities. -void FileInfo::printUncondBranchInfo(raw_ostream &OS, uint32_t &EdgeNo, - uint64_t Count) const { - OS << format("unconditional %2u ", EdgeNo++) - << formatBranchInfo(Options, Count, Count) << "\n"; -} - -// printCoverage - Print generic coverage info used by both printFuncCoverage -// and printFileCoverage. -void FileInfo::printCoverage(raw_ostream &OS, - const GCOVCoverage &Coverage) const { - OS << format("Lines executed:%.2f%% of %u\n", - double(Coverage.LinesExec) * 100 / Coverage.LogicalLines, - Coverage.LogicalLines); - if (Options.BranchInfo) { - if (Coverage.Branches) { - OS << format("Branches executed:%.2f%% of %u\n", - double(Coverage.BranchesExec) * 100 / Coverage.Branches, - Coverage.Branches); - OS << format("Taken at least once:%.2f%% of %u\n", - double(Coverage.BranchesTaken) * 100 / Coverage.Branches, - Coverage.Branches); - } else { - OS << "No branches\n"; - } - OS << "No calls\n"; // to be consistent with gcov - } -} - -// printFuncCoverage - Print per-function coverage info. -void FileInfo::printFuncCoverage(raw_ostream &OS) const { - for (const auto &FC : FuncCoverages) { - const GCOVCoverage &Coverage = FC.second; - OS << "Function '" << Coverage.Name << "'\n"; - printCoverage(OS, Coverage); - OS << "\n"; - } -} - -// printFileCoverage - Print per-file coverage info. -void FileInfo::printFileCoverage(raw_ostream &OS) const { - for (const auto &FC : FileCoverages) { - const std::string &Filename = FC.first; - const GCOVCoverage &Coverage = FC.second; - OS << "File '" << Coverage.Name << "'\n"; - printCoverage(OS, Coverage); - if (!Options.NoOutput) - OS << Coverage.Name << ":creating '" << Filename << "'\n"; - OS << "\n"; - } -} diff --git a/src/plugin/GCOV.h b/src/plugin/GCOV.h deleted file mode 100644 index 497f80b..0000000 --- a/src/plugin/GCOV.h +++ /dev/null @@ -1,460 +0,0 @@ -//===- GCOV.h - LLVM coverage tool ------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This header provides the interface to read and write coverage files that -// use 'gcov' format. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_PROFILEDATA_GCOV_H -#define LLVM_PROFILEDATA_GCOV_H - -#include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/MapVector.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/StringMap.h" -#include "llvm/ADT/StringRef.h" -#include "llvm/ADT/iterator.h" -#include "llvm/ADT/iterator_range.h" -#include "llvm/Support/MemoryBuffer.h" -#include "llvm/Support/raw_ostream.h" -#include -#include -#include -#include -#include -#include - -namespace llvm { - -class GCOVFunction; -class GCOVBlock; -class FileInfo; - -namespace GCOV { - -enum GCOVVersion { V402, V404, V704 }; - -/// \brief A struct for passing gcov options between functions. -struct Options { - Options(bool A, bool B, bool C, bool F, bool P, bool U, bool L, bool N) - : AllBlocks(A), BranchInfo(B), BranchCount(C), FuncCoverage(F), - PreservePaths(P), UncondBranch(U), LongFileNames(L), NoOutput(N) {} - - bool AllBlocks; - bool BranchInfo; - bool BranchCount; - bool FuncCoverage; - bool PreservePaths; - bool UncondBranch; - bool LongFileNames; - bool NoOutput; -}; - -} // end namespace GCOV - -/// GCOVBuffer - A wrapper around MemoryBuffer to provide GCOV specific -/// read operations. -class GCOVBuffer { -public: - GCOVBuffer(MemoryBuffer *B) : Buffer(B) {} - - /// readGCNOFormat - Check GCNO signature is valid at the beginning of buffer. - bool readGCNOFormat() { - StringRef File = Buffer->getBuffer().slice(0, 4); - if (File != "oncg") { - errs() << "Unexpected file type: " << File << ".\n"; - return false; - } - Cursor = 4; - return true; - } - - /// readGCDAFormat - Check GCDA signature is valid at the beginning of buffer. - bool readGCDAFormat() { - StringRef File = Buffer->getBuffer().slice(0, 4); - if (File != "adcg") { - errs() << "Unexpected file type: " << File << ".\n"; - return false; - } - Cursor = 4; - return true; - } - - /// readGCOVVersion - Read GCOV version. - bool readGCOVVersion(GCOV::GCOVVersion &Version) { - StringRef VersionStr = Buffer->getBuffer().slice(Cursor, Cursor + 4); - if (VersionStr == "*204") { - Cursor += 4; - Version = GCOV::V402; - return true; - } - if (VersionStr == "*404") { - Cursor += 4; - Version = GCOV::V404; - return true; - } - if (VersionStr == "*704") { - Cursor += 4; - Version = GCOV::V704; - return true; - } - errs() << "Unexpected version: " << VersionStr << ".\n"; - return false; - } - - /// readFunctionTag - If cursor points to a function tag then increment the - /// cursor and return true otherwise return false. - bool readFunctionTag() { - StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor + 4); - if (Tag.empty() || Tag[0] != '\0' || Tag[1] != '\0' || Tag[2] != '\0' || - Tag[3] != '\1') { - return false; - } - Cursor += 4; - return true; - } - - /// readBlockTag - If cursor points to a block tag then increment the - /// cursor and return true otherwise return false. - bool readBlockTag() { - StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor + 4); - if (Tag.empty() || Tag[0] != '\0' || Tag[1] != '\0' || Tag[2] != '\x41' || - Tag[3] != '\x01') { - return false; - } - Cursor += 4; - return true; - } - - /// readEdgeTag - If cursor points to an edge tag then increment the - /// cursor and return true otherwise return false. - bool readEdgeTag() { - StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor + 4); - if (Tag.empty() || Tag[0] != '\0' || Tag[1] != '\0' || Tag[2] != '\x43' || - Tag[3] != '\x01') { - return false; - } - Cursor += 4; - return true; - } - - /// readLineTag - If cursor points to a line tag then increment the - /// cursor and return true otherwise return false. - bool readLineTag() { - StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor + 4); - if (Tag.empty() || Tag[0] != '\0' || Tag[1] != '\0' || Tag[2] != '\x45' || - Tag[3] != '\x01') { - return false; - } - Cursor += 4; - return true; - } - - /// readArcTag - If cursor points to an gcda arc tag then increment the - /// cursor and return true otherwise return false. - bool readArcTag() { - StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor + 4); - if (Tag.empty() || Tag[0] != '\0' || Tag[1] != '\0' || Tag[2] != '\xa1' || - Tag[3] != '\1') { - return false; - } - Cursor += 4; - return true; - } - - /// readObjectTag - If cursor points to an object summary tag then increment - /// the cursor and return true otherwise return false. - bool readObjectTag() { - StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor + 4); - if (Tag.empty() || Tag[0] != '\0' || Tag[1] != '\0' || Tag[2] != '\0' || - Tag[3] != '\xa1') { - return false; - } - Cursor += 4; - return true; - } - - /// readProgramTag - If cursor points to a program summary tag then increment - /// the cursor and return true otherwise return false. - bool readProgramTag() { - StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor + 4); - if (Tag.empty() || Tag[0] != '\0' || Tag[1] != '\0' || Tag[2] != '\0' || - Tag[3] != '\xa3') { - return false; - } - Cursor += 4; - return true; - } - - bool readInt(uint32_t &Val) { - if (Buffer->getBuffer().size() < Cursor + 4) { - errs() << "Unexpected end of memory buffer: " << Cursor + 4 << ".\n"; - return false; - } - StringRef Str = Buffer->getBuffer().slice(Cursor, Cursor + 4); - Cursor += 4; - Val = *(const uint32_t *)(Str.data()); - return true; - } - - bool readInt64(uint64_t &Val) { - uint32_t Lo, Hi; - if (!readInt(Lo) || !readInt(Hi)) - return false; - Val = ((uint64_t)Hi << 32) | Lo; - return true; - } - - bool readString(StringRef &Str) { - uint32_t Len = 0; - // Keep reading until we find a non-zero length. This emulates gcov's - // behaviour, which appears to do the same. - while (Len == 0) - if (!readInt(Len)) - return false; - Len *= 4; - if (Buffer->getBuffer().size() < Cursor + Len) { - errs() << "Unexpected end of memory buffer: " << Cursor + Len << ".\n"; - return false; - } - Str = Buffer->getBuffer().slice(Cursor, Cursor + Len).split('\0').first; - Cursor += Len; - return true; - } - - uint64_t getCursor() const { return Cursor; } - void advanceCursor(uint32_t n) { Cursor += n * 4; } - -private: - MemoryBuffer *Buffer; - uint64_t Cursor = 0; -}; - -/// GCOVFile - Collects coverage information for one pair of coverage file -/// (.gcno and .gcda). -class GCOVFile { -public: - GCOVFile() = default; - - bool readGCNO(GCOVBuffer &Buffer); - bool readGCDA(GCOVBuffer &Buffer); - uint32_t getChecksum() const { return Checksum; } - void print(raw_ostream &OS) const; - void dump() const; - void collectLineCounts(FileInfo &FI); - -private: - bool GCNOInitialized = false; - GCOV::GCOVVersion Version; - uint32_t Checksum = 0; - SmallVector, 16> Functions; - uint32_t RunCount = 0; - uint32_t ProgramCount = 0; -}; - -/// GCOVEdge - Collects edge information. -struct GCOVEdge { - GCOVEdge(GCOVBlock &S, GCOVBlock &D) : Src(S), Dst(D) {} - - GCOVBlock &Src; - GCOVBlock &Dst; - uint64_t Count = 0; -}; - -/// GCOVFunction - Collects function information. -class GCOVFunction { -public: - using BlockIterator = pointee_iterator>::const_iterator>; - - GCOVFunction(GCOVFile &P) : Parent(P) {} - - bool readGCNO(GCOVBuffer &Buffer, GCOV::GCOVVersion Version); - bool readGCDA(GCOVBuffer &Buffer, GCOV::GCOVVersion Version); - StringRef getName() const { return Name; } - StringRef getFilename() const { return Filename; } - size_t getNumBlocks() const { return Blocks.size(); } - uint64_t getEntryCount() const; - uint64_t getExitCount() const; - - BlockIterator block_begin() const { return Blocks.begin(); } - BlockIterator block_end() const { return Blocks.end(); } - iterator_range blocks() const { - return make_range(block_begin(), block_end()); - } - - void print(raw_ostream &OS) const; - void dump() const; - void collectLineCounts(FileInfo &FI); - -private: - GCOVFile &Parent; - uint32_t Ident = 0; - uint32_t Checksum; - uint32_t LineNumber = 0; - StringRef Name; - StringRef Filename; - SmallVector, 16> Blocks; - SmallVector, 16> Edges; -}; - -/// GCOVBlock - Collects block information. -class GCOVBlock { - struct EdgeWeight { - EdgeWeight(GCOVBlock *D) : Dst(D) {} - - GCOVBlock *Dst; - uint64_t Count = 0; - }; - - struct SortDstEdgesFunctor { - bool operator()(const GCOVEdge *E1, const GCOVEdge *E2) { - return E1->Dst.Number < E2->Dst.Number; - } - }; - -public: - using EdgeIterator = SmallVectorImpl::const_iterator; - - GCOVBlock(GCOVFunction &P, uint32_t N) : Parent(P), Number(N) {} - ~GCOVBlock(); - - const GCOVFunction &getParent() const { return Parent; } - void addLine(uint32_t N) { Lines.push_back(N); } - uint32_t getLastLine() const { return Lines.back(); } - void addCount(size_t DstEdgeNo, uint64_t N); - uint64_t getCount() const { return Counter; } - - void addSrcEdge(GCOVEdge *Edge) { - assert(&Edge->Dst == this); // up to caller to ensure edge is valid - SrcEdges.push_back(Edge); - } - - void addDstEdge(GCOVEdge *Edge) { - assert(&Edge->Src == this); // up to caller to ensure edge is valid - // Check if adding this edge causes list to become unsorted. - if (DstEdges.size() && DstEdges.back()->Dst.Number > Edge->Dst.Number) - DstEdgesAreSorted = false; - DstEdges.push_back(Edge); - } - - size_t getNumSrcEdges() const { return SrcEdges.size(); } - size_t getNumDstEdges() const { return DstEdges.size(); } - void sortDstEdges(); - - EdgeIterator src_begin() const { return SrcEdges.begin(); } - EdgeIterator src_end() const { return SrcEdges.end(); } - iterator_range srcs() const { - return make_range(src_begin(), src_end()); - } - - EdgeIterator dst_begin() const { return DstEdges.begin(); } - EdgeIterator dst_end() const { return DstEdges.end(); } - iterator_range dsts() const { - return make_range(dst_begin(), dst_end()); - } - - void print(raw_ostream &OS) const; - void dump() const; - void collectLineCounts(FileInfo &FI); - -private: - GCOVFunction &Parent; - uint32_t Number; - uint64_t Counter = 0; - bool DstEdgesAreSorted = true; - SmallVector SrcEdges; - SmallVector DstEdges; - SmallVector Lines; -}; - -class FileInfo { - // It is unlikely--but possible--for multiple functions to be on the same - // line. - // Therefore this typedef allows LineData.Functions to store multiple - // functions - // per instance. This is rare, however, so optimize for the common case. - using FunctionVector = SmallVector; - using FunctionLines = DenseMap; - using BlockVector = SmallVector; - using BlockLines = DenseMap; - - struct LineData { - LineData() = default; - - BlockLines Blocks; - FunctionLines Functions; - uint32_t LastLine = 0; - }; - - struct GCOVCoverage { - GCOVCoverage(StringRef Name) : Name(Name) {} - - StringRef Name; - - uint32_t LogicalLines = 0; - uint32_t LinesExec = 0; - - uint32_t Branches = 0; - uint32_t BranchesExec = 0; - uint32_t BranchesTaken = 0; - }; - -public: - FileInfo(const GCOV::Options &Options) : Options(Options) {} - - void addBlockLine(StringRef Filename, uint32_t Line, const GCOVBlock *Block) { - if (Line > LineInfo[Filename].LastLine) - LineInfo[Filename].LastLine = Line; - LineInfo[Filename].Blocks[Line - 1].push_back(Block); - } - - void addFunctionLine(StringRef Filename, uint32_t Line, - const GCOVFunction *Function) { - if (Line > LineInfo[Filename].LastLine) - LineInfo[Filename].LastLine = Line; - LineInfo[Filename].Functions[Line - 1].push_back(Function); - } - - void setRunCount(uint32_t Runs) { RunCount = Runs; } - void setProgramCount(uint32_t Programs) { ProgramCount = Programs; } - void print(raw_ostream &OS, StringRef MainFilename, StringRef GCNOFile, - StringRef GCDAFile); - -private: - std::string getCoveragePath(StringRef Filename, StringRef MainFilename); - std::unique_ptr openCoveragePath(StringRef CoveragePath); - void printFunctionSummary(raw_ostream &OS, const FunctionVector &Funcs) const; - void printBlockInfo(raw_ostream &OS, const GCOVBlock &Block, - uint32_t LineIndex, uint32_t &BlockNo) const; - void printBranchInfo(raw_ostream &OS, const GCOVBlock &Block, - GCOVCoverage &Coverage, uint32_t &EdgeNo); - void printUncondBranchInfo(raw_ostream &OS, uint32_t &EdgeNo, - uint64_t Count) const; - - void printCoverage(raw_ostream &OS, const GCOVCoverage &Coverage) const; - void printFuncCoverage(raw_ostream &OS) const; - void printFileCoverage(raw_ostream &OS) const; - - const GCOV::Options &Options; - StringMap LineInfo; - uint32_t RunCount = 0; - uint32_t ProgramCount = 0; - - using FileCoverageList = SmallVector, 4>; - using FuncCoverageMap = MapVector; - - FileCoverageList FileCoverages; - FuncCoverageMap FuncCoverages; -}; - -} // end namespace llvm - -#endif // LLVM_SUPPORT_GCOV_H diff --git a/src/plugin/cycle_estimate.cpp b/src/plugin/cycle_estimate.cpp index 6abf77c..3aa856b 100644 --- a/src/plugin/cycle_estimate.cpp +++ b/src/plugin/cycle_estimate.cpp @@ -47,10 +47,10 @@ iss::plugin::cycle_estimate::cycle_estimate(std::string config_file_name) try { is >> root; } catch (Json::RuntimeError &e) { - LOG(ERROR) << "Could not parse input file " << config_file_name << ", reason: " << e.what(); + LOG(ERR) << "Could not parse input file " << config_file_name << ", reason: " << e.what(); } } else { - LOG(ERROR) << "Could not open input file " << config_file_name; + LOG(ERR) << "Could not open input file " << config_file_name; } } } @@ -77,7 +77,7 @@ bool iss::plugin::cycle_estimate::registration(const char* const version, vm_if& } } } else { - LOG(ERROR)<<"plugin cycle_estimate: could not find an entry for "<get_next_pc()-arch_instr->get_pc()) != (entry.size/8); - uint32_t delay = taken ? entry.taken : entry.not_taken; - if(delay>1) arch_instr->set_curr_instr_cycles(delay); + if (taken && entry.taken > 1) + arch_instr->set_curr_instr_cycles(entry.taken); + else if (entry.not_taken > 1) + arch_instr->set_curr_instr_cycles(entry.not_taken); } diff --git a/src/plugin/instruction_count.cpp b/src/plugin/instruction_count.cpp index 2f33d7c..aba30eb 100644 --- a/src/plugin/instruction_count.cpp +++ b/src/plugin/instruction_count.cpp @@ -46,10 +46,10 @@ iss::plugin::instruction_count::instruction_count(std::string config_file_name) try { is >> root; } catch (Json::RuntimeError &e) { - LOG(ERROR) << "Could not parse input file " << config_file_name << ", reason: " << e.what(); + LOG(ERR) << "Could not parse input file " << config_file_name << ", reason: " << e.what(); } } else { - LOG(ERROR) << "Could not open input file " << config_file_name; + LOG(ERR) << "Could not open input file " << config_file_name; } } } @@ -85,7 +85,7 @@ bool iss::plugin::instruction_count::registration(const char* const version, vm_ } rep_counts.resize(delays.size()); } else { - LOG(ERROR)<<"plugin instruction_count: could not find an entry for "< #include "sysc/core_complex.h" #ifdef CORE_TGC_B #include "iss/arch/riscv_hart_m_p.h" @@ -44,22 +52,25 @@ using tgc_c_plat_type = iss::arch::riscv_hart_m_p; #include "iss/arch/tgc_d.h" using tgc_d_plat_type = iss::arch::riscv_hart_mu_p; #endif -#include "iss/debugger/encoderdecoder.h" -#include "iss/debugger/gdb_session.h" -#include "iss/debugger/server.h" -#include "iss/debugger/target_adapter_if.h" -#include "iss/iss.h" -#include "iss/vm_types.h" -#include "scc/report.h" +#ifdef CORE_TGC_D_XRB_MAC +#include "iss/arch/riscv_hart_mu_p.h" +#include "iss/arch/tgc_d_xrb_mac.h" +using tgc_d_xrb_mac_plat_type = iss::arch::riscv_hart_mu_p; +#endif +#include +#include #include #include #include +#include +#include +// clang-format on #define STR(X) #X #define CREATE_CORE(CN) \ if (type == STR(CN)) { std::tie(cpu, vm) = create_core(backend, gdb_port, hart_id); } else -#ifdef WITH_SCV +#ifdef HAS_SCV #include #else #include @@ -72,6 +83,12 @@ using namespace scv_tr; #define GET_PROP_VALUE(P) P.getValue() #endif +#ifdef _MSC_VER +// not #if defined(_WIN32) || defined(_WIN64) because we have strncasecmp in mingw +#define strncasecmp _strnicmp +#define strcasecmp _stricmp +#endif + namespace sysc { namespace tgfs { using namespace std; @@ -285,9 +302,12 @@ public: #endif #ifdef CORE_TGC_D CREATE_CORE(tgc_d) +#endif +#ifdef CORE_TGC_D_XRB_MACD + CREATE_CORE(tgc_d_xrb_mac) #endif { - LOG(ERROR) << "Illegal argument value for core type: " << type << std::endl; + LOG(ERR) << "Illegal argument value for core type: " << type << std::endl; } auto *srv = debugger::server::get(); if (srv) tgt_adapter = srv->get_target(); @@ -364,6 +384,8 @@ void core_complex::init(){ core_complex::~core_complex(){ delete cpu; delete trc; + for (auto *p : plugin_list) + delete p; } void core_complex::trace(sc_trace_file *trf) const {} @@ -375,6 +397,37 @@ void core_complex::before_end_of_elaboration() { cpu->create_cpu(GET_PROP_VALUE(core_type), GET_PROP_VALUE(backend), GET_PROP_VALUE(gdb_server_port), GET_PROP_VALUE(mhartid)); sc_assert(cpu->vm!=nullptr); cpu->vm->setDisassEnabled(GET_PROP_VALUE(enable_disass) || trc->m_db != nullptr); + if (GET_PROP_VALUE(plugins).length()) { + auto p = util::split(GET_PROP_VALUE(plugins), ';'); + for (std::string const& opt_val : p) { + std::string plugin_name=opt_val; + std::string filename{"cycles.txt"}; + std::size_t found = opt_val.find('='); + if (found != std::string::npos) { + plugin_name = opt_val.substr(0, found); + filename = opt_val.substr(found + 1, opt_val.size()); + } + if (plugin_name == "ic") { + auto *plugin = new iss::plugin::instruction_count(filename); + cpu->vm->register_plugin(*plugin); + plugin_list.push_back(plugin); + } else if (plugin_name == "ce") { + auto *plugin = new iss::plugin::cycle_estimate(filename); + cpu->vm->register_plugin(*plugin); + plugin_list.push_back(plugin); + } else { + std::array a{{filename.c_str()}}; + iss::plugin::loader l(plugin_name, {{"initPlugin"}}); + auto* plugin = l.call_function("initPlugin", a.size(), a.data()); + if(plugin){ + cpu->vm->register_plugin(*plugin); + plugin_list.push_back(plugin); + } else + SCCERR(SCMOD) << "Unknown plugin '" << plugin_name << "' or plugin not found"; + } + } + } + } void core_complex::start_of_simulation() { diff --git a/src/vm/interp/vm_tgc_c.cpp b/src/vm/interp/vm_tgc_c.cpp index e142646..ad50b5a 100644 --- a/src/vm/interp/vm_tgc_c.cpp +++ b/src/vm/interp/vm_tgc_c.cpp @@ -64,7 +64,7 @@ public: using addr_t = typename super::addr_t; using reg_t = typename traits::reg_t; using mem_type_e = typename traits::mem_type_e; - + vm_impl(); vm_impl(ARCH &core, unsigned core_id = 0, unsigned cluster_id = 0); @@ -92,7 +92,10 @@ protected: // enum { MASK16 = 0b1111110001100011, MASK32 = 0b11111111111100000111000001111111 }; enum { MASK16 = 0b1111111111111111, MASK32 = 0b11111111111100000111000001111111 }; enum { EXTR_MASK16 = MASK16 >> 2, EXTR_MASK32 = MASK32 >> 2 }; - enum { LUT_SIZE = 1 << util::bit_count(EXTR_MASK32), LUT_SIZE_C = 1 << util::bit_count(EXTR_MASK16) }; + enum { + LUT_SIZE = 1 << util::bit_count(static_cast(EXTR_MASK32)), + LUT_SIZE_C = 1 << util::bit_count(static_cast(EXTR_MASK16)) + }; std::array lut; @@ -177,7 +180,7 @@ private: compile_func op; }; - const std::array instr_descr = {{ + const std::array instr_descr = {{ /* entries are: size, valid value, valid mask, function ptr */ /* instruction LUI */ {32, 0b00000000000000000000000000110111, 0b00000000000000000000000001111111, &this_class::__lui}, @@ -267,6 +270,8 @@ private: {32, 0b00110000001000000000000001110011, 0b11111111111111111111111111111111, &this_class::__mret}, /* instruction WFI */ {32, 0b00010000010100000000000001110011, 0b11111111111111111111111111111111, &this_class::__wfi}, + /* instruction DRET */ + {32, 0b01111011001000000000000001110011, 0b11111111111111111111111111111111, &this_class::__dret}, /* instruction CSRRW */ {32, 0b00000000000000000001000001110011, 0b00000000000000000111000001111111, &this_class::__csrrw}, /* instruction CSRRS */ @@ -279,6 +284,8 @@ private: {32, 0b00000000000000000110000001110011, 0b00000000000000000111000001111111, &this_class::__csrrsi}, /* instruction CSRRCI */ {32, 0b00000000000000000111000001110011, 0b00000000000000000111000001111111, &this_class::__csrrci}, + /* instruction FENCE_I */ + {32, 0b00000000000000000001000000001111, 0b00000000000000000111000001111111, &this_class::__fence_i}, /* instruction MUL */ {32, 0b00000010000000000000000000110011, 0b11111110000000000111000001111111, &this_class::__mul}, /* instruction MULH */ @@ -463,8 +470,13 @@ private: // execute instruction try { { - if(rd != 0) *(X+rd) = *PC + 4; - pc_assign(*NEXT_PC) = *PC + (int32_t)sext<21>(imm); + if(imm % traits::INSTR_ALIGNMENT) { + raise(0, 0); + } + else { + if(rd != 0) *(X+rd) = *PC + 4; + pc_assign(*NEXT_PC) = *PC + (int32_t)sext<21>(imm); + } } } catch(...){} // post execution stuff @@ -507,9 +519,14 @@ private: // execute instruction try { { - int32_t new_pc = *(X+rs1) + (int16_t)sext<12>(imm); - if(rd != 0) *(X+rd) = *PC + 4; - pc_assign(*NEXT_PC) = new_pc & ~ 0x1; + int32_t new_pc = (*(X+rs1) + (int16_t)sext<12>(imm)) & ~ 1; + if(new_pc % traits::INSTR_ALIGNMENT) { + raise(0, 0); + } + else { + if(rd != 0) *(X+rd) = *PC + 4; + pc_assign(*NEXT_PC) = new_pc & ~ 0x1; + } } } catch(...){} // post execution stuff @@ -551,7 +568,12 @@ private: *NEXT_PC = *PC + 4; // execute instruction try { - if(*(X+rs1) == *(X+rs2)) pc_assign(*NEXT_PC) = *PC + (int16_t)sext<13>(imm); + { + if(*(X+rs1) == *(X+rs2)) if(imm % traits::INSTR_ALIGNMENT) { + raise(0, 0); + } + else pc_assign(*NEXT_PC) = *PC + (int16_t)sext<13>(imm); + } } catch(...){} // post execution stuff if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 4); @@ -592,7 +614,12 @@ private: *NEXT_PC = *PC + 4; // execute instruction try { - if(*(X+rs1) != *(X+rs2)) pc_assign(*NEXT_PC) = *PC + (int16_t)sext<13>(imm); + { + if(*(X+rs1) != *(X+rs2)) if(imm % traits::INSTR_ALIGNMENT) { + raise(0, 0); + } + else pc_assign(*NEXT_PC) = *PC + (int16_t)sext<13>(imm); + } } catch(...){} // post execution stuff if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 5); @@ -633,7 +660,12 @@ private: *NEXT_PC = *PC + 4; // execute instruction try { - if((int32_t)*(X+rs1) < (int32_t)*(X+rs2)) pc_assign(*NEXT_PC) = *PC + (int16_t)sext<13>(imm); + { + if((int32_t)*(X+rs1) < (int32_t)*(X+rs2)) if(imm % traits::INSTR_ALIGNMENT) { + raise(0, 0); + } + else pc_assign(*NEXT_PC) = *PC + (int16_t)sext<13>(imm); + } } catch(...){} // post execution stuff if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 6); @@ -674,7 +706,12 @@ private: *NEXT_PC = *PC + 4; // execute instruction try { - if((int32_t)*(X+rs1) >= (int32_t)*(X+rs2)) pc_assign(*NEXT_PC) = *PC + (int16_t)sext<13>(imm); + { + if((int32_t)*(X+rs1) >= (int32_t)*(X+rs2)) if(imm % traits::INSTR_ALIGNMENT) { + raise(0, 0); + } + else pc_assign(*NEXT_PC) = *PC + (int16_t)sext<13>(imm); + } } catch(...){} // post execution stuff if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 7); @@ -715,7 +752,12 @@ private: *NEXT_PC = *PC + 4; // execute instruction try { - if(*(X+rs1) < *(X+rs2)) pc_assign(*NEXT_PC) = *PC + (int16_t)sext<13>(imm); + { + if(*(X+rs1) < *(X+rs2)) if(imm % traits::INSTR_ALIGNMENT) { + raise(0, 0); + } + else pc_assign(*NEXT_PC) = *PC + (int16_t)sext<13>(imm); + } } catch(...){} // post execution stuff if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 8); @@ -756,7 +798,12 @@ private: *NEXT_PC = *PC + 4; // execute instruction try { - if(*(X+rs1) >= *(X+rs2)) pc_assign(*NEXT_PC) = *PC + (int16_t)sext<13>(imm); + { + if(*(X+rs1) >= *(X+rs2)) if(imm % traits::INSTR_ALIGNMENT) { + raise(0, 0); + } + else pc_assign(*NEXT_PC) = *PC + (int16_t)sext<13>(imm); + } } catch(...){} // post execution stuff if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 9); @@ -2164,8 +2211,8 @@ private: return pc; } - /* instruction 44: CSRRW */ - compile_ret_t __csrrw(virt_addr_t& pc, code_word_t instr){ + /* instruction 44: DRET */ + compile_ret_t __dret(virt_addr_t& pc, code_word_t instr){ // pre execution stuff auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); auto NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); @@ -2173,6 +2220,50 @@ private: auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 44); + if(this->disass_enabled){ + /* generate console output when executing the command */ + this->core.disass_output(pc.val, "dret"); + + } + // used registers + auto* PRIV = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PRIV]); + + auto* DPC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::DPC]); + // calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + try { + { + if(*PRIV < 4) raise(0, 2); + else { + pc_assign(*NEXT_PC) = *DPC; + *PRIV &= 0x3; + } + } + } catch(...){} + // post execution stuff + if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 44); + // trap check + if(*trap_state!=0){ + super::core.enter_trap(*trap_state, pc.val, instr); + } else { + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::ICOUNT]))++; + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRET]))++; + } + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::CYCLE]))++; + pc.val=*NEXT_PC; + return pc; + } + + /* instruction 45: CSRRW */ + compile_ret_t __csrrw(virt_addr_t& pc, code_word_t instr){ + // pre execution stuff + auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); + auto NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); + *PC=*NEXT_PC; + auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); + *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); + if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 45); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint16_t csr = ((bit_sub<20,12>(instr))); @@ -2202,7 +2293,7 @@ private: } } catch(...){} // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 44); + if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 45); // trap check if(*trap_state!=0){ super::core.enter_trap(*trap_state, pc.val, instr); @@ -2215,7 +2306,7 @@ private: return pc; } - /* instruction 45: CSRRS */ + /* instruction 46: CSRRS */ compile_ret_t __csrrs(virt_addr_t& pc, code_word_t instr){ // pre execution stuff auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); @@ -2223,7 +2314,7 @@ private: *PC=*NEXT_PC; auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); - if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 45); + if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 46); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint16_t csr = ((bit_sub<20,12>(instr))); @@ -2248,7 +2339,7 @@ private: } } catch(...){} // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 45); + if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 46); // trap check if(*trap_state!=0){ super::core.enter_trap(*trap_state, pc.val, instr); @@ -2261,7 +2352,7 @@ private: return pc; } - /* instruction 46: CSRRC */ + /* instruction 47: CSRRC */ compile_ret_t __csrrc(virt_addr_t& pc, code_word_t instr){ // pre execution stuff auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); @@ -2269,7 +2360,7 @@ private: *PC=*NEXT_PC; auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); - if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 46); + if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 47); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint16_t csr = ((bit_sub<20,12>(instr))); @@ -2294,7 +2385,7 @@ private: } } catch(...){} // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 46); + if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 47); // trap check if(*trap_state!=0){ super::core.enter_trap(*trap_state, pc.val, instr); @@ -2307,7 +2398,7 @@ private: return pc; } - /* instruction 47: CSRRWI */ + /* instruction 48: CSRRWI */ compile_ret_t __csrrwi(virt_addr_t& pc, code_word_t instr){ // pre execution stuff auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); @@ -2315,7 +2406,7 @@ private: *PC=*NEXT_PC; auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); - if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 47); + if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 48); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t zimm = ((bit_sub<15,5>(instr))); uint16_t csr = ((bit_sub<20,12>(instr))); @@ -2339,7 +2430,7 @@ private: } } catch(...){} // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 47); + if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 48); // trap check if(*trap_state!=0){ super::core.enter_trap(*trap_state, pc.val, instr); @@ -2352,7 +2443,7 @@ private: return pc; } - /* instruction 48: CSRRSI */ + /* instruction 49: CSRRSI */ compile_ret_t __csrrsi(virt_addr_t& pc, code_word_t instr){ // pre execution stuff auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); @@ -2360,7 +2451,7 @@ private: *PC=*NEXT_PC; auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); - if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 48); + if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 49); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t zimm = ((bit_sub<15,5>(instr))); uint16_t csr = ((bit_sub<20,12>(instr))); @@ -2384,7 +2475,7 @@ private: } } catch(...){} // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 48); + if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 49); // trap check if(*trap_state!=0){ super::core.enter_trap(*trap_state, pc.val, instr); @@ -2397,7 +2488,7 @@ private: return pc; } - /* instruction 49: CSRRCI */ + /* instruction 50: CSRRCI */ compile_ret_t __csrrci(virt_addr_t& pc, code_word_t instr){ // pre execution stuff auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); @@ -2405,7 +2496,7 @@ private: *PC=*NEXT_PC; auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); - if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 49); + if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 50); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t zimm = ((bit_sub<15,5>(instr))); uint16_t csr = ((bit_sub<20,12>(instr))); @@ -2429,7 +2520,7 @@ private: } } catch(...){} // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 49); + if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 50); // trap check if(*trap_state!=0){ super::core.enter_trap(*trap_state, pc.val, instr); @@ -2442,7 +2533,47 @@ private: return pc; } - /* instruction 50: MUL */ + /* instruction 51: FENCE_I */ + compile_ret_t __fence_i(virt_addr_t& pc, code_word_t instr){ + // pre execution stuff + auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); + auto NEXT_PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::NEXT_PC]); + *PC=*NEXT_PC; + auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); + *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); + if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 51); + uint8_t rd = ((bit_sub<7,5>(instr))); + uint8_t rs1 = ((bit_sub<15,5>(instr))); + uint16_t imm = ((bit_sub<20,12>(instr))); + if(this->disass_enabled){ + /* generate console output when executing the command */ + auto mnemonic = fmt::format( + "{mnemonic:10} {rs1}, {rd}, {imm}", fmt::arg("mnemonic", "fence_i"), + fmt::arg("rs1", name(rs1)), fmt::arg("rd", name(rd)), fmt::arg("imm", imm)); + this->core.disass_output(pc.val, mnemonic); + + } + // used registers// calculate next pc value + *NEXT_PC = *PC + 4; + // execute instruction + try { + writeSpace2(traits::FENCE, traits::fencei, imm); + } catch(...){} + // post execution stuff + if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 51); + // trap check + if(*trap_state!=0){ + super::core.enter_trap(*trap_state, pc.val, instr); + } else { + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::ICOUNT]))++; + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::INSTRET]))++; + } + (*reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::CYCLE]))++; + pc.val=*NEXT_PC; + return pc; + } + + /* instruction 52: MUL */ compile_ret_t __mul(virt_addr_t& pc, code_word_t instr){ // pre execution stuff auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); @@ -2450,7 +2581,7 @@ private: *PC=*NEXT_PC; auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); - if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 50); + if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 52); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint8_t rs2 = ((bit_sub<20,5>(instr))); @@ -2475,7 +2606,7 @@ private: } } catch(...){} // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 50); + if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 52); // trap check if(*trap_state!=0){ super::core.enter_trap(*trap_state, pc.val, instr); @@ -2488,7 +2619,7 @@ private: return pc; } - /* instruction 51: MULH */ + /* instruction 53: MULH */ compile_ret_t __mulh(virt_addr_t& pc, code_word_t instr){ // pre execution stuff auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); @@ -2496,7 +2627,7 @@ private: *PC=*NEXT_PC; auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); - if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 51); + if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 53); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint8_t rs2 = ((bit_sub<20,5>(instr))); @@ -2521,7 +2652,7 @@ private: } } catch(...){} // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 51); + if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 53); // trap check if(*trap_state!=0){ super::core.enter_trap(*trap_state, pc.val, instr); @@ -2534,7 +2665,7 @@ private: return pc; } - /* instruction 52: MULHSU */ + /* instruction 54: MULHSU */ compile_ret_t __mulhsu(virt_addr_t& pc, code_word_t instr){ // pre execution stuff auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); @@ -2542,7 +2673,7 @@ private: *PC=*NEXT_PC; auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); - if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 52); + if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 54); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint8_t rs2 = ((bit_sub<20,5>(instr))); @@ -2567,7 +2698,7 @@ private: } } catch(...){} // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 52); + if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 54); // trap check if(*trap_state!=0){ super::core.enter_trap(*trap_state, pc.val, instr); @@ -2580,7 +2711,7 @@ private: return pc; } - /* instruction 53: MULHU */ + /* instruction 55: MULHU */ compile_ret_t __mulhu(virt_addr_t& pc, code_word_t instr){ // pre execution stuff auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); @@ -2588,7 +2719,7 @@ private: *PC=*NEXT_PC; auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); - if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 53); + if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 55); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint8_t rs2 = ((bit_sub<20,5>(instr))); @@ -2613,7 +2744,7 @@ private: } } catch(...){} // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 53); + if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 55); // trap check if(*trap_state!=0){ super::core.enter_trap(*trap_state, pc.val, instr); @@ -2626,7 +2757,7 @@ private: return pc; } - /* instruction 54: DIV */ + /* instruction 56: DIV */ compile_ret_t __div(virt_addr_t& pc, code_word_t instr){ // pre execution stuff auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); @@ -2634,7 +2765,7 @@ private: *PC=*NEXT_PC; auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); - if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 54); + if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 56); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint8_t rs2 = ((bit_sub<20,5>(instr))); @@ -2663,7 +2794,7 @@ private: } } catch(...){} // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 54); + if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 56); // trap check if(*trap_state!=0){ super::core.enter_trap(*trap_state, pc.val, instr); @@ -2676,7 +2807,7 @@ private: return pc; } - /* instruction 55: DIVU */ + /* instruction 57: DIVU */ compile_ret_t __divu(virt_addr_t& pc, code_word_t instr){ // pre execution stuff auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); @@ -2684,7 +2815,7 @@ private: *PC=*NEXT_PC; auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); - if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 55); + if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 57); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint8_t rs2 = ((bit_sub<20,5>(instr))); @@ -2709,7 +2840,7 @@ private: } } catch(...){} // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 55); + if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 57); // trap check if(*trap_state!=0){ super::core.enter_trap(*trap_state, pc.val, instr); @@ -2722,7 +2853,7 @@ private: return pc; } - /* instruction 56: REM */ + /* instruction 58: REM */ compile_ret_t __rem(virt_addr_t& pc, code_word_t instr){ // pre execution stuff auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); @@ -2730,7 +2861,7 @@ private: *PC=*NEXT_PC; auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); - if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 56); + if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 58); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint8_t rs2 = ((bit_sub<20,5>(instr))); @@ -2759,7 +2890,7 @@ private: } } catch(...){} // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 56); + if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 58); // trap check if(*trap_state!=0){ super::core.enter_trap(*trap_state, pc.val, instr); @@ -2772,7 +2903,7 @@ private: return pc; } - /* instruction 57: REMU */ + /* instruction 59: REMU */ compile_ret_t __remu(virt_addr_t& pc, code_word_t instr){ // pre execution stuff auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); @@ -2780,7 +2911,7 @@ private: *PC=*NEXT_PC; auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); - if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 57); + if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 59); uint8_t rd = ((bit_sub<7,5>(instr))); uint8_t rs1 = ((bit_sub<15,5>(instr))); uint8_t rs2 = ((bit_sub<20,5>(instr))); @@ -2805,7 +2936,7 @@ private: } } catch(...){} // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 57); + if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 59); // trap check if(*trap_state!=0){ super::core.enter_trap(*trap_state, pc.val, instr); @@ -2818,7 +2949,7 @@ private: return pc; } - /* instruction 58: CADDI4SPN */ + /* instruction 60: CADDI4SPN */ compile_ret_t __caddi4spn(virt_addr_t& pc, code_word_t instr){ // pre execution stuff auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); @@ -2826,7 +2957,7 @@ private: *PC=*NEXT_PC; auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); - if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 58); + if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 60); uint8_t rd = ((bit_sub<2,3>(instr))); uint16_t imm = ((bit_sub<5,1>(instr) << 3) | (bit_sub<6,1>(instr) << 2) | (bit_sub<7,4>(instr) << 6) | (bit_sub<11,2>(instr) << 4)); if(this->disass_enabled){ @@ -2846,7 +2977,7 @@ private: else raise(0, 2); } catch(...){} // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 58); + if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 60); // trap check if(*trap_state!=0){ super::core.enter_trap(*trap_state, pc.val, instr); @@ -2859,7 +2990,7 @@ private: return pc; } - /* instruction 59: CLW */ + /* instruction 61: CLW */ compile_ret_t __clw(virt_addr_t& pc, code_word_t instr){ // pre execution stuff auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); @@ -2867,7 +2998,7 @@ private: *PC=*NEXT_PC; auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); - if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 59); + if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 61); uint8_t rd = ((bit_sub<2,3>(instr))); uint8_t uimm = ((bit_sub<5,1>(instr) << 6) | (bit_sub<6,1>(instr) << 2) | (bit_sub<10,3>(instr) << 3)); uint8_t rs1 = ((bit_sub<7,3>(instr))); @@ -2890,7 +3021,7 @@ private: } } catch(...){} // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 59); + if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 61); // trap check if(*trap_state!=0){ super::core.enter_trap(*trap_state, pc.val, instr); @@ -2903,7 +3034,7 @@ private: return pc; } - /* instruction 60: CSW */ + /* instruction 62: CSW */ compile_ret_t __csw(virt_addr_t& pc, code_word_t instr){ // pre execution stuff auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); @@ -2911,7 +3042,7 @@ private: *PC=*NEXT_PC; auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); - if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 60); + if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 62); uint8_t rs2 = ((bit_sub<2,3>(instr))); uint8_t uimm = ((bit_sub<5,1>(instr) << 6) | (bit_sub<6,1>(instr) << 2) | (bit_sub<10,3>(instr) << 3)); uint8_t rs1 = ((bit_sub<7,3>(instr))); @@ -2934,7 +3065,7 @@ private: } } catch(...){} // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 60); + if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 62); // trap check if(*trap_state!=0){ super::core.enter_trap(*trap_state, pc.val, instr); @@ -2947,7 +3078,7 @@ private: return pc; } - /* instruction 61: CADDI */ + /* instruction 63: CADDI */ compile_ret_t __caddi(virt_addr_t& pc, code_word_t instr){ // pre execution stuff auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); @@ -2955,7 +3086,7 @@ private: *PC=*NEXT_PC; auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); - if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 61); + if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 63); uint8_t imm = ((bit_sub<2,5>(instr)) | (bit_sub<12,1>(instr) << 5)); uint8_t rs1 = ((bit_sub<7,5>(instr))); if(this->disass_enabled){ @@ -2974,7 +3105,7 @@ private: *(X+rs1) = *(X+rs1) + (int8_t)sext<6>(imm); } catch(...){} // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 61); + if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 63); // trap check if(*trap_state!=0){ super::core.enter_trap(*trap_state, pc.val, instr); @@ -2987,7 +3118,7 @@ private: return pc; } - /* instruction 62: CNOP */ + /* instruction 64: CNOP */ compile_ret_t __cnop(virt_addr_t& pc, code_word_t instr){ // pre execution stuff auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); @@ -2995,7 +3126,7 @@ private: *PC=*NEXT_PC; auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); - if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 62); + if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 64); uint8_t nzimm = ((bit_sub<2,5>(instr)) | (bit_sub<12,1>(instr) << 5)); if(this->disass_enabled){ /* generate console output when executing the command */ @@ -3010,7 +3141,7 @@ private: } } catch(...){} // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 62); + if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 64); // trap check if(*trap_state!=0){ super::core.enter_trap(*trap_state, pc.val, instr); @@ -3023,7 +3154,7 @@ private: return pc; } - /* instruction 63: CJAL */ + /* instruction 65: CJAL */ compile_ret_t __cjal(virt_addr_t& pc, code_word_t instr){ // pre execution stuff auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); @@ -3031,7 +3162,7 @@ private: *PC=*NEXT_PC; auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); - if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 63); + if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 65); uint16_t imm = ((bit_sub<2,1>(instr) << 5) | (bit_sub<3,3>(instr) << 1) | (bit_sub<6,1>(instr) << 7) | (bit_sub<7,1>(instr) << 6) | (bit_sub<8,1>(instr) << 10) | (bit_sub<9,2>(instr) << 8) | (bit_sub<11,1>(instr) << 4) | (bit_sub<12,1>(instr) << 11)); if(this->disass_enabled){ /* generate console output when executing the command */ @@ -3052,7 +3183,7 @@ private: } } catch(...){} // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 63); + if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 65); // trap check if(*trap_state!=0){ super::core.enter_trap(*trap_state, pc.val, instr); @@ -3065,7 +3196,7 @@ private: return pc; } - /* instruction 64: CLI */ + /* instruction 66: CLI */ compile_ret_t __cli(virt_addr_t& pc, code_word_t instr){ // pre execution stuff auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); @@ -3073,7 +3204,7 @@ private: *PC=*NEXT_PC; auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); - if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 64); + if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 66); uint8_t imm = ((bit_sub<2,5>(instr)) | (bit_sub<12,1>(instr) << 5)); uint8_t rd = ((bit_sub<7,5>(instr))); if(this->disass_enabled){ @@ -3094,7 +3225,7 @@ private: } } catch(...){} // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 64); + if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 66); // trap check if(*trap_state!=0){ super::core.enter_trap(*trap_state, pc.val, instr); @@ -3107,7 +3238,7 @@ private: return pc; } - /* instruction 65: CLUI */ + /* instruction 67: CLUI */ compile_ret_t __clui(virt_addr_t& pc, code_word_t instr){ // pre execution stuff auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); @@ -3115,7 +3246,7 @@ private: *PC=*NEXT_PC; auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); - if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 65); + if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 67); uint32_t imm = ((bit_sub<2,5>(instr) << 12) | (bit_sub<12,1>(instr) << 17)); uint8_t rd = ((bit_sub<7,5>(instr))); if(this->disass_enabled){ @@ -3137,7 +3268,7 @@ private: } } catch(...){} // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 65); + if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 67); // trap check if(*trap_state!=0){ super::core.enter_trap(*trap_state, pc.val, instr); @@ -3150,7 +3281,7 @@ private: return pc; } - /* instruction 66: CADDI16SP */ + /* instruction 68: CADDI16SP */ compile_ret_t __caddi16sp(virt_addr_t& pc, code_word_t instr){ // pre execution stuff auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); @@ -3158,7 +3289,7 @@ private: *PC=*NEXT_PC; auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); - if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 66); + if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 68); uint16_t nzimm = ((bit_sub<2,1>(instr) << 5) | (bit_sub<3,2>(instr) << 7) | (bit_sub<5,1>(instr) << 6) | (bit_sub<6,1>(instr) << 4) | (bit_sub<12,1>(instr) << 9)); if(this->disass_enabled){ /* generate console output when executing the command */ @@ -3177,7 +3308,7 @@ private: else raise(0, 2); } catch(...){} // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 66); + if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 68); // trap check if(*trap_state!=0){ super::core.enter_trap(*trap_state, pc.val, instr); @@ -3190,7 +3321,7 @@ private: return pc; } - /* instruction 67: __reserved_clui */ + /* instruction 69: __reserved_clui */ compile_ret_t ____reserved_clui(virt_addr_t& pc, code_word_t instr){ // pre execution stuff auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); @@ -3198,7 +3329,7 @@ private: *PC=*NEXT_PC; auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); - if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 67); + if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 69); uint8_t rd = ((bit_sub<7,5>(instr))); if(this->disass_enabled){ /* generate console output when executing the command */ @@ -3212,7 +3343,7 @@ private: raise(0, 2); } catch(...){} // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 67); + if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 69); // trap check if(*trap_state!=0){ super::core.enter_trap(*trap_state, pc.val, instr); @@ -3225,7 +3356,7 @@ private: return pc; } - /* instruction 68: CSRLI */ + /* instruction 70: CSRLI */ compile_ret_t __csrli(virt_addr_t& pc, code_word_t instr){ // pre execution stuff auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); @@ -3233,7 +3364,7 @@ private: *PC=*NEXT_PC; auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); - if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 68); + if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 70); uint8_t shamt = ((bit_sub<2,5>(instr))); uint8_t rs1 = ((bit_sub<7,3>(instr))); if(this->disass_enabled){ @@ -3255,7 +3386,7 @@ private: } } catch(...){} // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 68); + if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 70); // trap check if(*trap_state!=0){ super::core.enter_trap(*trap_state, pc.val, instr); @@ -3268,7 +3399,7 @@ private: return pc; } - /* instruction 69: CSRAI */ + /* instruction 71: CSRAI */ compile_ret_t __csrai(virt_addr_t& pc, code_word_t instr){ // pre execution stuff auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); @@ -3276,7 +3407,7 @@ private: *PC=*NEXT_PC; auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); - if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 69); + if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 71); uint8_t shamt = ((bit_sub<2,5>(instr))); uint8_t rs1 = ((bit_sub<7,3>(instr))); if(this->disass_enabled){ @@ -3302,7 +3433,7 @@ private: } } catch(...){} // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 69); + if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 71); // trap check if(*trap_state!=0){ super::core.enter_trap(*trap_state, pc.val, instr); @@ -3315,7 +3446,7 @@ private: return pc; } - /* instruction 70: CANDI */ + /* instruction 72: CANDI */ compile_ret_t __candi(virt_addr_t& pc, code_word_t instr){ // pre execution stuff auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); @@ -3323,7 +3454,7 @@ private: *PC=*NEXT_PC; auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); - if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 70); + if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 72); uint8_t imm = ((bit_sub<2,5>(instr)) | (bit_sub<12,1>(instr) << 5)); uint8_t rs1 = ((bit_sub<7,3>(instr))); if(this->disass_enabled){ @@ -3345,7 +3476,7 @@ private: } } catch(...){} // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 70); + if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 72); // trap check if(*trap_state!=0){ super::core.enter_trap(*trap_state, pc.val, instr); @@ -3358,7 +3489,7 @@ private: return pc; } - /* instruction 71: CSUB */ + /* instruction 73: CSUB */ compile_ret_t __csub(virt_addr_t& pc, code_word_t instr){ // pre execution stuff auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); @@ -3366,7 +3497,7 @@ private: *PC=*NEXT_PC; auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); - if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 71); + if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 73); uint8_t rs2 = ((bit_sub<2,3>(instr))); uint8_t rd = ((bit_sub<7,3>(instr))); if(this->disass_enabled){ @@ -3388,7 +3519,7 @@ private: } } catch(...){} // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 71); + if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 73); // trap check if(*trap_state!=0){ super::core.enter_trap(*trap_state, pc.val, instr); @@ -3401,7 +3532,7 @@ private: return pc; } - /* instruction 72: CXOR */ + /* instruction 74: CXOR */ compile_ret_t __cxor(virt_addr_t& pc, code_word_t instr){ // pre execution stuff auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); @@ -3409,7 +3540,7 @@ private: *PC=*NEXT_PC; auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); - if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 72); + if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 74); uint8_t rs2 = ((bit_sub<2,3>(instr))); uint8_t rd = ((bit_sub<7,3>(instr))); if(this->disass_enabled){ @@ -3431,7 +3562,7 @@ private: } } catch(...){} // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 72); + if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 74); // trap check if(*trap_state!=0){ super::core.enter_trap(*trap_state, pc.val, instr); @@ -3444,7 +3575,7 @@ private: return pc; } - /* instruction 73: COR */ + /* instruction 75: COR */ compile_ret_t __cor(virt_addr_t& pc, code_word_t instr){ // pre execution stuff auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); @@ -3452,7 +3583,7 @@ private: *PC=*NEXT_PC; auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); - if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 73); + if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 75); uint8_t rs2 = ((bit_sub<2,3>(instr))); uint8_t rd = ((bit_sub<7,3>(instr))); if(this->disass_enabled){ @@ -3474,7 +3605,7 @@ private: } } catch(...){} // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 73); + if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 75); // trap check if(*trap_state!=0){ super::core.enter_trap(*trap_state, pc.val, instr); @@ -3487,7 +3618,7 @@ private: return pc; } - /* instruction 74: CAND */ + /* instruction 76: CAND */ compile_ret_t __cand(virt_addr_t& pc, code_word_t instr){ // pre execution stuff auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); @@ -3495,7 +3626,7 @@ private: *PC=*NEXT_PC; auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); - if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 74); + if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 76); uint8_t rs2 = ((bit_sub<2,3>(instr))); uint8_t rd = ((bit_sub<7,3>(instr))); if(this->disass_enabled){ @@ -3517,7 +3648,7 @@ private: } } catch(...){} // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 74); + if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 76); // trap check if(*trap_state!=0){ super::core.enter_trap(*trap_state, pc.val, instr); @@ -3530,7 +3661,7 @@ private: return pc; } - /* instruction 75: CJ */ + /* instruction 77: CJ */ compile_ret_t __cj(virt_addr_t& pc, code_word_t instr){ // pre execution stuff auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); @@ -3538,7 +3669,7 @@ private: *PC=*NEXT_PC; auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); - if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 75); + if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 77); uint16_t imm = ((bit_sub<2,1>(instr) << 5) | (bit_sub<3,3>(instr) << 1) | (bit_sub<6,1>(instr) << 7) | (bit_sub<7,1>(instr) << 6) | (bit_sub<8,1>(instr) << 10) | (bit_sub<9,2>(instr) << 8) | (bit_sub<11,1>(instr) << 4) | (bit_sub<12,1>(instr) << 11)); if(this->disass_enabled){ /* generate console output when executing the command */ @@ -3555,7 +3686,7 @@ private: pc_assign(*NEXT_PC) = *PC + (int16_t)sext<12>(imm); } catch(...){} // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 75); + if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 77); // trap check if(*trap_state!=0){ super::core.enter_trap(*trap_state, pc.val, instr); @@ -3568,7 +3699,7 @@ private: return pc; } - /* instruction 76: CBEQZ */ + /* instruction 78: CBEQZ */ compile_ret_t __cbeqz(virt_addr_t& pc, code_word_t instr){ // pre execution stuff auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); @@ -3576,7 +3707,7 @@ private: *PC=*NEXT_PC; auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); - if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 76); + if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 78); uint16_t imm = ((bit_sub<2,1>(instr) << 5) | (bit_sub<3,2>(instr) << 1) | (bit_sub<5,2>(instr) << 6) | (bit_sub<10,2>(instr) << 3) | (bit_sub<12,1>(instr) << 8)); uint8_t rs1 = ((bit_sub<7,3>(instr))); if(this->disass_enabled){ @@ -3595,7 +3726,7 @@ private: if(*(X+(rs1 + 8)) == 0) pc_assign(*NEXT_PC) = *PC + (int16_t)sext<9>(imm); } catch(...){} // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 76); + if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 78); // trap check if(*trap_state!=0){ super::core.enter_trap(*trap_state, pc.val, instr); @@ -3608,7 +3739,7 @@ private: return pc; } - /* instruction 77: CBNEZ */ + /* instruction 79: CBNEZ */ compile_ret_t __cbnez(virt_addr_t& pc, code_word_t instr){ // pre execution stuff auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); @@ -3616,7 +3747,7 @@ private: *PC=*NEXT_PC; auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); - if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 77); + if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 79); uint16_t imm = ((bit_sub<2,1>(instr) << 5) | (bit_sub<3,2>(instr) << 1) | (bit_sub<5,2>(instr) << 6) | (bit_sub<10,2>(instr) << 3) | (bit_sub<12,1>(instr) << 8)); uint8_t rs1 = ((bit_sub<7,3>(instr))); if(this->disass_enabled){ @@ -3635,7 +3766,7 @@ private: if(*(X+(rs1 + 8)) != 0) pc_assign(*NEXT_PC) = *PC + (int16_t)sext<9>(imm); } catch(...){} // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 77); + if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 79); // trap check if(*trap_state!=0){ super::core.enter_trap(*trap_state, pc.val, instr); @@ -3648,7 +3779,7 @@ private: return pc; } - /* instruction 78: CSLLI */ + /* instruction 80: CSLLI */ compile_ret_t __cslli(virt_addr_t& pc, code_word_t instr){ // pre execution stuff auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); @@ -3656,7 +3787,7 @@ private: *PC=*NEXT_PC; auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); - if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 78); + if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 80); uint8_t nzuimm = ((bit_sub<2,5>(instr))); uint8_t rs1 = ((bit_sub<7,5>(instr))); if(this->disass_enabled){ @@ -3675,7 +3806,7 @@ private: if(nzuimm) *(X+rs1) = *(X+rs1) << nzuimm; } catch(...){} // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 78); + if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 80); // trap check if(*trap_state!=0){ super::core.enter_trap(*trap_state, pc.val, instr); @@ -3688,7 +3819,7 @@ private: return pc; } - /* instruction 79: CLWSP */ + /* instruction 81: CLWSP */ compile_ret_t __clwsp(virt_addr_t& pc, code_word_t instr){ // pre execution stuff auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); @@ -3696,7 +3827,7 @@ private: *PC=*NEXT_PC; auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); - if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 79); + if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 81); uint8_t uimm = ((bit_sub<2,2>(instr) << 6) | (bit_sub<4,3>(instr) << 2) | (bit_sub<12,1>(instr) << 5)); uint8_t rd = ((bit_sub<7,5>(instr))); if(this->disass_enabled){ @@ -3719,7 +3850,7 @@ private: else raise(0, 2); } catch(...){} // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 79); + if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 81); // trap check if(*trap_state!=0){ super::core.enter_trap(*trap_state, pc.val, instr); @@ -3732,7 +3863,7 @@ private: return pc; } - /* instruction 80: CMV */ + /* instruction 82: CMV */ compile_ret_t __cmv(virt_addr_t& pc, code_word_t instr){ // pre execution stuff auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); @@ -3740,7 +3871,7 @@ private: *PC=*NEXT_PC; auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); - if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 80); + if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 82); uint8_t rs2 = ((bit_sub<2,5>(instr))); uint8_t rd = ((bit_sub<7,5>(instr))); if(this->disass_enabled){ @@ -3759,7 +3890,7 @@ private: if(rd != 0) *(X+rd) = *(X+rs2); } catch(...){} // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 80); + if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 82); // trap check if(*trap_state!=0){ super::core.enter_trap(*trap_state, pc.val, instr); @@ -3772,7 +3903,7 @@ private: return pc; } - /* instruction 81: CJR */ + /* instruction 83: CJR */ compile_ret_t __cjr(virt_addr_t& pc, code_word_t instr){ // pre execution stuff auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); @@ -3780,7 +3911,7 @@ private: *PC=*NEXT_PC; auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); - if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 81); + if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 83); uint8_t rs1 = ((bit_sub<7,5>(instr))); if(this->disass_enabled){ /* generate console output when executing the command */ @@ -3799,7 +3930,7 @@ private: else raise(0, 2); } catch(...){} // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 81); + if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 83); // trap check if(*trap_state!=0){ super::core.enter_trap(*trap_state, pc.val, instr); @@ -3812,7 +3943,7 @@ private: return pc; } - /* instruction 82: __reserved_cmv */ + /* instruction 84: __reserved_cmv */ compile_ret_t ____reserved_cmv(virt_addr_t& pc, code_word_t instr){ // pre execution stuff auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); @@ -3820,7 +3951,7 @@ private: *PC=*NEXT_PC; auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); - if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 82); + if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 84); if(this->disass_enabled){ /* generate console output when executing the command */ this->core.disass_output(pc.val, "__reserved_cmv"); @@ -3833,7 +3964,7 @@ private: raise(0, 2); } catch(...){} // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 82); + if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 84); // trap check if(*trap_state!=0){ super::core.enter_trap(*trap_state, pc.val, instr); @@ -3846,7 +3977,7 @@ private: return pc; } - /* instruction 83: CADD */ + /* instruction 85: CADD */ compile_ret_t __cadd(virt_addr_t& pc, code_word_t instr){ // pre execution stuff auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); @@ -3854,7 +3985,7 @@ private: *PC=*NEXT_PC; auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); - if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 83); + if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 85); uint8_t rs2 = ((bit_sub<2,5>(instr))); uint8_t rd = ((bit_sub<7,5>(instr))); if(this->disass_enabled){ @@ -3873,7 +4004,7 @@ private: if(rd != 0) *(X+rd) = *(X+rd) + *(X+rs2); } catch(...){} // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 83); + if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 85); // trap check if(*trap_state!=0){ super::core.enter_trap(*trap_state, pc.val, instr); @@ -3886,7 +4017,7 @@ private: return pc; } - /* instruction 84: CJALR */ + /* instruction 86: CJALR */ compile_ret_t __cjalr(virt_addr_t& pc, code_word_t instr){ // pre execution stuff auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); @@ -3894,7 +4025,7 @@ private: *PC=*NEXT_PC; auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); - if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 84); + if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 86); uint8_t rs1 = ((bit_sub<7,5>(instr))); if(this->disass_enabled){ /* generate console output when executing the command */ @@ -3916,7 +4047,7 @@ private: } } catch(...){} // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 84); + if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 86); // trap check if(*trap_state!=0){ super::core.enter_trap(*trap_state, pc.val, instr); @@ -3929,7 +4060,7 @@ private: return pc; } - /* instruction 85: CEBREAK */ + /* instruction 87: CEBREAK */ compile_ret_t __cebreak(virt_addr_t& pc, code_word_t instr){ // pre execution stuff auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); @@ -3937,7 +4068,7 @@ private: *PC=*NEXT_PC; auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); - if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 85); + if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 87); if(this->disass_enabled){ /* generate console output when executing the command */ this->core.disass_output(pc.val, "cebreak"); @@ -3950,7 +4081,7 @@ private: raise(0, 3); } catch(...){} // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 85); + if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 87); // trap check if(*trap_state!=0){ super::core.enter_trap(*trap_state, pc.val, instr); @@ -3963,7 +4094,7 @@ private: return pc; } - /* instruction 86: CSWSP */ + /* instruction 88: CSWSP */ compile_ret_t __cswsp(virt_addr_t& pc, code_word_t instr){ // pre execution stuff auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); @@ -3971,7 +4102,7 @@ private: *PC=*NEXT_PC; auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); - if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 86); + if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 88); uint8_t rs2 = ((bit_sub<2,5>(instr))); uint8_t uimm = ((bit_sub<7,2>(instr) << 6) | (bit_sub<9,4>(instr) << 2)); if(this->disass_enabled){ @@ -3993,7 +4124,7 @@ private: } } catch(...){} // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 86); + if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 88); // trap check if(*trap_state!=0){ super::core.enter_trap(*trap_state, pc.val, instr); @@ -4006,7 +4137,7 @@ private: return pc; } - /* instruction 87: DII */ + /* instruction 89: DII */ compile_ret_t __dii(virt_addr_t& pc, code_word_t instr){ // pre execution stuff auto* PC = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PC]); @@ -4014,7 +4145,7 @@ private: *PC=*NEXT_PC; auto* trap_state = reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::TRAP_STATE]); *trap_state = *reinterpret_cast(this->regs_base_ptr+arch::traits::reg_byte_offsets[arch::traits::PENDING_TRAP]); - if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 87); + if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, 89); if(this->disass_enabled){ /* generate console output when executing the command */ this->core.disass_output(pc.val, "dii"); @@ -4027,7 +4158,7 @@ private: raise(0, 2); } catch(...){} // post execution stuff - if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 87); + if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, 89); // trap check if(*trap_state!=0){ super::core.enter_trap(*trap_state, pc.val, instr); @@ -4060,7 +4191,7 @@ private: return pc; } - static constexpr typename traits::addr_t upper_bits = ~traits::PGMASK; + //static constexpr typename traits::addr_t upper_bits = ~traits::PGMASK; iss::status fetch_ins(virt_addr_t pc, uint8_t * data){ auto phys_pc = this->core.v2p(pc); //if ((pc.val & upper_bits) != ((pc.val + 2) & upper_bits)) { // we may cross a page boundary @@ -4138,9 +4269,10 @@ typename vm_base::virt_addr_t vm_impl::execute_inst(finish_cond_e co this->do_sync(POST_SYNC, std::numeric_limits::max()); pc.val = super::core.enter_trap(std::numeric_limits::max(), pc.val, 0); } else { - if (is_jump_to_self_enabled(cond) && (insn == 0x0000006f || (insn&0xffff)==0xa001)) - throw simulation_stopped(0); // 'J 0' or 'C.J 0' + if (is_jump_to_self_enabled(cond) && + (insn == 0x0000006f || (insn&0xffff)==0xa001)) throw simulation_stopped(0); // 'J 0' or 'C.J 0' auto f = decode_inst(insn); + auto old_pc = pc.val; pc = (this->*f)(pc, insn); } }