Compare commits
	
		
			18 Commits
		
	
	
		
			dd4c19a15c
			...
			feature/re
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 58311b37db | |||
| ad8dc09bee | |||
| 2bba5645c3 | |||
| bf0a5a80de | |||
| b37ef973de | |||
| 4c363f4073 | |||
| b8fa5fbbda | |||
| ac86f14a54 | |||
| 68b5697c8f | |||
| 09b0f0d0c8 | |||
| 98b418ff43 | |||
| 059bd0d371 | |||
| ef2a4df925 | |||
| 7578906310 | |||
| afe8905ac9 | |||
| ecc6091d1e | |||
| 3563ba80d0 | |||
| 09955be90f | 
							
								
								
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							@@ -32,3 +32,4 @@ language.settings.xml
 | 
				
			|||||||
/dump.json
 | 
					/dump.json
 | 
				
			||||||
/src-gen/
 | 
					/src-gen/
 | 
				
			||||||
/*.yaml
 | 
					/*.yaml
 | 
				
			||||||
 | 
					/*.json
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -7,6 +7,7 @@ project(dbt-rise-tgc VERSION 1.0.0)
 | 
				
			|||||||
include(GNUInstallDirs)
 | 
					include(GNUInstallDirs)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
find_package(elfio)
 | 
					find_package(elfio)
 | 
				
			||||||
 | 
					find_package(Boost COMPONENTS coroutine)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
if(WITH_LLVM)
 | 
					if(WITH_LLVM)
 | 
				
			||||||
    if(DEFINED ENV{LLVM_HOME})
 | 
					    if(DEFINED ENV{LLVM_HOME})
 | 
				
			||||||
@@ -34,10 +35,14 @@ FILE(GLOB TGC_VM_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src/vm/interp/vm_*.cpp)
 | 
				
			|||||||
set(LIB_SOURCES 
 | 
					set(LIB_SOURCES 
 | 
				
			||||||
    src/vm/fp_functions.cpp
 | 
					    src/vm/fp_functions.cpp
 | 
				
			||||||
    src/plugin/instruction_count.cpp
 | 
					    src/plugin/instruction_count.cpp
 | 
				
			||||||
    src/plugin/cycle_estimate.cpp
 | 
					    src/plugin/pctrace.cpp
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
    ${TGC_SOURCES}
 | 
					    ${TGC_SOURCES}
 | 
				
			||||||
    ${TGC_VM_SOURCES}
 | 
					    ${TGC_VM_SOURCES}
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					if(TARGET RapidJSON)
 | 
				
			||||||
 | 
					    list(APPEND LIB_SOURCES src/plugin/cycle_estimate.cpp)
 | 
				
			||||||
 | 
					endif()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
if(WITH_LLVM)
 | 
					if(WITH_LLVM)
 | 
				
			||||||
	FILE(GLOB TGC_LLVM_SOURCES
 | 
						FILE(GLOB TGC_LLVM_SOURCES
 | 
				
			||||||
@@ -66,7 +71,7 @@ elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
 | 
				
			|||||||
    target_compile_options(${PROJECT_NAME} PRIVATE /wd4293)
 | 
					    target_compile_options(${PROJECT_NAME} PRIVATE /wd4293)
 | 
				
			||||||
endif()
 | 
					endif()
 | 
				
			||||||
target_include_directories(${PROJECT_NAME} PUBLIC incl)
 | 
					target_include_directories(${PROJECT_NAME} PUBLIC incl)
 | 
				
			||||||
target_link_libraries(${PROJECT_NAME} PUBLIC softfloat scc-util jsoncpp)
 | 
					target_link_libraries(${PROJECT_NAME} PUBLIC softfloat scc-util jsoncpp Boost::coroutine)
 | 
				
			||||||
if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
 | 
					if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
 | 
				
			||||||
    target_link_libraries(${PROJECT_NAME} PUBLIC -Wl,--whole-archive dbt-core -Wl,--no-whole-archive)
 | 
					    target_link_libraries(${PROJECT_NAME} PUBLIC -Wl,--whole-archive dbt-core -Wl,--no-whole-archive)
 | 
				
			||||||
else()
 | 
					else()
 | 
				
			||||||
@@ -79,6 +84,10 @@ elseif(TARGET elfio::elfio)
 | 
				
			|||||||
else()
 | 
					else()
 | 
				
			||||||
    message(FATAL_ERROR "No elfio library found, maybe a find_package() call is missing")
 | 
					    message(FATAL_ERROR "No elfio library found, maybe a find_package() call is missing")
 | 
				
			||||||
endif()
 | 
					endif()
 | 
				
			||||||
 | 
					if(TARGET RapidJSON)
 | 
				
			||||||
 | 
					    target_link_libraries(${PROJECT_NAME} PUBLIC RapidJSON)
 | 
				
			||||||
 | 
					endif()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
set_target_properties(${PROJECT_NAME} PROPERTIES
 | 
					set_target_properties(${PROJECT_NAME} PROPERTIES
 | 
				
			||||||
  VERSION ${PROJECT_VERSION}
 | 
					  VERSION ${PROJECT_VERSION}
 | 
				
			||||||
 
 | 
				
			|||||||
 Submodule gen_input/CoreDSL-Instruction-Set-Description deleted from b005607fc3
									
								
							@@ -161,7 +161,7 @@ struct ${coreDef.name.toLowerCase()}: public arch_if {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    inline uint32_t get_last_branch() { return reg.last_branch; }
 | 
					    inline uint32_t get_last_branch() { return reg.last_branch; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
protected:
 | 
					
 | 
				
			||||||
#pragma pack(push, 1)
 | 
					#pragma pack(push, 1)
 | 
				
			||||||
    struct ${coreDef.name}_regs {<%
 | 
					    struct ${coreDef.name}_regs {<%
 | 
				
			||||||
        registers.each { reg -> if(reg.size>0) {%> 
 | 
					        registers.each { reg -> if(reg.size>0) {%> 
 | 
				
			||||||
@@ -169,7 +169,6 @@ protected:
 | 
				
			|||||||
        }}%>
 | 
					        }}%>
 | 
				
			||||||
        uint32_t trap_state = 0, pending_trap = 0;
 | 
					        uint32_t trap_state = 0, pending_trap = 0;
 | 
				
			||||||
        uint64_t icount = 0;
 | 
					        uint64_t icount = 0;
 | 
				
			||||||
        uint64_t cycle = 0;
 | 
					 | 
				
			||||||
        uint64_t instret = 0;
 | 
					        uint64_t instret = 0;
 | 
				
			||||||
        uint32_t last_branch;
 | 
					        uint32_t last_branch;
 | 
				
			||||||
    } reg;
 | 
					    } reg;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,9 +1,12 @@
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
	"${coreDef.name}" : [<%instructions.eachWithIndex{instr,index -> %>${index==0?"":","}
 | 
						"${coreDef.name}" : [<%instructions.eachWithIndex{instr,index -> %>${index==0?"":","}
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			"name"  : "${instr.name}",
 | 
								"name"  :   "${instr.name}",
 | 
				
			||||||
			"size"  : ${instr.length},
 | 
								"size"  :   ${instr.length},
 | 
				
			||||||
			"delay" : ${instr.isConditional?"[1,1]":"1"}
 | 
								"encoding": "${instr.encoding}",
 | 
				
			||||||
 | 
					            "mask":     "${instr.mask}",
 | 
				
			||||||
 | 
								"branch":   ${instr.modifiesPC},
 | 
				
			||||||
 | 
								"delay" :   ${instr.isConditional?"[1,1]":"1"}
 | 
				
			||||||
		}<%}%>
 | 
							}<%}%>
 | 
				
			||||||
	]
 | 
						]
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -45,6 +45,8 @@ def nativeTypeSize(int size){
 | 
				
			|||||||
#include <iss/interp/vm_base.h>
 | 
					#include <iss/interp/vm_base.h>
 | 
				
			||||||
#include <util/logging.h>
 | 
					#include <util/logging.h>
 | 
				
			||||||
#include <sstream>
 | 
					#include <sstream>
 | 
				
			||||||
 | 
					#include <boost/coroutine2/all.hpp>
 | 
				
			||||||
 | 
					#include <functional>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifndef FMT_HEADER_ONLY
 | 
					#ifndef FMT_HEADER_ONLY
 | 
				
			||||||
#define FMT_HEADER_ONLY
 | 
					#define FMT_HEADER_ONLY
 | 
				
			||||||
@@ -59,6 +61,7 @@ namespace interp {
 | 
				
			|||||||
namespace ${coreDef.name.toLowerCase()} {
 | 
					namespace ${coreDef.name.toLowerCase()} {
 | 
				
			||||||
using namespace iss::arch;
 | 
					using namespace iss::arch;
 | 
				
			||||||
using namespace iss::debugger;
 | 
					using namespace iss::debugger;
 | 
				
			||||||
 | 
					using namespace std::placeholders;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
template <typename ARCH> class vm_impl : public iss::interp::vm_base<ARCH> {
 | 
					template <typename ARCH> class vm_impl : public iss::interp::vm_base<ARCH> {
 | 
				
			||||||
public:
 | 
					public:
 | 
				
			||||||
@@ -130,6 +133,10 @@ protected:
 | 
				
			|||||||
        this->core.wait_until(type);
 | 
					        this->core.wait_until(type);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    using yield_t = boost::coroutines2::coroutine<void>::push_type;
 | 
				
			||||||
 | 
					    using coro_t = boost::coroutines2::coroutine<void>::pull_type;
 | 
				
			||||||
 | 
					    std::vector<coro_t> spawn_blocks;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    template<typename T>
 | 
					    template<typename T>
 | 
				
			||||||
    T& pc_assign(T& val){super::ex_info.branch_taken=true; return val;}
 | 
					    T& pc_assign(T& val){super::ex_info.branch_taken=true; return val;}
 | 
				
			||||||
    inline uint8_t readSpace1(typename super::mem_type_e space, uint64_t addr){
 | 
					    inline uint8_t readSpace1(typename super::mem_type_e space, uint64_t addr){
 | 
				
			||||||
@@ -174,7 +181,18 @@ protected:
 | 
				
			|||||||
        auto sign_mask = 1ULL<<(W-1);
 | 
					        auto sign_mask = 1ULL<<(W-1);
 | 
				
			||||||
        return (from & mask) | ((from & sign_mask) ? ~mask : 0);
 | 
					        return (from & mask) | ((from & sign_mask) ? ~mask : 0);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    inline void process_spawn_blocks() {
 | 
				
			||||||
 | 
					        for(auto it = std::begin(spawn_blocks); it!=std::end(spawn_blocks);)
 | 
				
			||||||
 | 
					             if(*it){
 | 
				
			||||||
 | 
					                 (*it)();
 | 
				
			||||||
 | 
					                 ++it;
 | 
				
			||||||
 | 
					             } else
 | 
				
			||||||
 | 
					                 spawn_blocks.erase(it);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					<%functions.each{ it.eachLine { %>
 | 
				
			||||||
 | 
					    ${it}<%}%>
 | 
				
			||||||
 | 
					<%}%>
 | 
				
			||||||
private:
 | 
					private:
 | 
				
			||||||
    /****************************************************************************
 | 
					    /****************************************************************************
 | 
				
			||||||
     * start opcode definitions
 | 
					     * start opcode definitions
 | 
				
			||||||
@@ -196,11 +214,6 @@ private:
 | 
				
			|||||||
    /* instruction ${idx}: ${instr.name} */
 | 
					    /* instruction ${idx}: ${instr.name} */
 | 
				
			||||||
    compile_ret_t __${generator.functionName(instr.name)}(virt_addr_t& pc, code_word_t instr){
 | 
					    compile_ret_t __${generator.functionName(instr.name)}(virt_addr_t& pc, code_word_t instr){
 | 
				
			||||||
        // pre execution stuff
 | 
					        // pre execution stuff
 | 
				
			||||||
        auto* PC = reinterpret_cast<uint${addrDataWidth}_t*>(this->regs_base_ptr+arch::traits<ARCH>::reg_byte_offsets[arch::traits<ARCH>::PC]);
 | 
					 | 
				
			||||||
        auto NEXT_PC = reinterpret_cast<uint${addrDataWidth}_t*>(this->regs_base_ptr+arch::traits<ARCH>::reg_byte_offsets[arch::traits<ARCH>::NEXT_PC]);
 | 
					 | 
				
			||||||
        *PC=*NEXT_PC;
 | 
					 | 
				
			||||||
        auto* trap_state = reinterpret_cast<uint32_t*>(this->regs_base_ptr+arch::traits<ARCH>::reg_byte_offsets[arch::traits<ARCH>::TRAP_STATE]);
 | 
					 | 
				
			||||||
        *trap_state = *reinterpret_cast<uint32_t*>(this->regs_base_ptr+arch::traits<ARCH>::reg_byte_offsets[arch::traits<ARCH>::PENDING_TRAP]);
 | 
					 | 
				
			||||||
        if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, ${idx});
 | 
					        if(this->sync_exec && PRE_SYNC) this->do_sync(PRE_SYNC, ${idx});
 | 
				
			||||||
        <%instr.fields.eachLine{%>${it}
 | 
					        <%instr.fields.eachLine{%>${it}
 | 
				
			||||||
        <%}%>if(this->disass_enabled){
 | 
					        <%}%>if(this->disass_enabled){
 | 
				
			||||||
@@ -208,6 +221,9 @@ private:
 | 
				
			|||||||
            <%instr.disass.eachLine{%>${it}
 | 
					            <%instr.disass.eachLine{%>${it}
 | 
				
			||||||
            <%}%>
 | 
					            <%}%>
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					        auto* PC = reinterpret_cast<uint${addrDataWidth}_t*>(this->regs_base_ptr+arch::traits<ARCH>::reg_byte_offsets[arch::traits<ARCH>::PC]);
 | 
				
			||||||
 | 
					        auto* NEXT_PC = reinterpret_cast<uint${addrDataWidth}_t*>(this->regs_base_ptr+arch::traits<ARCH>::reg_byte_offsets[arch::traits<ARCH>::NEXT_PC]);
 | 
				
			||||||
 | 
					        auto* trap_state = reinterpret_cast<uint32_t*>(this->regs_base_ptr+arch::traits<ARCH>::reg_byte_offsets[arch::traits<ARCH>::TRAP_STATE]);
 | 
				
			||||||
        // used registers<%instr.usedVariables.each{ k,v->
 | 
					        // used registers<%instr.usedVariables.each{ k,v->
 | 
				
			||||||
            if(v.isArray) {%>
 | 
					            if(v.isArray) {%>
 | 
				
			||||||
        auto* ${k} = reinterpret_cast<uint${nativeTypeSize(v.type.size)}_t*>(this->regs_base_ptr+arch::traits<ARCH>::reg_byte_offsets[arch::traits<ARCH>::${k}0]);<% }else{ %> 
 | 
					        auto* ${k} = reinterpret_cast<uint${nativeTypeSize(v.type.size)}_t*>(this->regs_base_ptr+arch::traits<ARCH>::reg_byte_offsets[arch::traits<ARCH>::${k}0]);<% }else{ %> 
 | 
				
			||||||
@@ -219,6 +235,7 @@ private:
 | 
				
			|||||||
        <%instr.behavior.eachLine{%>${it}
 | 
					        <%instr.behavior.eachLine{%>${it}
 | 
				
			||||||
        <%}%>} catch(...){}
 | 
					        <%}%>} catch(...){}
 | 
				
			||||||
        // post execution stuff
 | 
					        // post execution stuff
 | 
				
			||||||
 | 
					        process_spawn_blocks();
 | 
				
			||||||
        if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, ${idx});
 | 
					        if(this->sync_exec && POST_SYNC) this->do_sync(POST_SYNC, ${idx});
 | 
				
			||||||
        // trap check
 | 
					        // trap check
 | 
				
			||||||
        if(*trap_state!=0){
 | 
					        if(*trap_state!=0){
 | 
				
			||||||
@@ -335,6 +352,8 @@ typename vm_base<ARCH>::virt_addr_t vm_impl<ARCH>::execute_inst(finish_cond_e co
 | 
				
			|||||||
            auto f = decode_inst(insn);
 | 
					            auto f = decode_inst(insn);
 | 
				
			||||||
            auto old_pc = pc.val;
 | 
					            auto old_pc = pc.val;
 | 
				
			||||||
            pc = (this->*f)(pc, insn);
 | 
					            pc = (this->*f)(pc, insn);
 | 
				
			||||||
 | 
					            this->core.reg.PC = this->core.reg.NEXT_PC;
 | 
				
			||||||
 | 
					            this->core.reg.trap_state = this->core.reg.pending_trap;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    return pc;
 | 
					    return pc;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -201,7 +201,7 @@ public:
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    void disass_output(uint64_t pc, const std::string instr) override {
 | 
					    void disass_output(uint64_t pc, const std::string instr) override {
 | 
				
			||||||
        CLOG(INFO, disass) << fmt::format("0x{:016x}    {:40} [s:0x{:x};c:{}]",
 | 
					        CLOG(INFO, disass) << fmt::format("0x{:016x}    {:40} [s:0x{:x};c:{}]",
 | 
				
			||||||
                pc, instr, (reg_t)state.mstatus, this->reg.icount);
 | 
					                pc, instr, (reg_t)state.mstatus, this->reg.icount + cycle_offset);
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    iss::instrumentation_if *get_instrumentation_if() override { return &instr_if; }
 | 
					    iss::instrumentation_if *get_instrumentation_if() override { return &instr_if; }
 | 
				
			||||||
@@ -233,11 +233,15 @@ protected:
 | 
				
			|||||||
         */
 | 
					         */
 | 
				
			||||||
        const std::string core_type_name() const override { return traits<BASE>::core_type; }
 | 
					        const std::string core_type_name() const override { return traits<BASE>::core_type; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        virtual uint64_t get_pc() { return arch.get_pc(); };
 | 
					        uint64_t get_pc() override { return arch.get_pc(); };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        virtual uint64_t get_next_pc() { return arch.get_next_pc(); };
 | 
					        uint64_t get_next_pc() override { return arch.get_next_pc(); };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        virtual void set_curr_instr_cycles(unsigned cycles) { arch.cycle_offset += cycles - 1; };
 | 
					        uint64_t get_instr_count() { return arch.reg.icount; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        uint64_t get_total_cycles() override { return arch.reg.icount + arch.cycle_offset; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        void set_curr_instr_cycles(unsigned cycles) override { arch.cycle_offset += cycles - 1; };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        riscv_hart_m_p<BASE, FEAT> &arch;
 | 
					        riscv_hart_m_p<BASE, FEAT> &arch;
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -293,21 +293,21 @@ public:
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    std::pair<uint64_t, bool> load_file(std::string name, int type = -1) override;
 | 
					    std::pair<uint64_t, bool> load_file(std::string name, int type = -1) override;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    virtual phys_addr_t virt2phys(const iss::addr_t &addr) override;
 | 
					    phys_addr_t virt2phys(const iss::addr_t &addr) override;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    iss::status read(const address_type type, const access_type access, const uint32_t space,
 | 
					    iss::status read(const address_type type, const access_type access, const uint32_t space,
 | 
				
			||||||
            const uint64_t addr, const unsigned length, uint8_t *const data) override;
 | 
					            const uint64_t addr, const unsigned length, uint8_t *const data) override;
 | 
				
			||||||
    iss::status write(const address_type type, const access_type access, const uint32_t space,
 | 
					    iss::status write(const address_type type, const access_type access, const uint32_t space,
 | 
				
			||||||
            const uint64_t addr, const unsigned length, const uint8_t *const data) override;
 | 
					            const uint64_t addr, const unsigned length, const uint8_t *const data) override;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    virtual uint64_t enter_trap(uint64_t flags) override { return riscv_hart_msu_vp::enter_trap(flags, fault_data, fault_data); }
 | 
					    uint64_t enter_trap(uint64_t flags) override { return riscv_hart_msu_vp::enter_trap(flags, fault_data, fault_data); }
 | 
				
			||||||
    virtual uint64_t enter_trap(uint64_t flags, uint64_t addr, uint64_t instr) override;
 | 
					    uint64_t enter_trap(uint64_t flags, uint64_t addr, uint64_t instr) override;
 | 
				
			||||||
    virtual uint64_t leave_trap(uint64_t flags) override;
 | 
					    uint64_t leave_trap(uint64_t flags) override;
 | 
				
			||||||
    void wait_until(uint64_t flags) override;
 | 
					    void wait_until(uint64_t flags) override;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    void disass_output(uint64_t pc, const std::string instr) override {
 | 
					    void disass_output(uint64_t pc, const std::string instr) override {
 | 
				
			||||||
        CLOG(INFO, disass) << fmt::format("0x{:016x}    {:40} [p:{};s:0x{:x};c:{}]",
 | 
					        CLOG(INFO, disass) << fmt::format("0x{:016x}    {:40} [p:{};s:0x{:x};c:{}]",
 | 
				
			||||||
                pc, instr, lvl[this->reg.PRIV], (reg_t)state.mstatus, this->reg.ccount);
 | 
					                pc, instr, lvl[this->reg.PRIV], (reg_t)state.mstatus, this->reg.ccount + cycle_offset);
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    iss::instrumentation_if *get_instrumentation_if() override { return &instr_if; }
 | 
					    iss::instrumentation_if *get_instrumentation_if() override { return &instr_if; }
 | 
				
			||||||
@@ -340,6 +340,10 @@ protected:
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        virtual uint64_t get_next_pc() { return arch.get_next_pc(); };
 | 
					        virtual uint64_t get_next_pc() { return arch.get_next_pc(); };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        uint64_t get_instr_count() { return arch.reg.icount; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        uint64_t get_total_cycles() override { return arch.reg.icount + arch.cycle_offset; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        virtual void set_curr_instr_cycles(unsigned cycles) { arch.cycle_offset += cycles - 1; };
 | 
					        virtual void set_curr_instr_cycles(unsigned cycles) { arch.cycle_offset += cycles - 1; };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        riscv_hart_msu_vp<BASE> &arch;
 | 
					        riscv_hart_msu_vp<BASE> &arch;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -207,16 +207,16 @@ public:
 | 
				
			|||||||
    iss::status write(const address_type type, const access_type access, const uint32_t space,
 | 
					    iss::status write(const address_type type, const access_type access, const uint32_t space,
 | 
				
			||||||
            const uint64_t addr, const unsigned length, const uint8_t *const data) override;
 | 
					            const uint64_t addr, const unsigned length, const uint8_t *const data) override;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    virtual uint64_t enter_trap(uint64_t flags) override { return riscv_hart_mu_p::enter_trap(flags, fault_data, fault_data); }
 | 
					    uint64_t enter_trap(uint64_t flags) override { return riscv_hart_mu_p::enter_trap(flags, fault_data, fault_data); }
 | 
				
			||||||
    virtual uint64_t enter_trap(uint64_t flags, uint64_t addr, uint64_t instr) override;
 | 
					    uint64_t enter_trap(uint64_t flags, uint64_t addr, uint64_t instr) override;
 | 
				
			||||||
    virtual uint64_t leave_trap(uint64_t flags) override;
 | 
					    uint64_t leave_trap(uint64_t flags) override;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const reg_t& get_mhartid() const { return mhartid_reg;	}
 | 
					    const reg_t& get_mhartid() const { return mhartid_reg;	}
 | 
				
			||||||
	void set_mhartid(reg_t mhartid) { mhartid_reg = mhartid; };
 | 
						void set_mhartid(reg_t mhartid) { mhartid_reg = mhartid; };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    void disass_output(uint64_t pc, const std::string instr) override {
 | 
					    void disass_output(uint64_t pc, const std::string instr) override {
 | 
				
			||||||
        CLOG(INFO, disass) << fmt::format("0x{:016x}    {:40} [p:{};s:0x{:x};c:{}]",
 | 
					        CLOG(INFO, disass) << fmt::format("0x{:016x}    {:40} [p:{};s:0x{:x};c:{}]",
 | 
				
			||||||
                pc, instr, lvl[this->reg.PRIV], (reg_t)state.mstatus, this->reg.icount);
 | 
					                pc, instr, lvl[this->reg.PRIV], (reg_t)state.mstatus, this->reg.icount + cycle_offset);
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    iss::instrumentation_if *get_instrumentation_if() override { return &instr_if; }
 | 
					    iss::instrumentation_if *get_instrumentation_if() override { return &instr_if; }
 | 
				
			||||||
@@ -252,6 +252,10 @@ protected:
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        virtual uint64_t get_next_pc() { return arch.get_next_pc(); };
 | 
					        virtual uint64_t get_next_pc() { return arch.get_next_pc(); };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        uint64_t get_instr_count() { return arch.reg.icount; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        uint64_t get_total_cycles() override { return arch.reg.icount + arch.cycle_offset; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        virtual void set_curr_instr_cycles(unsigned cycles) { arch.cycle_offset += cycles - 1; };
 | 
					        virtual void set_curr_instr_cycles(unsigned cycles) { arch.cycle_offset += cycles - 1; };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        riscv_hart_mu_p<BASE, FEAT> &arch;
 | 
					        riscv_hart_mu_p<BASE, FEAT> &arch;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -217,7 +217,7 @@ struct tgc_c: public arch_if {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    inline uint32_t get_last_branch() { return reg.last_branch; }
 | 
					    inline uint32_t get_last_branch() { return reg.last_branch; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
protected:
 | 
					
 | 
				
			||||||
#pragma pack(push, 1)
 | 
					#pragma pack(push, 1)
 | 
				
			||||||
    struct TGC_C_regs { 
 | 
					    struct TGC_C_regs { 
 | 
				
			||||||
        uint32_t X0 = 0; 
 | 
					        uint32_t X0 = 0; 
 | 
				
			||||||
@@ -258,7 +258,6 @@ protected:
 | 
				
			|||||||
        uint32_t DPC = 0;
 | 
					        uint32_t DPC = 0;
 | 
				
			||||||
        uint32_t trap_state = 0, pending_trap = 0;
 | 
					        uint32_t trap_state = 0, pending_trap = 0;
 | 
				
			||||||
        uint64_t icount = 0;
 | 
					        uint64_t icount = 0;
 | 
				
			||||||
        uint64_t cycle = 0;
 | 
					 | 
				
			||||||
        uint64_t instret = 0;
 | 
					        uint64_t instret = 0;
 | 
				
			||||||
        uint32_t last_branch;
 | 
					        uint32_t last_branch;
 | 
				
			||||||
    } reg;
 | 
					    } reg;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -37,9 +37,9 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#include "iss/instrumentation_if.h"
 | 
					#include "iss/instrumentation_if.h"
 | 
				
			||||||
#include "iss/vm_plugin.h"
 | 
					#include "iss/vm_plugin.h"
 | 
				
			||||||
#include <json/json.h>
 | 
					 | 
				
			||||||
#include <string>
 | 
					#include <string>
 | 
				
			||||||
#include <unordered_map>
 | 
					#include <unordered_map>
 | 
				
			||||||
 | 
					#include <vector>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace iss {
 | 
					namespace iss {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -49,11 +49,13 @@ class cycle_estimate: public iss::vm_plugin {
 | 
				
			|||||||
	BEGIN_BF_DECL(instr_desc, uint32_t)
 | 
						BEGIN_BF_DECL(instr_desc, uint32_t)
 | 
				
			||||||
		BF_FIELD(taken, 24, 8)
 | 
							BF_FIELD(taken, 24, 8)
 | 
				
			||||||
		BF_FIELD(not_taken, 16, 8)
 | 
							BF_FIELD(not_taken, 16, 8)
 | 
				
			||||||
		BF_FIELD(size, 0, 16)
 | 
					        BF_FIELD(is_branch, 8, 8)
 | 
				
			||||||
		instr_desc(uint32_t size, uint32_t taken, uint32_t not_taken): instr_desc() {
 | 
					        BF_FIELD(size, 0, 8)
 | 
				
			||||||
 | 
							instr_desc(uint32_t size, uint32_t taken, uint32_t not_taken, bool branch): instr_desc() {
 | 
				
			||||||
			this->size=size;
 | 
								this->size=size;
 | 
				
			||||||
			this->taken=taken;
 | 
								this->taken=taken;
 | 
				
			||||||
			this->not_taken=not_taken;
 | 
								this->not_taken=not_taken;
 | 
				
			||||||
 | 
								this->is_branch=branch;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	END_BF_DECL();
 | 
						END_BF_DECL();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -64,7 +66,7 @@ public:
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    cycle_estimate(const cycle_estimate &&) = delete;
 | 
					    cycle_estimate(const cycle_estimate &&) = delete;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    cycle_estimate(std::string config_file_name);
 | 
					    cycle_estimate(std::string const& config_file_name);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    virtual ~cycle_estimate();
 | 
					    virtual ~cycle_estimate();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -88,7 +90,7 @@ private:
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
    std::unordered_map<std::pair<uint64_t, uint64_t>, uint64_t, pair_hash> blocks;
 | 
					    std::unordered_map<std::pair<uint64_t, uint64_t>, uint64_t, pair_hash> blocks;
 | 
				
			||||||
    Json::Value root;
 | 
					    std::string config_file_name;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										99
									
								
								incl/iss/plugin/pctrace.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										99
									
								
								incl/iss/plugin/pctrace.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,99 @@
 | 
				
			|||||||
 | 
					/*******************************************************************************
 | 
				
			||||||
 | 
					 * Copyright (C) 2017, 2018, MINRES Technologies GmbH
 | 
				
			||||||
 | 
					 * All rights reserved.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Redistribution and use in source and binary forms, with or without
 | 
				
			||||||
 | 
					 * modification, are permitted provided that the following conditions are met:
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * 1. Redistributions of source code must retain the above copyright notice,
 | 
				
			||||||
 | 
					 *    this list of conditions and the following disclaimer.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * 2. Redistributions in binary form must reproduce the above copyright notice,
 | 
				
			||||||
 | 
					 *    this list of conditions and the following disclaimer in the documentation
 | 
				
			||||||
 | 
					 *    and/or other materials provided with the distribution.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * 3. Neither the name of the copyright holder nor the names of its contributors
 | 
				
			||||||
 | 
					 *    may be used to endorse or promote products derived from this software
 | 
				
			||||||
 | 
					 *    without specific prior written permission.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 | 
				
			||||||
 | 
					 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
				
			||||||
 | 
					 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 | 
				
			||||||
 | 
					 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 | 
				
			||||||
 | 
					 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 | 
				
			||||||
 | 
					 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 | 
				
			||||||
 | 
					 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 | 
				
			||||||
 | 
					 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 | 
				
			||||||
 | 
					 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 | 
				
			||||||
 | 
					 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 | 
				
			||||||
 | 
					 * POSSIBILITY OF SUCH DAMAGE.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Contributors:
 | 
				
			||||||
 | 
					 *       eyck@minres.com - initial API and implementation
 | 
				
			||||||
 | 
					 ******************************************************************************/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef _ISS_PLUGIN_COV_H_
 | 
				
			||||||
 | 
					#define _ISS_PLUGIN_COV_H_
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <iss/vm_plugin.h>
 | 
				
			||||||
 | 
					#include "iss/instrumentation_if.h"
 | 
				
			||||||
 | 
					#include <json/json.h>
 | 
				
			||||||
 | 
					#include <string>
 | 
				
			||||||
 | 
					#include <fstream>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace iss {
 | 
				
			||||||
 | 
					namespace plugin {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class cov : public iss::vm_plugin {
 | 
				
			||||||
 | 
					    struct instr_delay {
 | 
				
			||||||
 | 
					        std::string instr_name;
 | 
				
			||||||
 | 
					        size_t size;
 | 
				
			||||||
 | 
					        size_t not_taken_delay;
 | 
				
			||||||
 | 
					        size_t taken_delay;
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					    BEGIN_BF_DECL(instr_desc, uint32_t)
 | 
				
			||||||
 | 
					        BF_FIELD(taken, 24, 8)
 | 
				
			||||||
 | 
					        BF_FIELD(not_taken, 16, 8)
 | 
				
			||||||
 | 
					        BF_FIELD(is_branch, 8, 8)
 | 
				
			||||||
 | 
					        BF_FIELD(size, 0, 8)
 | 
				
			||||||
 | 
					        instr_desc(uint32_t size, uint32_t taken, uint32_t not_taken, bool branch): instr_desc() {
 | 
				
			||||||
 | 
					            this->size=size;
 | 
				
			||||||
 | 
					            this->taken=taken;
 | 
				
			||||||
 | 
					            this->not_taken=not_taken;
 | 
				
			||||||
 | 
					            this->is_branch=branch;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    END_BF_DECL();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    cov(const cov &) = delete;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    cov(const cov &&) = delete;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    cov(std::string const &);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    virtual ~cov();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    cov &operator=(const cov &) = delete;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    cov &operator=(const cov &&) = delete;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    bool registration(const char *const version, vm_if &arch) override;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    sync_type get_sync() override { return POST_SYNC; };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void callback(instr_info_t, exec_info const&) override;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					private:
 | 
				
			||||||
 | 
					    iss::instrumentation_if *instr_if  {nullptr};
 | 
				
			||||||
 | 
					    std::ofstream output;
 | 
				
			||||||
 | 
					    std::string filename;
 | 
				
			||||||
 | 
					    std::vector<instr_desc> delays;
 | 
				
			||||||
 | 
					    bool jumped, first;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif /* _ISS_PLUGIN_COV_H_ */
 | 
				
			||||||
							
								
								
									
										11
									
								
								src/main.cpp
									
									
									
									
									
								
							
							
						
						
									
										11
									
								
								src/main.cpp
									
									
									
									
									
								
							@@ -44,6 +44,11 @@ using tgc_c_plat_type = iss::arch::riscv_hart_m_p<iss::arch::tgc_c>;
 | 
				
			|||||||
#include "iss/arch/tgc_b.h"
 | 
					#include "iss/arch/tgc_b.h"
 | 
				
			||||||
using tgc_b_plat_type = iss::arch::riscv_hart_m_p<iss::arch::tgc_b>;
 | 
					using tgc_b_plat_type = iss::arch::riscv_hart_m_p<iss::arch::tgc_b>;
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					#ifdef CORE_TGC_C_XRB_NN
 | 
				
			||||||
 | 
					#include "iss/arch/riscv_hart_m_p.h"
 | 
				
			||||||
 | 
					#include "iss/arch/tgc_c_xrb_nn.h"
 | 
				
			||||||
 | 
					using tgc_c_xrb_nn_plat_type = iss::arch::riscv_hart_m_p<iss::arch::tgc_c_xrb_nn>;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
#ifdef CORE_TGC_D
 | 
					#ifdef CORE_TGC_D
 | 
				
			||||||
#include "iss/arch/riscv_hart_mu_p.h"
 | 
					#include "iss/arch/riscv_hart_mu_p.h"
 | 
				
			||||||
#include "iss/arch/tgc_d.h"
 | 
					#include "iss/arch/tgc_d.h"
 | 
				
			||||||
@@ -152,6 +157,12 @@ int main(int argc, char *argv[]) {
 | 
				
			|||||||
                iss::create_cpu<tgc_b_plat_type>(clim["backend"].as<std::string>(), clim["gdb-port"].as<unsigned>());
 | 
					                iss::create_cpu<tgc_b_plat_type>(clim["backend"].as<std::string>(), clim["gdb-port"].as<unsigned>());
 | 
				
			||||||
        } else
 | 
					        } else
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					#ifdef CORE_TGC_C_XRB_NN
 | 
				
			||||||
 | 
					        if (isa_opt == "tgc_c_xrb_nn") {
 | 
				
			||||||
 | 
					            std::tie(cpu, vm) =
 | 
				
			||||||
 | 
					                iss::create_cpu<tgc_c_xrb_nn_plat_type>(clim["backend"].as<std::string>(), clim["gdb-port"].as<unsigned>());
 | 
				
			||||||
 | 
					        } else
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
#ifdef CORE_TGC_D
 | 
					#ifdef CORE_TGC_D
 | 
				
			||||||
        if (isa_opt == "tgc_d") {
 | 
					        if (isa_opt == "tgc_d") {
 | 
				
			||||||
            std::tie(cpu, vm) =
 | 
					            std::tie(cpu, vm) =
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -36,58 +36,82 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#include <iss/arch_if.h>
 | 
					#include <iss/arch_if.h>
 | 
				
			||||||
#include <util/logging.h>
 | 
					#include <util/logging.h>
 | 
				
			||||||
 | 
					#include <rapidjson/document.h>
 | 
				
			||||||
 | 
					#include <rapidjson/istreamwrapper.h>
 | 
				
			||||||
 | 
					#include "rapidjson/writer.h"
 | 
				
			||||||
 | 
					#include "rapidjson/stringbuffer.h"
 | 
				
			||||||
 | 
					#include <rapidjson/ostreamwrapper.h>
 | 
				
			||||||
 | 
					#include <rapidjson/error/en.h>
 | 
				
			||||||
#include <fstream>
 | 
					#include <fstream>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
iss::plugin::cycle_estimate::cycle_estimate(std::string config_file_name)
 | 
					using namespace rapidjson;
 | 
				
			||||||
 | 
					using namespace std;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					iss::plugin::cycle_estimate::cycle_estimate(string const& config_file_name)
 | 
				
			||||||
: arch_instr(nullptr)
 | 
					: arch_instr(nullptr)
 | 
				
			||||||
 | 
					, config_file_name(config_file_name)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    if (config_file_name.length() > 0) {
 | 
					 | 
				
			||||||
        std::ifstream is(config_file_name);
 | 
					 | 
				
			||||||
        if (is.is_open()) {
 | 
					 | 
				
			||||||
            try {
 | 
					 | 
				
			||||||
                is >> root;
 | 
					 | 
				
			||||||
            } catch (Json::RuntimeError &e) {
 | 
					 | 
				
			||||||
                LOG(ERR) << "Could not parse input file " << config_file_name << ", reason: " << e.what();
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        } else {
 | 
					 | 
				
			||||||
            LOG(ERR) << "Could not open input file " << config_file_name;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
iss::plugin::cycle_estimate::~cycle_estimate() {
 | 
					iss::plugin::cycle_estimate::~cycle_estimate() {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
bool iss::plugin::cycle_estimate::registration(const char* const version, vm_if& vm) {
 | 
					bool iss::plugin::cycle_estimate::registration(const char* const version, vm_if& vm) {
 | 
				
			||||||
	arch_instr = vm.get_arch()->get_instrumentation_if();
 | 
					    arch_instr = vm.get_arch()->get_instrumentation_if();
 | 
				
			||||||
	if(!arch_instr) return false;
 | 
					    if(!arch_instr) return false;
 | 
				
			||||||
	const std::string  core_name = arch_instr->core_type_name();
 | 
					    const string  core_name = arch_instr->core_type_name();
 | 
				
			||||||
    Json::Value &val = root[core_name];
 | 
					    if (config_file_name.length() > 0) {
 | 
				
			||||||
    if(!val.isNull() && val.isArray()){
 | 
					        ifstream is(config_file_name);
 | 
				
			||||||
    	delays.reserve(val.size());
 | 
					        if (is.is_open()) {
 | 
				
			||||||
    	for(auto it:val){
 | 
					            try {
 | 
				
			||||||
    		auto name = it["name"];
 | 
					                IStreamWrapper isw(is);
 | 
				
			||||||
    		auto size = it["size"];
 | 
					                Document d;
 | 
				
			||||||
    		auto delay = it["delay"];
 | 
					                ParseResult ok = d.ParseStream(isw);
 | 
				
			||||||
    		if(!name.isString() || !size.isUInt() || !(delay.isUInt() || delay.isArray())) throw std::runtime_error("JSON parse error");
 | 
					                if(ok) {
 | 
				
			||||||
    		if(delay.isUInt()){
 | 
					                    Value& val = d[core_name.c_str()];
 | 
				
			||||||
				delays.push_back(instr_desc{size.asUInt(), delay.asUInt(), 0});
 | 
					                    if(val.IsArray()){
 | 
				
			||||||
    		} else {
 | 
					                        delays.reserve(val.Size());
 | 
				
			||||||
				delays.push_back(instr_desc{size.asUInt(), delay[0].asUInt(), delay[1].asUInt()});
 | 
					                        for (auto it = val.Begin(); it != val.End(); ++it) {
 | 
				
			||||||
    		}
 | 
					                            auto& name = (*it)["name"];
 | 
				
			||||||
    	}
 | 
					                            auto& size = (*it)["size"];
 | 
				
			||||||
    } else {
 | 
					                            auto& delay = (*it)["delay"];
 | 
				
			||||||
        LOG(ERR)<<"plugin cycle_estimate: could not find an entry for "<<core_name<<" in JSON file"<<std::endl;
 | 
					                            auto& branch = (*it)["branch"];
 | 
				
			||||||
 | 
					                            if(delay.IsArray()) {
 | 
				
			||||||
 | 
					                                auto dt = delay[0].Get<unsigned>();
 | 
				
			||||||
 | 
					                                auto dnt = delay[1].Get<unsigned>();
 | 
				
			||||||
 | 
					                                delays.push_back(instr_desc{size.Get<unsigned>(), dt, dnt, branch.Get<bool>()});
 | 
				
			||||||
 | 
					                            } else if(delay.Is<unsigned>()) {
 | 
				
			||||||
 | 
					                                auto d = delay.Get<unsigned>();
 | 
				
			||||||
 | 
					                                delays.push_back(instr_desc{size.Get<unsigned>(), d, d, branch.Get<bool>()});
 | 
				
			||||||
 | 
					                            } else
 | 
				
			||||||
 | 
					                                throw runtime_error("JSON parse error");
 | 
				
			||||||
 | 
					                       }
 | 
				
			||||||
 | 
					                    } else {
 | 
				
			||||||
 | 
					                        LOG(ERR)<<"plugin cycle_estimate: could not find an entry for "<<core_name<<" in JSON file"<<endl;
 | 
				
			||||||
 | 
					                        return false;
 | 
				
			||||||
 | 
					                   }
 | 
				
			||||||
 | 
					                } else {
 | 
				
			||||||
 | 
					                    LOG(ERR)<<"plugin cycle_estimate: could not parse in JSON file at "<< ok.Offset()<<": "<<GetParseError_En(ok.Code())<<endl;
 | 
				
			||||||
 | 
					                    return false;
 | 
				
			||||||
 | 
					               }
 | 
				
			||||||
 | 
					            } catch (runtime_error &e) {
 | 
				
			||||||
 | 
					                LOG(ERR) << "Could not parse input file " << config_file_name << ", reason: " << e.what();
 | 
				
			||||||
 | 
					                return false;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            LOG(ERR) << "Could not open input file " << config_file_name;
 | 
				
			||||||
 | 
					            return false;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
	return true;
 | 
					    return true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void iss::plugin::cycle_estimate::callback(instr_info_t instr_info, exec_info const&) {
 | 
					void iss::plugin::cycle_estimate::callback(instr_info_t instr_info, exec_info const& exc_info) {
 | 
				
			||||||
    assert(arch_instr && "No instrumentation interface available but callback executed");
 | 
					    assert(arch_instr && "No instrumentation interface available but callback executed");
 | 
				
			||||||
	auto entry = delays[instr_info.instr_id];
 | 
					    auto entry = delays[instr_info.instr_id];
 | 
				
			||||||
	bool taken = (arch_instr->get_next_pc()-arch_instr->get_pc()) != (entry.size/8);
 | 
					    bool taken = exc_info.branch_taken;
 | 
				
			||||||
    if (taken && entry.taken > 1)
 | 
					    if (exc_info.branch_taken && (entry.taken > 1))
 | 
				
			||||||
        arch_instr->set_curr_instr_cycles(entry.taken);
 | 
					        arch_instr->set_curr_instr_cycles(entry.taken);
 | 
				
			||||||
    else if (entry.not_taken > 1)
 | 
					    else if (entry.not_taken > 1)
 | 
				
			||||||
        arch_instr->set_curr_instr_cycles(entry.not_taken);
 | 
					        arch_instr->set_curr_instr_cycles(entry.not_taken);
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										133
									
								
								src/plugin/pctrace.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										133
									
								
								src/plugin/pctrace.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,133 @@
 | 
				
			|||||||
 | 
					#include <iss/arch_if.h>
 | 
				
			||||||
 | 
					#include <iss/plugin/pctrace.h>
 | 
				
			||||||
 | 
					#include <util/logging.h>
 | 
				
			||||||
 | 
					#include <rapidjson/document.h>
 | 
				
			||||||
 | 
					#include <rapidjson/istreamwrapper.h>
 | 
				
			||||||
 | 
					#include "rapidjson/writer.h"
 | 
				
			||||||
 | 
					#include "rapidjson/stringbuffer.h"
 | 
				
			||||||
 | 
					#include <rapidjson/ostreamwrapper.h>
 | 
				
			||||||
 | 
					#include <rapidjson/error/en.h>
 | 
				
			||||||
 | 
					#include <fstream>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <iostream>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					using namespace rapidjson;
 | 
				
			||||||
 | 
					using namespace std;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					iss::plugin::cov::cov(std::string const &filename)
 | 
				
			||||||
 | 
					    : instr_if(nullptr)
 | 
				
			||||||
 | 
					    , filename(filename)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    output.open("output.trc");
 | 
				
			||||||
 | 
					    jumped = false;
 | 
				
			||||||
 | 
					    first = true;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					iss::plugin::cov::~cov() {
 | 
				
			||||||
 | 
					    output.close();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool iss::plugin::cov::registration(const char *const version, vm_if& vm) {
 | 
				
			||||||
 | 
					    instr_if = vm.get_arch()->get_instrumentation_if();
 | 
				
			||||||
 | 
					    if(!instr_if) return false;
 | 
				
			||||||
 | 
					    const string  core_name = instr_if->core_type_name();
 | 
				
			||||||
 | 
					    if (filename.length() > 0) {
 | 
				
			||||||
 | 
					        ifstream is(filename);
 | 
				
			||||||
 | 
					        if (is.is_open()) {
 | 
				
			||||||
 | 
					            try {
 | 
				
			||||||
 | 
					                IStreamWrapper isw(is);
 | 
				
			||||||
 | 
					                Document d;
 | 
				
			||||||
 | 
					                ParseResult ok = d.ParseStream(isw);
 | 
				
			||||||
 | 
					                if(ok) {
 | 
				
			||||||
 | 
					                    Value& val = d[core_name.c_str()];
 | 
				
			||||||
 | 
					                    if(val.IsArray()){
 | 
				
			||||||
 | 
					                        delays.reserve(val.Size());
 | 
				
			||||||
 | 
					                        for (auto it = val.Begin(); it != val.End(); ++it) {
 | 
				
			||||||
 | 
					                            auto& name = (*it)["name"];
 | 
				
			||||||
 | 
					                            auto& size = (*it)["size"];
 | 
				
			||||||
 | 
					                            auto& delay = (*it)["delay"];
 | 
				
			||||||
 | 
					                            auto& branch = (*it)["branch"];
 | 
				
			||||||
 | 
					                            if(delay.IsArray()) {
 | 
				
			||||||
 | 
					                                auto dt = delay[0].Get<unsigned>();
 | 
				
			||||||
 | 
					                                auto dnt = delay[1].Get<unsigned>();
 | 
				
			||||||
 | 
					                                delays.push_back(instr_desc{size.Get<unsigned>(), dt, dnt, branch.Get<bool>()});
 | 
				
			||||||
 | 
					                            } else if(delay.Is<unsigned>()) {
 | 
				
			||||||
 | 
					                                auto d = delay.Get<unsigned>();
 | 
				
			||||||
 | 
					                                delays.push_back(instr_desc{size.Get<unsigned>(), d, d, branch.Get<bool>()});
 | 
				
			||||||
 | 
					                            } else
 | 
				
			||||||
 | 
					                                throw runtime_error("JSON parse error");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
 | 
					                    } else {
 | 
				
			||||||
 | 
					                        LOG(ERR)<<"plugin cycle_estimate: could not find an entry for "<<core_name<<" in JSON file"<<endl;
 | 
				
			||||||
 | 
					                        return false;
 | 
				
			||||||
 | 
					                   }
 | 
				
			||||||
 | 
					                } else {
 | 
				
			||||||
 | 
					                    LOG(ERR)<<"plugin cycle_estimate: could not parse in JSON file at "<< ok.Offset()<<": "<<GetParseError_En(ok.Code())<<endl;
 | 
				
			||||||
 | 
					                    return false;
 | 
				
			||||||
 | 
					               }
 | 
				
			||||||
 | 
					            } catch (runtime_error &e) {
 | 
				
			||||||
 | 
					                LOG(ERR) << "Could not parse input file " << filename << ", reason: " << e.what();
 | 
				
			||||||
 | 
					                return false;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            LOG(ERR) << "Could not open input file " << filename;
 | 
				
			||||||
 | 
					            return false;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					inline string formatPC(uint64_t pc) {
 | 
				
			||||||
 | 
					    stringstream stream;
 | 
				
			||||||
 | 
					    stream << "0x" << std::hex << pc;
 | 
				
			||||||
 | 
					    return stream.str();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void iss::plugin::cov::callback(instr_info_t iinfo, const exec_info& einfo) {
 | 
				
			||||||
 | 
					//    auto delay = 0;
 | 
				
			||||||
 | 
					//    auto entry = delays[iinfo.instr_id];
 | 
				
			||||||
 | 
					//    bool taken = einfo.branch_taken;
 | 
				
			||||||
 | 
					//    if (einfo.branch_taken)
 | 
				
			||||||
 | 
					//        delay = entry.taken;
 | 
				
			||||||
 | 
					//    else
 | 
				
			||||||
 | 
					//        delay = entry.not_taken;
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					//    if (first){
 | 
				
			||||||
 | 
					//        output << formatPC(instr_if->get_pc()) << "," << delay;
 | 
				
			||||||
 | 
					//        first = false;
 | 
				
			||||||
 | 
					//    }
 | 
				
			||||||
 | 
					//    if(instr_if->get_next_pc()-instr_if->get_pc() != delays[iinfo.instr_id].size/8){
 | 
				
			||||||
 | 
					//        //The goal is to keep the output in start-target pairs, so after a jump the target address needs to get written
 | 
				
			||||||
 | 
					//        //to the output. If the target happens to also be a start, we keep the pairing by adding a 0-delay entry.
 | 
				
			||||||
 | 
					//        if (jumped)
 | 
				
			||||||
 | 
					//            output <<"\n" <<formatPC(instr_if->get_pc()) << "," << 0;
 | 
				
			||||||
 | 
					//        output <<"\n" << formatPC(instr_if->get_pc()) << "," << delay;
 | 
				
			||||||
 | 
					//        jumped = true;
 | 
				
			||||||
 | 
					//    }
 | 
				
			||||||
 | 
					//    else{
 | 
				
			||||||
 | 
					//        if (jumped){
 | 
				
			||||||
 | 
					//            output <<"\n" << formatPC(instr_if->get_pc()) << "," << delay;
 | 
				
			||||||
 | 
					//            jumped = false;
 | 
				
			||||||
 | 
					//        }
 | 
				
			||||||
 | 
					//        else if(delay!=1){
 | 
				
			||||||
 | 
					//            output <<"\n" << formatPC(instr_if->get_pc()) << "," << delay;
 | 
				
			||||||
 | 
					//            output <<"\n" << formatPC(instr_if->get_pc()) << "," << 0;
 | 
				
			||||||
 | 
					//        }
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					//    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//source code for the full output
 | 
				
			||||||
 | 
					    auto delay = 0;
 | 
				
			||||||
 | 
					    auto entry = delays[iinfo.instr_id];
 | 
				
			||||||
 | 
					    bool taken = einfo.branch_taken;
 | 
				
			||||||
 | 
					    if (einfo.branch_taken)
 | 
				
			||||||
 | 
					        delay = entry.taken;
 | 
				
			||||||
 | 
					    else
 | 
				
			||||||
 | 
					       delay = entry.not_taken;
 | 
				
			||||||
 | 
					    output<<std::hex <<"0x" << instr_if->get_pc() <<"," << delay << "\n";
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -69,6 +69,8 @@ using tgc_d_xrb_nn_plat_type = iss::arch::riscv_hart_mu_p<iss::arch::tgc_d_xrb_n
 | 
				
			|||||||
#include <array>
 | 
					#include <array>
 | 
				
			||||||
#include <iss/plugin/cycle_estimate.h>
 | 
					#include <iss/plugin/cycle_estimate.h>
 | 
				
			||||||
#include <iss/plugin/instruction_count.h>
 | 
					#include <iss/plugin/instruction_count.h>
 | 
				
			||||||
 | 
					#include <iss/plugin/pctrace.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// clang-format on
 | 
					// clang-format on
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define STR(X) #X
 | 
					#define STR(X) #X
 | 
				
			||||||
@@ -134,7 +136,8 @@ public:
 | 
				
			|||||||
        if (!owner->disass_output(pc, instr)) {
 | 
					        if (!owner->disass_output(pc, instr)) {
 | 
				
			||||||
            std::stringstream s;
 | 
					            std::stringstream s;
 | 
				
			||||||
            s << "[p:" << lvl[this->reg.PRIV] << ";s:0x" << std::hex << std::setfill('0')
 | 
					            s << "[p:" << lvl[this->reg.PRIV] << ";s:0x" << std::hex << std::setfill('0')
 | 
				
			||||||
              << std::setw(sizeof(reg_t) * 2) << (reg_t)this->state.mstatus << std::dec << ";c:" << this->reg.icount << "]";
 | 
					              << std::setw(sizeof(reg_t) * 2) << (reg_t)this->state.mstatus << std::dec << ";c:"
 | 
				
			||||||
 | 
					              << this->reg.icount + this->cycle_offset << "]";
 | 
				
			||||||
            SCCDEBUG(owner->name())<<"disass: "
 | 
					            SCCDEBUG(owner->name())<<"disass: "
 | 
				
			||||||
                << "0x" << std::setw(16) << std::right << std::setfill('0') << std::hex << pc << "\t\t" << std::setw(40)
 | 
					                << "0x" << std::setw(16) << std::right << std::setfill('0') << std::hex << pc << "\t\t" << std::setw(40)
 | 
				
			||||||
                << std::setfill(' ') << std::left << instr << s.str();
 | 
					                << std::setfill(' ') << std::left << instr << s.str();
 | 
				
			||||||
@@ -423,6 +426,10 @@ void core_complex::before_end_of_elaboration() {
 | 
				
			|||||||
                auto *plugin = new iss::plugin::cycle_estimate(filename);
 | 
					                auto *plugin = new iss::plugin::cycle_estimate(filename);
 | 
				
			||||||
                cpu->vm->register_plugin(*plugin);
 | 
					                cpu->vm->register_plugin(*plugin);
 | 
				
			||||||
                plugin_list.push_back(plugin);
 | 
					                plugin_list.push_back(plugin);
 | 
				
			||||||
 | 
					            } else if (plugin_name == "pctrace") {
 | 
				
			||||||
 | 
					                auto *plugin = new iss::plugin::cov(filename);
 | 
				
			||||||
 | 
					                cpu->vm->register_plugin(*plugin);
 | 
				
			||||||
 | 
					                plugin_list.push_back(plugin);
 | 
				
			||||||
            } else {
 | 
					            } else {
 | 
				
			||||||
                std::array<char const*, 1> a{{filename.c_str()}};
 | 
					                std::array<char const*, 1> a{{filename.c_str()}};
 | 
				
			||||||
                iss::plugin::loader l(plugin_name, {{"initPlugin"}});
 | 
					                iss::plugin::loader l(plugin_name, {{"initPlugin"}});
 | 
				
			||||||
 
 | 
				
			|||||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
		Reference in New Issue
	
	Block a user