Compare commits
	
		
			2 Commits
		
	
	
		
			e8fd5143bc
			...
			076b5a39ad
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 076b5a39ad | |||
| f40ab41899 | 
| @@ -1,5 +1,5 @@ | |||||||
| #include <iss/arch_if.h> | #include <iss/arch_if.h> | ||||||
| #include "pctrace.h" | #include <iss/plugin/pctrace.h> | ||||||
| #include <util/logging.h> | #include <util/logging.h> | ||||||
| #include <util/ities.h> | #include <util/ities.h> | ||||||
| #include <rapidjson/document.h> | #include <rapidjson/document.h> | ||||||
| @@ -89,7 +89,7 @@ private: | |||||||
| }; | }; | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| cov::cov(std::string const &filename) | pctrace::pctrace(std::string const &filename) | ||||||
| : instr_if(nullptr) | : instr_if(nullptr) | ||||||
| , filename(filename) | , filename(filename) | ||||||
| , output("output.trc") | , output("output.trc") | ||||||
| @@ -99,9 +99,9 @@ cov::cov(std::string const &filename) | |||||||
| #endif | #endif | ||||||
| { } | { } | ||||||
|  |  | ||||||
| cov::~cov() { } | pctrace::~pctrace() { } | ||||||
|  |  | ||||||
| bool cov::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(); | ||||||
|     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(); | ||||||
| @@ -152,13 +152,14 @@ bool cov::registration(const char *const version, vm_if& vm) { | |||||||
|     return true; |     return true; | ||||||
| } | } | ||||||
|  |  | ||||||
| void cov::callback(instr_info_t iinfo, const exec_info& einfo) { | void pctrace::callback(instr_info_t iinfo, const exec_info& einfo) { | ||||||
|     auto delay = 0; |     auto delay = 0; | ||||||
|     size_t id = iinfo.instr_id; |     size_t id = iinfo.instr_id; | ||||||
|     auto entry = delays[id]; |     auto entry = delays[id]; | ||||||
|     auto instr = instr_if->get_instr_word(); |     auto instr = instr_if->get_instr_word(); | ||||||
|     auto call = (id==2 || id==3) && bit_sub<7,5>(instr)!=0; |     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 taken = einfo.branch_taken; | ||||||
|  |     bool compressed = (instr&0x3)!=0x3; | ||||||
|     if (einfo.branch_taken) { |     if (einfo.branch_taken) { | ||||||
|         delay = entry.taken; |         delay = entry.taken; | ||||||
|         if(entry.taken > 1) |         if(entry.taken > 1) | ||||||
| @@ -169,10 +170,10 @@ void cov::callback(instr_info_t iinfo, const exec_info& einfo) { | |||||||
|             instr_if->set_curr_instr_cycles(entry.not_taken); |             instr_if->set_curr_instr_cycles(entry.not_taken); | ||||||
|     } |     } | ||||||
| #ifndef WITH_LZ4 | #ifndef WITH_LZ4 | ||||||
|     output<<std::hex <<"0x" << instr_if->get_pc() <<"," << delay <<"," << call<< "\n"; |     output<<std::hex <<"0x" << instr_if->get_pc() <<"," << delay <<"," << call<<","<<(compressed?2:4) <<"\n"; | ||||||
| #else | #else | ||||||
|     auto rdbuf=ostr.rdbuf(); |     auto rdbuf=ostr.rdbuf(); | ||||||
|     ostr<<std::hex <<"0x" << instr_if->get_pc() <<"," << delay <<"," << call<< "\n"; |     ostr<<std::hex <<"0x" << instr_if->get_pc() <<"," << delay <<"," << call<<","<<(compressed?2:4) <<"\n"; | ||||||
| #endif | #endif | ||||||
| } | } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -45,7 +45,7 @@ | |||||||
| namespace iss { | namespace iss { | ||||||
| namespace plugin { | namespace plugin { | ||||||
| class lz4compress_steambuf; | class lz4compress_steambuf; | ||||||
| class cov : public iss::vm_plugin { | class pctrace : public iss::vm_plugin { | ||||||
|     struct instr_delay { |     struct instr_delay { | ||||||
|         std::string instr_name; |         std::string instr_name; | ||||||
|         size_t size; |         size_t size; | ||||||
| @@ -67,17 +67,17 @@ class cov : public iss::vm_plugin { | |||||||
|  |  | ||||||
| public: | public: | ||||||
|  |  | ||||||
|     cov(const cov &) = delete; |     pctrace(const pctrace &) = delete; | ||||||
|  |  | ||||||
|     cov(const cov &&) = delete; |     pctrace(const pctrace &&) = delete; | ||||||
|  |  | ||||||
|     cov(std::string const &); |     pctrace(std::string const &); | ||||||
|  |  | ||||||
|     virtual ~cov(); |     virtual ~pctrace(); | ||||||
|  |  | ||||||
|     cov &operator=(const cov &) = delete; |     pctrace &operator=(const pctrace &) = delete; | ||||||
|  |  | ||||||
|     cov &operator=(const cov &&) = delete; |     pctrace &operator=(const pctrace &&) = delete; | ||||||
|  |  | ||||||
|     bool registration(const char *const version, vm_if &arch) override; |     bool registration(const char *const version, vm_if &arch) override; | ||||||
|  |  | ||||||
|   | |||||||
| @@ -177,7 +177,7 @@ int main(int argc, char *argv[]) { | |||||||
|                     vm->register_plugin(*ce_plugin); |                     vm->register_plugin(*ce_plugin); | ||||||
|                     plugin_list.push_back(ce_plugin); |                     plugin_list.push_back(ce_plugin); | ||||||
|                 } else if (plugin_name == "pctrace") { |                 } else if (plugin_name == "pctrace") { | ||||||
|                     auto *plugin = new iss::plugin::cov(filename); |                     auto *plugin = new iss::plugin::pctrace(filename); | ||||||
|                     vm->register_plugin(*plugin); |                     vm->register_plugin(*plugin); | ||||||
|                     plugin_list.push_back(plugin); |                     plugin_list.push_back(plugin); | ||||||
|                } else { |                } else { | ||||||
|   | |||||||
| @@ -1,180 +0,0 @@ | |||||||
| #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 |  | ||||||
| } |  | ||||||
| } |  | ||||||
| } |  | ||||||
| @@ -405,7 +405,7 @@ void core_complex::before_end_of_elaboration() { | |||||||
|                 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") { |             } else if (plugin_name == "pctrace") { | ||||||
|                 auto *plugin = new iss::plugin::cov(filename); |                 auto *plugin = new iss::plugin::pctrace(filename); | ||||||
|                 cpu->vm->register_plugin(*plugin); |                 cpu->vm->register_plugin(*plugin); | ||||||
|                 plugin_list.push_back(plugin); |                 plugin_list.push_back(plugin); | ||||||
|             } else { |             } else { | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user