Compare commits
7 Commits
ac86f14a54
...
feature/re
Author | SHA1 | Date | |
---|---|---|---|
58311b37db | |||
ad8dc09bee | |||
2bba5645c3 | |||
bf0a5a80de | |||
b37ef973de | |||
4c363f4073 | |||
b8fa5fbbda |
@@ -35,7 +35,7 @@ FILE(GLOB TGC_VM_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src/vm/interp/vm_*.cpp)
|
|||||||
set(LIB_SOURCES
|
set(LIB_SOURCES
|
||||||
src/vm/fp_functions.cpp
|
src/vm/fp_functions.cpp
|
||||||
src/plugin/instruction_count.cpp
|
src/plugin/instruction_count.cpp
|
||||||
src/plugin/cov.cpp
|
src/plugin/pctrace.cpp
|
||||||
|
|
||||||
${TGC_SOURCES}
|
${TGC_SOURCES}
|
||||||
${TGC_VM_SOURCES}
|
${TGC_VM_SOURCES}
|
||||||
|
@@ -169,7 +169,6 @@ struct ${coreDef.name.toLowerCase()}: public arch_if {
|
|||||||
}}%>
|
}}%>
|
||||||
uint32_t trap_state = 0, pending_trap = 0;
|
uint32_t trap_state = 0, pending_trap = 0;
|
||||||
uint64_t icount = 0;
|
uint64_t icount = 0;
|
||||||
uint64_t cycle = 0;
|
|
||||||
uint64_t instret = 0;
|
uint64_t instret = 0;
|
||||||
uint32_t last_branch;
|
uint32_t last_branch;
|
||||||
} reg;
|
} reg;
|
||||||
|
@@ -237,6 +237,10 @@ protected:
|
|||||||
|
|
||||||
uint64_t get_next_pc() override { return arch.get_next_pc(); };
|
uint64_t get_next_pc() override { return arch.get_next_pc(); };
|
||||||
|
|
||||||
|
uint64_t get_instr_count() { return arch.reg.icount; }
|
||||||
|
|
||||||
|
uint64_t get_total_cycles() override { return arch.reg.icount + arch.cycle_offset; }
|
||||||
|
|
||||||
void set_curr_instr_cycles(unsigned cycles) override { arch.cycle_offset += cycles - 1; };
|
void set_curr_instr_cycles(unsigned cycles) override { arch.cycle_offset += cycles - 1; };
|
||||||
|
|
||||||
riscv_hart_m_p<BASE, FEAT> &arch;
|
riscv_hart_m_p<BASE, FEAT> &arch;
|
||||||
|
@@ -340,6 +340,10 @@ protected:
|
|||||||
|
|
||||||
virtual uint64_t get_next_pc() { return arch.get_next_pc(); };
|
virtual uint64_t get_next_pc() { return arch.get_next_pc(); };
|
||||||
|
|
||||||
|
uint64_t get_instr_count() { return arch.reg.icount; }
|
||||||
|
|
||||||
|
uint64_t get_total_cycles() override { return arch.reg.icount + arch.cycle_offset; }
|
||||||
|
|
||||||
virtual void set_curr_instr_cycles(unsigned cycles) { arch.cycle_offset += cycles - 1; };
|
virtual void set_curr_instr_cycles(unsigned cycles) { arch.cycle_offset += cycles - 1; };
|
||||||
|
|
||||||
riscv_hart_msu_vp<BASE> &arch;
|
riscv_hart_msu_vp<BASE> &arch;
|
||||||
|
@@ -252,6 +252,10 @@ protected:
|
|||||||
|
|
||||||
virtual uint64_t get_next_pc() { return arch.get_next_pc(); };
|
virtual uint64_t get_next_pc() { return arch.get_next_pc(); };
|
||||||
|
|
||||||
|
uint64_t get_instr_count() { return arch.reg.icount; }
|
||||||
|
|
||||||
|
uint64_t get_total_cycles() override { return arch.reg.icount + arch.cycle_offset; }
|
||||||
|
|
||||||
virtual void set_curr_instr_cycles(unsigned cycles) { arch.cycle_offset += cycles - 1; };
|
virtual void set_curr_instr_cycles(unsigned cycles) { arch.cycle_offset += cycles - 1; };
|
||||||
|
|
||||||
riscv_hart_mu_p<BASE, FEAT> &arch;
|
riscv_hart_mu_p<BASE, FEAT> &arch;
|
||||||
|
@@ -258,7 +258,6 @@ struct tgc_c: public arch_if {
|
|||||||
uint32_t DPC = 0;
|
uint32_t DPC = 0;
|
||||||
uint32_t trap_state = 0, pending_trap = 0;
|
uint32_t trap_state = 0, pending_trap = 0;
|
||||||
uint64_t icount = 0;
|
uint64_t icount = 0;
|
||||||
uint64_t cycle = 0;
|
|
||||||
uint64_t instret = 0;
|
uint64_t instret = 0;
|
||||||
uint32_t last_branch;
|
uint32_t last_branch;
|
||||||
} reg;
|
} reg;
|
||||||
|
@@ -52,6 +52,18 @@ class cov : public iss::vm_plugin {
|
|||||||
size_t not_taken_delay;
|
size_t not_taken_delay;
|
||||||
size_t 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:
|
public:
|
||||||
|
|
||||||
@@ -59,7 +71,7 @@ public:
|
|||||||
|
|
||||||
cov(const cov &&) = delete;
|
cov(const cov &&) = delete;
|
||||||
|
|
||||||
cov();
|
cov(std::string const &);
|
||||||
|
|
||||||
virtual ~cov();
|
virtual ~cov();
|
||||||
|
|
||||||
@@ -75,8 +87,11 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
iss::instrumentation_if *instr_if {nullptr};
|
iss::instrumentation_if *instr_if {nullptr};
|
||||||
int counter {0};
|
|
||||||
std::ofstream output;
|
std::ofstream output;
|
||||||
|
std::string filename;
|
||||||
|
std::vector<instr_desc> delays;
|
||||||
|
bool jumped, first;
|
||||||
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -1,32 +0,0 @@
|
|||||||
#include <iss/plugin/cov.h>
|
|
||||||
#include <iss/arch_if.h>
|
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
|
|
||||||
iss::plugin::cov::cov() {
|
|
||||||
std::cout << "Entering Constructor"<<std::endl;
|
|
||||||
output.open("output.txt");
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
iss::plugin::cov::~cov() {
|
|
||||||
std::cout << "Entering Destructor"<<std::endl;
|
|
||||||
output.close();
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
bool iss::plugin::cov::registration(const char *const version, vm_if& vm) {
|
|
||||||
instr_if = vm.get_arch()->get_instrumentation_if();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
void iss::plugin::cov::callback(instr_info_t iinfo, const exec_info&) {
|
|
||||||
// if((instr_if->get_next_pc() - instr_if->get_pc() != 4) ||( instr_if->get_next_pc() - instr_if->get_pc() != 2)){
|
|
||||||
// std::cout << "jump from " << std::hex << instr_if->get_pc() << " to " << instr_if->get_next_pc()<< " after " << std::dec << counter <<" linear instructions" <<std::endl;
|
|
||||||
// counter = 0;
|
|
||||||
// }else {
|
|
||||||
// counter++;
|
|
||||||
// }
|
|
||||||
|
|
||||||
output<<std::hex << instr_if->get_pc() << std::endl;
|
|
||||||
}
|
|
@@ -85,7 +85,7 @@ bool iss::plugin::cycle_estimate::registration(const char* const version, vm_if&
|
|||||||
delays.push_back(instr_desc{size.Get<unsigned>(), d, d, branch.Get<bool>()});
|
delays.push_back(instr_desc{size.Get<unsigned>(), d, d, branch.Get<bool>()});
|
||||||
} else
|
} else
|
||||||
throw runtime_error("JSON parse error");
|
throw runtime_error("JSON parse error");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
LOG(ERR)<<"plugin cycle_estimate: could not find an entry for "<<core_name<<" in JSON file"<<endl;
|
LOG(ERR)<<"plugin cycle_estimate: could not find an entry for "<<core_name<<" in JSON file"<<endl;
|
||||||
return false;
|
return false;
|
||||||
@@ -111,7 +111,7 @@ void iss::plugin::cycle_estimate::callback(instr_info_t instr_info, exec_info co
|
|||||||
assert(arch_instr && "No instrumentation interface available but callback executed");
|
assert(arch_instr && "No instrumentation interface available but callback executed");
|
||||||
auto entry = delays[instr_info.instr_id];
|
auto entry = delays[instr_info.instr_id];
|
||||||
bool taken = exc_info.branch_taken;
|
bool taken = exc_info.branch_taken;
|
||||||
if (exc_info.branch_taken && entry.taken > 1)
|
if (exc_info.branch_taken && (entry.taken > 1))
|
||||||
arch_instr->set_curr_instr_cycles(entry.taken);
|
arch_instr->set_curr_instr_cycles(entry.taken);
|
||||||
else if (entry.not_taken > 1)
|
else if (entry.not_taken > 1)
|
||||||
arch_instr->set_curr_instr_cycles(entry.not_taken);
|
arch_instr->set_curr_instr_cycles(entry.not_taken);
|
||||||
|
133
src/plugin/pctrace.cpp
Normal file
133
src/plugin/pctrace.cpp
Normal file
@@ -0,0 +1,133 @@
|
|||||||
|
#include <iss/arch_if.h>
|
||||||
|
#include <iss/plugin/pctrace.h>
|
||||||
|
#include <util/logging.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>
|
||||||
|
|
||||||
|
|
||||||
|
using namespace rapidjson;
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
iss::plugin::cov::cov(std::string const &filename)
|
||||||
|
: instr_if(nullptr)
|
||||||
|
, filename(filename)
|
||||||
|
{
|
||||||
|
output.open("output.trc");
|
||||||
|
jumped = false;
|
||||||
|
first = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
iss::plugin::cov::~cov() {
|
||||||
|
output.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool iss::plugin::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;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
inline string formatPC(uint64_t pc) {
|
||||||
|
stringstream stream;
|
||||||
|
stream << "0x" << std::hex << pc;
|
||||||
|
return stream.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
void iss::plugin::cov::callback(instr_info_t iinfo, const exec_info& einfo) {
|
||||||
|
// auto delay = 0;
|
||||||
|
// auto entry = delays[iinfo.instr_id];
|
||||||
|
// bool taken = einfo.branch_taken;
|
||||||
|
// if (einfo.branch_taken)
|
||||||
|
// delay = entry.taken;
|
||||||
|
// else
|
||||||
|
// delay = entry.not_taken;
|
||||||
|
//
|
||||||
|
// if (first){
|
||||||
|
// output << formatPC(instr_if->get_pc()) << "," << delay;
|
||||||
|
// first = false;
|
||||||
|
// }
|
||||||
|
// if(instr_if->get_next_pc()-instr_if->get_pc() != delays[iinfo.instr_id].size/8){
|
||||||
|
// //The goal is to keep the output in start-target pairs, so after a jump the target address needs to get written
|
||||||
|
// //to the output. If the target happens to also be a start, we keep the pairing by adding a 0-delay entry.
|
||||||
|
// if (jumped)
|
||||||
|
// output <<"\n" <<formatPC(instr_if->get_pc()) << "," << 0;
|
||||||
|
// output <<"\n" << formatPC(instr_if->get_pc()) << "," << delay;
|
||||||
|
// jumped = true;
|
||||||
|
// }
|
||||||
|
// else{
|
||||||
|
// if (jumped){
|
||||||
|
// output <<"\n" << formatPC(instr_if->get_pc()) << "," << delay;
|
||||||
|
// jumped = false;
|
||||||
|
// }
|
||||||
|
// else if(delay!=1){
|
||||||
|
// output <<"\n" << formatPC(instr_if->get_pc()) << "," << delay;
|
||||||
|
// output <<"\n" << formatPC(instr_if->get_pc()) << "," << 0;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// }
|
||||||
|
|
||||||
|
//source code for the full output
|
||||||
|
auto delay = 0;
|
||||||
|
auto entry = delays[iinfo.instr_id];
|
||||||
|
bool taken = einfo.branch_taken;
|
||||||
|
if (einfo.branch_taken)
|
||||||
|
delay = entry.taken;
|
||||||
|
else
|
||||||
|
delay = entry.not_taken;
|
||||||
|
output<<std::hex <<"0x" << instr_if->get_pc() <<"," << delay << "\n";
|
||||||
|
}
|
@@ -69,7 +69,7 @@ using tgc_d_xrb_nn_plat_type = iss::arch::riscv_hart_mu_p<iss::arch::tgc_d_xrb_n
|
|||||||
#include <array>
|
#include <array>
|
||||||
#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/cov.h>
|
#include <iss/plugin/pctrace.h>
|
||||||
|
|
||||||
// clang-format on
|
// clang-format on
|
||||||
|
|
||||||
@@ -426,8 +426,8 @@ void core_complex::before_end_of_elaboration() {
|
|||||||
auto *plugin = new iss::plugin::cycle_estimate(filename);
|
auto *plugin = new iss::plugin::cycle_estimate(filename);
|
||||||
cpu->vm->register_plugin(*plugin);
|
cpu->vm->register_plugin(*plugin);
|
||||||
plugin_list.push_back(plugin);
|
plugin_list.push_back(plugin);
|
||||||
} else if (plugin_name == "cov") {
|
} else if (plugin_name == "pctrace") {
|
||||||
auto *plugin = new iss::plugin::cov();
|
auto *plugin = new iss::plugin::cov(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