adds tracing functionality

This commit is contained in:
Eyck-Alexander Jentzsch 2023-09-22 12:40:35 +02:00
parent f74f98f361
commit 212fb1c8ff
6 changed files with 63 additions and 32 deletions

View File

@ -304,9 +304,9 @@ 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; }
uint64_t get_pc() override { return arch.reg.PC; }; uint64_t get_pc() override { return arch.reg.PC; }
uint64_t get_next_pc() override { return arch.reg.NEXT_PC; }; uint64_t get_next_pc() override { return arch.reg.NEXT_PC; }
uint64_t get_instr_word() override { return arch.reg.instruction; } uint64_t get_instr_word() override { return arch.reg.instruction; }
@ -316,9 +316,11 @@ protected:
uint64_t get_total_cycles() override { return arch.reg.icount + arch.cycle_offset; } uint64_t get_total_cycles() override { return arch.reg.icount + arch.cycle_offset; }
void update_last_instr_cycles(unsigned cycles) override { arch.cycle_offset += cycles - 1; }; void update_last_instr_cycles(unsigned cycles) override { arch.cycle_offset += cycles - 1; }
bool is_branch_taken() override { return arch.reg.last_branch; }; bool is_branch_taken() override { return arch.reg.last_branch; }
unsigned get_reg_num() override {return traits<BASE>::NUM_REGS;}
riscv_hart_m_p<BASE, FEAT> &arch; riscv_hart_m_p<BASE, FEAT> &arch;
}; };

View File

@ -331,9 +331,9 @@ 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; }
uint64_t get_pc() override { return arch.reg.PC; }; uint64_t get_pc() override { return arch.reg.PC; }
uint64_t get_next_pc() override { return arch.reg.NEXT_PC; }; uint64_t get_next_pc() override { return arch.reg.NEXT_PC; }
uint64_t get_instr_word() override { return arch.reg.instruction; } uint64_t get_instr_word() override { return arch.reg.instruction; }
@ -343,9 +343,11 @@ protected:
uint64_t get_total_cycles() override { return arch.reg.icount + arch.cycle_offset; } uint64_t get_total_cycles() override { return arch.reg.icount + arch.cycle_offset; }
void update_last_instr_cycles(unsigned cycles) override { arch.cycle_offset += cycles - 1; }; void update_last_instr_cycles(unsigned cycles) override { arch.cycle_offset += cycles - 1; }
bool is_branch_taken() override { return arch.reg.last_branch; }; bool is_branch_taken() override { return arch.reg.last_branch; }
unsigned get_reg_num() override {return traits<BASE>::NUM_REGS; }
riscv_hart_msu_vp<BASE> &arch; riscv_hart_msu_vp<BASE> &arch;
}; };

View File

@ -329,9 +329,9 @@ 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; }
uint64_t get_pc() override { return arch.reg.PC; }; uint64_t get_pc() override { return arch.reg.PC; }
uint64_t get_next_pc() override { return arch.reg.NEXT_PC; }; uint64_t get_next_pc() override { return arch.reg.NEXT_PC; }
uint64_t get_instr_word() override { return arch.reg.instruction; } uint64_t get_instr_word() override { return arch.reg.instruction; }
@ -341,9 +341,11 @@ protected:
uint64_t get_total_cycles() override { return arch.reg.icount + arch.cycle_offset; } uint64_t get_total_cycles() override { return arch.reg.icount + arch.cycle_offset; }
void update_last_instr_cycles(unsigned cycles) override { arch.cycle_offset += cycles - 1; }; void update_last_instr_cycles(unsigned cycles) override { arch.cycle_offset += cycles - 1; }
bool is_branch_taken() override { return arch.reg.last_branch; }; bool is_branch_taken() override { return arch.reg.last_branch; }
unsigned get_reg_num() override {return traits<BASE>::NUM_REGS; }
riscv_hart_mu_p<BASE, FEAT> &arch; riscv_hart_mu_p<BASE, FEAT> &arch;
}; };

8
src/iss/plugin/README.md Normal file
View File

@ -0,0 +1,8 @@
# pctrace
Trace functionality to allow visualizing coverage in lcov and cachegrind tools. Use environment variables NOCOMPRES and REGDUMP to toggle functionality.
- NOCOMPRES: any value turns off the LZ4 compression
- REGDUMP: any value switches to tracing the registers instead. Also turns off compression.
Known Bugs:
- currently does not work correctly with jit backends, the plugin cant tell if instructions are compressed. Additionaly the cost of instrs that raise a trap is not known. It takes the cost of the instrid -1 (0 at the moment).

View File

