moves pctrace
This commit is contained in:
parent
417076f8e6
commit
5fd226b670
|
@ -56,7 +56,6 @@ endif()
|
||||||
if(TARGET RapidJSON OR TARGET RapidJSON::RapidJSON)
|
if(TARGET RapidJSON OR TARGET RapidJSON::RapidJSON)
|
||||||
list(APPEND LIB_SOURCES
|
list(APPEND LIB_SOURCES
|
||||||
src/iss/plugin/cycle_estimate.cpp
|
src/iss/plugin/cycle_estimate.cpp
|
||||||
src/iss/plugin/pctrace.cpp
|
|
||||||
)
|
)
|
||||||
endif()
|
endif()
|
||||||
if(TARGET jsoncpp::jsoncpp)
|
if(TARGET jsoncpp::jsoncpp)
|
||||||
|
@ -88,10 +87,6 @@ target_link_libraries(${PROJECT_NAME} PUBLIC elfio::elfio softfloat scc-util Boo
|
||||||
if(TARGET jsoncpp::jsoncpp)
|
if(TARGET jsoncpp::jsoncpp)
|
||||||
target_link_libraries(${PROJECT_NAME} PUBLIC jsoncpp::jsoncpp)
|
target_link_libraries(${PROJECT_NAME} PUBLIC jsoncpp::jsoncpp)
|
||||||
endif()
|
endif()
|
||||||
if(TARGET lz4::lz4)
|
|
||||||
target_compile_definitions(${PROJECT_NAME} PUBLIC WITH_LZ4)
|
|
||||||
target_link_libraries(${PROJECT_NAME} PUBLIC lz4::lz4)
|
|
||||||
endif()
|
|
||||||
if(TARGET RapidJSON)
|
if(TARGET RapidJSON)
|
||||||
target_link_libraries(${PROJECT_NAME} PUBLIC RapidJSON)
|
target_link_libraries(${PROJECT_NAME} PUBLIC RapidJSON)
|
||||||
endif()
|
endif()
|
||||||
|
|
|
@ -1,228 +0,0 @@
|
||||||
/*******************************************************************************
|
|
||||||
* Copyright (C) 2017 - 2023, 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:
|
|
||||||
* alex@minres.com - initial implementation
|
|
||||||
******************************************************************************/
|
|
||||||
|
|
||||||
#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_streambuf: public std::streambuf {
|
|
||||||
public:
|
|
||||||
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))
|
|
||||||
{
|
|
||||||
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_streambuf() {
|
|
||||||
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
|
|
||||||
|
|
||||||
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( (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) {
|
|
||||||
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 pctrace::callback(instr_info_t iinfo) {
|
|
||||||
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 = instr_if->is_branch_taken();
|
|
||||||
bool compressed = (instr&0x3)!=0x3;
|
|
||||||
if (taken) {
|
|
||||||
delay = entry.taken;
|
|
||||||
if(entry.taken > 1)
|
|
||||||
instr_if->update_last_instr_cycles(entry.taken);
|
|
||||||
} else {
|
|
||||||
delay = entry.not_taken;
|
|
||||||
if (entry.not_taken > 1)
|
|
||||||
instr_if->update_last_instr_cycles(entry.not_taken);
|
|
||||||
}
|
|
||||||
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";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}//namespace plugin
|
|
||||||
}//namespace iss
|
|
|
@ -1,104 +0,0 @@
|
||||||
/*******************************************************************************
|
|
||||||
* Copyright (C) 2017 - 2023, 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 <string>
|
|
||||||
#include <fstream>
|
|
||||||
#include <cstdlib>
|
|
||||||
namespace iss {
|
|
||||||
namespace plugin {
|
|
||||||
class lz4compress_streambuf;
|
|
||||||
class pctrace : 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:
|
|
||||||
|
|
||||||
pctrace(const pctrace &) = delete;
|
|
||||||
|
|
||||||
pctrace(const pctrace &&) = delete;
|
|
||||||
|
|
||||||
pctrace(std::string const &);
|
|
||||||
|
|
||||||
virtual ~pctrace();
|
|
||||||
|
|
||||||
pctrace &operator=(const pctrace &) = delete;
|
|
||||||
|
|
||||||
pctrace &operator=(const pctrace &&) = delete;
|
|
||||||
|
|
||||||
bool registration(const char *const version, vm_if &arch) override;
|
|
||||||
|
|
||||||
sync_type get_sync() override { return POST_SYNC; };
|
|
||||||
|
|
||||||
void callback(instr_info_t) override;
|
|
||||||
|
|
||||||
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_streambuf> strbuf;
|
|
||||||
std::ostream ostr;
|
|
||||||
#endif
|
|
||||||
std::string filename;
|
|
||||||
std::vector<instr_desc> delays;
|
|
||||||
bool jumped{false}, first{true};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* _ISS_PLUGIN_COV_H_ */
|
|
|
@ -44,7 +44,6 @@
|
||||||
#include <iss/log_categories.h>
|
#include <iss/log_categories.h>
|
||||||
#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"
|
|
||||||
#ifndef WIN32
|
#ifndef WIN32
|
||||||
#include <iss/plugin/loader.h>
|
#include <iss/plugin/loader.h>
|
||||||
#endif
|
#endif
|
||||||
|
@ -157,11 +156,7 @@ int main(int argc, char *argv[]) {
|
||||||
auto *ce_plugin = new iss::plugin::cycle_estimate(arg);
|
auto *ce_plugin = new iss::plugin::cycle_estimate(arg);
|
||||||
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 {
|
||||||
auto *plugin = new iss::plugin::pctrace(arg);
|
|
||||||
vm->register_plugin(*plugin);
|
|
||||||
plugin_list.push_back(plugin);
|
|
||||||
} else {
|
|
||||||
#ifndef WIN32
|
#ifndef WIN32
|
||||||
std::vector<char const*> a{};
|
std::vector<char const*> a{};
|
||||||
if(arg.length())
|
if(arg.length())
|
||||||
|
|
Loading…
Reference in New Issue