Merge remote-tracking branch 'origin/Trace_enhancement' into develop
This commit is contained in:
commit
1c90fe765d
|
@ -0,0 +1,180 @@
|
||||||
|
#include <iss/arch_if.h>
|
||||||
|
#include <iss/plugin/pctrace.h>
|
||||||
|
#include <util/logging.h>
|
||||||
|
#include <util/ities.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>
|
||||||
|
#ifdef WITH_LZ4
|
||||||
|
#include <lz4frame.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace iss {
|
||||||
|
namespace plugin {
|
||||||
|
|
||||||
|
using namespace rapidjson;
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
#ifdef WITH_LZ4
|
||||||
|
class lz4compress_steambuf: 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)
|
||||||
|
: sink(sink)
|
||||||
|
, src_buf(buf_size)
|
||||||
|
, dest_buf(LZ4F_compressBound(buf_size, nullptr))
|
||||||
|
{
|
||||||
|
auto errCode = LZ4F_createCompressionContext(&ctx, LZ4F_VERSION);
|
||||||
|
if (LZ4F_isError(errCode) != 0)
|
||||||
|
throw std::runtime_error(std::string("Failed to create LZ4 context: ") + LZ4F_getErrorName(errCode));
|
||||||
|
size_t ret = LZ4F_compressBegin(ctx, &dest_buf.front(), dest_buf.capacity(), nullptr);
|
||||||
|
if (LZ4F_isError(ret) != 0)
|
||||||
|
throw std::runtime_error(std::string("Failed to start LZ4 compression: ") + LZ4F_getErrorName(ret));
|
||||||
|
setp(src_buf.data(), src_buf.data() + src_buf.size() - 1);
|
||||||
|
sink.write(dest_buf.data(), ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
~lz4compress_steambuf() {
|
||||||
|
close();
|
||||||
|
}
|
||||||
|
|
||||||
|
void close() {
|
||||||
|
if (closed)
|
||||||
|
return;
|
||||||
|
sync();
|
||||||
|
auto ret = LZ4F_compressEnd(ctx, dest_buf.data(), dest_buf.capacity(), nullptr);
|
||||||
|
if (LZ4F_isError(ret) != 0)
|
||||||
|
throw std::runtime_error(std::string("Failed to finish LZ4 compression: ") + LZ4F_getErrorName(ret));
|
||||||
|
sink.write(dest_buf.data(), ret);
|
||||||
|
LZ4F_freeCompressionContext(ctx);
|
||||||
|
closed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
int_type overflow(int_type ch) override {
|
||||||
|
compress_and_write();
|
||||||
|
*pptr() = static_cast<char_type>(ch);
|
||||||
|
pbump(1);
|
||||||
|
return ch;
|
||||||
|
}
|
||||||
|
|
||||||
|
int_type sync() override {
|
||||||
|
compress_and_write();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void compress_and_write() {
|
||||||
|
if (closed)
|
||||||
|
throw std::runtime_error("Cannot write to closed stream");
|
||||||
|
if(auto orig_size = pptr() - pbase()){
|
||||||
|
auto ret = LZ4F_compressUpdate(ctx, dest_buf.data(), dest_buf.capacity(), pbase(), orig_size, nullptr);
|
||||||
|
if (LZ4F_isError(ret) != 0)
|
||||||
|
throw std::runtime_error(std::string("LZ4 compression failed: ") + LZ4F_getErrorName(ret));
|
||||||
|
if(ret) sink.write(dest_buf.data(), ret);
|
||||||
|
pbump(-orig_size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::ostream &sink;
|
||||||
|
std::vector<char> src_buf;
|
||||||
|
std::vector<char> dest_buf;
|
||||||
|
LZ4F_compressionContext_t ctx{ nullptr };
|
||||||
|
bool closed{ false };
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
cov::cov(std::string const &filename)
|
||||||
|
: instr_if(nullptr)
|
||||||
|
, filename(filename)
|
||||||
|
, output("output.trc")
|
||||||
|
#ifdef WITH_LZ4
|
||||||
|
, strbuf(new lz4compress_steambuf(output, 4096))
|
||||||
|
, ostr(strbuf.get())
|
||||||
|
#endif
|
||||||
|
{ }
|
||||||
|
|
||||||
|
cov::~cov() { }
|
||||||
|
|
||||||
|
bool 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
void cov::callback(instr_info_t iinfo, const exec_info& einfo) {
|
||||||
|
auto delay = 0;
|
||||||
|
size_t id = iinfo.instr_id;
|
||||||
|
auto entry = delays[id];
|
||||||
|
auto instr = instr_if->get_instr_word();
|
||||||
|
auto call = id==65 || id ==86 || ((id==2 || id==3) && bit_sub<7,5>(instr)!=0) ;//not taking care of tail calls (jalr with loading x6)
|
||||||
|
bool taken = einfo.branch_taken;
|
||||||
|
bool compressed = (instr&0x3)!=0x3;
|
||||||
|
if (einfo.branch_taken) {
|
||||||
|
delay = entry.taken;
|
||||||
|
if(entry.taken > 1)
|
||||||
|
instr_if->set_curr_instr_cycles(entry.taken);
|
||||||
|
} else {
|
||||||
|
delay = entry.not_taken;
|
||||||
|
if (entry.not_taken > 1)
|
||||||
|
instr_if->set_curr_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();
|
||||||
|
ostr<<std::hex <<"0x" << instr_if->get_pc() <<"," << delay <<"," << call<<","<<(compressed?2:4) <<"\n";
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue