adds tracing functionality
This commit is contained in:
parent
f74f98f361
commit
212fb1c8ff
|
@ -304,9 +304,9 @@ protected:
|
|||
*/
|
||||
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; }
|
||||
|
||||
|
@ -316,9 +316,11 @@ protected:
|
|||
|
||||
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;
|
||||
};
|
||||
|
|
|
@ -331,9 +331,9 @@ protected:
|
|||
*/
|
||||
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; }
|
||||
|
||||
|
@ -343,9 +343,11 @@ protected:
|
|||
|
||||
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;
|
||||
};
|
||||
|
|
|
@ -329,9 +329,9 @@ protected:
|
|||
*/
|
||||
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; }
|
||||
|
||||
|
@ -341,9 +341,11 @@ protected:
|
|||
|
||||
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;
|
||||
};
|
||||
|
|
|
@ -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).
|
|
@ -29,7 +29,7 @@
|
|||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* Contributors:
|
||||
* alex.com - initial implementation
|
||||
* alex@minres.com - initial implementation
|
||||
******************************************************************************/
|
||||
|
||||
#include <iss/arch_if.h>
|
||||
|
@ -55,11 +55,11 @@ using namespace rapidjson;
|
|||
using namespace std;
|
||||
|
||||
#ifdef WITH_LZ4
|
||||
class lz4compress_steambuf: public std::streambuf {
|
||||
class lz4compress_streambuf: public std::streambuf {
|
||||
public:
|
||||
lz4compress_steambuf(const lz4compress_steambuf&) = delete;
|
||||
lz4compress_steambuf& operator=(const lz4compress_steambuf&) = delete;
|
||||
lz4compress_steambuf(std::ostream &sink, size_t buf_size)
|
||||
lz4compress_streambuf(const lz4compress_streambuf&) = delete;
|
||||
lz4compress_streambuf& operator=(const lz4compress_streambuf&) = delete;
|
||||
lz4compress_streambuf(std::ostream &sink, size_t buf_size)
|
||||
: sink(sink)
|
||||
, src_buf(buf_size)
|
||||
, dest_buf(LZ4F_compressBound(buf_size, nullptr))
|
||||
|
@ -74,7 +74,7 @@ public:
|
|||
sink.write(dest_buf.data(), ret);
|
||||
}
|
||||
|
||||
~lz4compress_steambuf() {
|
||||
~lz4compress_streambuf() {
|
||||
close();
|
||||
}
|
||||
|
||||
|
@ -126,17 +126,21 @@ private:
|
|||
pctrace::pctrace(std::string const &filename)
|
||||
: instr_if(nullptr)
|
||||
, filename(filename)
|
||||
, reg_dump(getenv("REGDUMP"))
|
||||
, no_compres(getenv("NOCOMPRES"))
|
||||
, output("output.trc")
|
||||
#ifdef WITH_LZ4
|
||||
, strbuf(new lz4compress_steambuf(output, 4096))
|
||||
, strbuf( (no_compres || reg_dump)? nullptr: new lz4compress_streambuf(output, 4096))
|
||||
, ostr(strbuf.get())
|
||||
#endif
|
||||
{ }
|
||||
{}
|
||||
|
||||
pctrace::~pctrace() { }
|
||||
|
||||
bool pctrace::registration(const char *const version, vm_if& vm) {
|
||||
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;
|
||||
const string core_name = instr_if->core_type_name();
|
||||
if (filename.length() > 0) {
|
||||
|
@ -203,12 +207,22 @@ void pctrace::callback(instr_info_t iinfo) {
|
|||
if (entry.not_taken > 1)
|
||||
instr_if->update_last_instr_cycles(entry.not_taken);
|
||||
}
|
||||
#ifndef WITH_LZ4
|
||||
output<<std::hex <<"0x" << instr_if->get_pc() <<"," << delay <<"," << call<<","<<(compressed?2:4) <<"\n";
|
||||
#else
|
||||
auto rdbuf=ostr.rdbuf();
|
||||
if(no_compres|| reg_dump){
|
||||
if(reg_dump){
|
||||
for(size_t i=0; i< instr_if->get_reg_num(); ++i){
|
||||
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";
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}//namespace plugin
|
||||
}//namespace iss
|
||||
|
|
|
@ -39,11 +39,10 @@
|
|||
#include "iss/instrumentation_if.h"
|
||||
#include <string>
|
||||
#include <fstream>
|
||||
|
||||
|
||||
#include <cstdlib>
|
||||
namespace iss {
|
||||
namespace plugin {
|
||||
class lz4compress_steambuf;
|
||||
class lz4compress_streambuf;
|
||||
class pctrace : public iss::vm_plugin {
|
||||
struct instr_delay {
|
||||
std::string instr_name;
|
||||
|
@ -86,9 +85,13 @@ public:
|
|||
|
||||
private:
|
||||
iss::instrumentation_if *instr_if {nullptr};
|
||||
uint32_t* reg_base_ptr {nullptr};
|
||||
bool reg_dump {false};
|
||||
bool no_compres {false};
|
||||
std::ofstream output;
|
||||
|
||||
#ifdef WITH_LZ4
|
||||
std::unique_ptr<lz4compress_steambuf> strbuf;
|
||||
std::unique_ptr<lz4compress_streambuf> strbuf;
|
||||
std::ostream ostr;
|
||||
#endif
|
||||
std::string filename;
|
||||
|
|
Loading…
Reference in New Issue