@ -29,7 +29,7 @@
* POSSIBILITY OF SUCH DAMAGE. * POSSIBILITY OF SUCH DAMAGE.
* *
* Contributors: * Contributors:
* alex.com - initial implementation * alex@minres.com - initial implementation
******************************************************************************/ ******************************************************************************/
#include <iss/arch_if.h> #include <iss/arch_if.h>
@ -55,11 +55,11 @@ using namespace rapidjson;
using namespace std; using namespace std;
#ifdef WITH_LZ4 #ifdef WITH_LZ4
class lz4compress_steambuf: public std::streambuf { class lz4compress_streambuf: public std::streambuf {
public: public:
lz4compress_steambuf(const lz4compress_steambuf&) = delete; lz4compress_streambuf(const lz4compress_streambuf&) = delete;
lz4compress_steambuf& operator=(const lz4compress_steambuf&) = delete; lz4compress_streambuf& operator=(const lz4compress_streambuf&) = delete;
lz4compress_steambuf(std::ostream &sink, size_t buf_size) lz4compress_streambuf(std::ostream &sink, size_t buf_size)
: sink(sink) : sink(sink)
, src_buf(buf_size) , src_buf(buf_size)
, dest_buf(LZ4F_compressBound(buf_size, nullptr)) , dest_buf(LZ4F_compressBound(buf_size, nullptr))
@ -74,7 +74,7 @@ public:
sink.write(dest_buf.data(), ret); sink.write(dest_buf.data(), ret);
} }
~lz4compress_steambuf() { ~lz4compress_streambuf() {
close(); close();
} }
@ -126,17 +126,21 @@ private:
pctrace::pctrace(std::string const &filename) pctrace::pctrace(std::string const &filename)
: instr_if(nullptr) : instr_if(nullptr)
, filename(filename) , filename(filename)
, reg_dump(getenv("REGDUMP"))
, no_compres(getenv("NOCOMPRES"))
, output("output.trc") , output("output.trc")
#ifdef WITH_LZ4 #ifdef WITH_LZ4
, strbuf(new lz4compress_steambuf(output, 4096)) , strbuf( (no_compres || reg_dump)? nullptr: new lz4compress_streambuf(output, 4096))
, ostr(strbuf.get()) , ostr(strbuf.get())
#endif #endif
{ } {}
pctrace::~pctrace() { } pctrace::~pctrace() { }
bool pctrace::registration(const char *const version, vm_if& vm) { bool pctrace::registration(const char *const version, vm_if& vm) {
instr_if = vm.get_arch()->get_instrumentation_if(); instr_if = vm.get_arch()->get_instrumentation_if();
reg_base_ptr = reinterpret_cast<uint32_t*>(vm.get_arch()->get_regs_base_ptr());
if(!instr_if) return false; if(!instr_if) return false;
const string core_name = instr_if->core_type_name(); const string core_name = instr_if->core_type_name();
if (filename.length() > 0) { if (filename.length() > 0) {
@ -203,12 +207,22 @@ void pctrace::callback(instr_info_t iinfo) {
if (entry.not_taken > 1) if (entry.not_taken > 1)
instr_if->update_last_instr_cycles(entry.not_taken); instr_if->update_last_instr_cycles(entry.not_taken);
} }
#ifndef WITH_LZ4 if(no_compres|| reg_dump){
output<<std::hex <<"0x" << instr_if->get_pc() <<"," << delay <<"," << call<<","<<(compressed?2:4) <<"\n"; if(reg_dump){
#else for(size_t i=0; i< instr_if->get_reg_num(); ++i){
auto rdbuf=ostr.rdbuf(); uint32_t reg_val = *(reg_base_ptr+i);
output << "0x" << std::setfill('0') << std::setw(8) << std::hex << reg_val << " ";
}
output<<"\n" ;
}
else{
output<<std::hex <<"0x" << instr_if->get_pc() <<"," << delay <<"," << call<<","<<(compressed?2:4) <<std::endl;
}
}else{
ostr<<std::hex <<"0x" << instr_if->get_pc() <<"," << delay <<"," << call<<","<<(compressed?2:4) <<"\n"; ostr<<std::hex <<"0x" << instr_if->get_pc() <<"," << delay <<"," << call<<","<<(compressed?2:4) <<"\n";
#endif }
}
}
} }
}//namespace plugin
}//namespace iss

View File

@ -39,11 +39,10 @@
#include "iss/instrumentation_if.h" #include "iss/instrumentation_if.h"
#include <string> #include <string>
#include <fstream> #include <fstream>
#include <cstdlib>
namespace iss { namespace iss {
namespace plugin { namespace plugin {
class lz4compress_steambuf; class lz4compress_streambuf;
class pctrace : public iss::vm_plugin { class pctrace : public iss::vm_plugin {
struct instr_delay { struct instr_delay {
std::string instr_name; std::string instr_name;
@ -86,9 +85,13 @@ public:
private: private:
iss::instrumentation_if *instr_if {nullptr}; iss::instrumentation_if *instr_if {nullptr};
uint32_t* reg_base_ptr {nullptr};
bool reg_dump {false};
bool no_compres {false};
std::ofstream output; std::ofstream output;
#ifdef WITH_LZ4 #ifdef WITH_LZ4
std::unique_ptr<lz4compress_steambuf> strbuf; std::unique_ptr<lz4compress_streambuf> strbuf;
std::ostream ostr; std::ostream ostr;
#endif #endif
std::string filename; std::string filename;