Merge branch 'wsos'
This commit is contained in:
@ -1,4 +1,4 @@
|
|||||||
find_program(LLVMCONFIG NAMES llvm-config llvm-config-3.4 llvm-config-3.3 llvm-config-3.2 llvm-config-3.1)
|
find_program(LLVMCONFIG NAMES llvm-config-3.4 llvm-config-3.3 llvm-config-3.2 llvm-config-3.1 llvm-config)
|
||||||
|
|
||||||
if( NOT LLVMCONFIG )
|
if( NOT LLVMCONFIG )
|
||||||
message(FATAL_ERROR "llvm-config not found, try installing llvm-dev llvm")
|
message(FATAL_ERROR "llvm-config not found, try installing llvm-dev llvm")
|
||||||
|
|||||||
@ -33,6 +33,7 @@ Required for Fail*:
|
|||||||
* a MySQL 5.0+ or MariaDB 5.1+ (MariaDB 5.5 recommended) server
|
* a MySQL 5.0+ or MariaDB 5.1+ (MariaDB 5.5 recommended) server
|
||||||
* doxygen
|
* doxygen
|
||||||
* cmake-curses-gui
|
* cmake-curses-gui
|
||||||
|
* python-numpy and python-matplotlib for the faultspaceplot tool
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -19,9 +19,12 @@ message DatabaseCampaignMessage {
|
|||||||
required string benchmark = 9 [(sql_ignore) = true];
|
required string benchmark = 9 [(sql_ignore) = true];
|
||||||
|
|
||||||
required InjectionPointMessage injection_point = 10 [(sql_ignore) = true];
|
required InjectionPointMessage injection_point = 10 [(sql_ignore) = true];
|
||||||
|
|
||||||
|
required bool inject_bursts = 11 [default = false];
|
||||||
}
|
}
|
||||||
|
|
||||||
message DatabaseExperimentMessage {
|
message DatabaseExperimentMessage {
|
||||||
required uint32 bitoffset = 1 [(sql_primary_key) = true];
|
required uint32 bitoffset = 1 [(sql_primary_key) = true];
|
||||||
required uint32 original_value = 2;
|
required uint32 original_value = 2;
|
||||||
|
required uint32 injection_width = 3;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -46,6 +46,10 @@ bool DatabaseCampaign::run() {
|
|||||||
cmd.addOption("p", "prune-method", Arg::Required,
|
cmd.addOption("p", "prune-method", Arg::Required,
|
||||||
"-p/--prune-method \tWhich import method(s) to use (default: \"%\"; use % and _ as wildcard characters)");
|
"-p/--prune-method \tWhich import method(s) to use (default: \"%\"; use % and _ as wildcard characters)");
|
||||||
|
|
||||||
|
CommandLine::option_handle BURST =
|
||||||
|
cmd.addOption("","inject-bursts", Arg::None,
|
||||||
|
"--inject-bursts \tinject burst faults (default: single bitflips)");
|
||||||
|
|
||||||
if (!cmd.parse()) {
|
if (!cmd.parse()) {
|
||||||
log_send << "Error parsing arguments." << std::endl;
|
log_send << "Error parsing arguments." << std::endl;
|
||||||
exit(-1);
|
exit(-1);
|
||||||
@ -91,6 +95,14 @@ bool DatabaseCampaign::run() {
|
|||||||
benchmarks.push_back("%");
|
benchmarks.push_back("%");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (cmd[BURST]) {
|
||||||
|
m_inject_bursts = true;
|
||||||
|
log_send << "fault model: burst" << std::endl;
|
||||||
|
} else {
|
||||||
|
m_inject_bursts = false;
|
||||||
|
log_send << "fault model: single-bit flip" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
if (cmd[PRUNER]) {
|
if (cmd[PRUNER]) {
|
||||||
m_fspmethod = std::string(cmd[PRUNER].first()->arg);
|
m_fspmethod = std::string(cmd[PRUNER].first()->arg);
|
||||||
} else {
|
} else {
|
||||||
@ -225,7 +237,7 @@ bool DatabaseCampaign::run_variant(Database::Variant variant) {
|
|||||||
}
|
}
|
||||||
pilot.set_data_address(data_address);
|
pilot.set_data_address(data_address);
|
||||||
pilot.set_data_width(data_width);
|
pilot.set_data_width(data_width);
|
||||||
|
pilot.set_inject_bursts(m_inject_bursts);
|
||||||
|
|
||||||
this->cb_send_pilot(pilot);
|
this->cb_send_pilot(pilot);
|
||||||
|
|
||||||
|
|||||||
@ -39,6 +39,8 @@ class DatabaseCampaign : public Campaign {
|
|||||||
id_map completed_pilots; // !< map: Pilot IDs -> result count
|
id_map completed_pilots; // !< map: Pilot IDs -> result count
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
bool m_inject_bursts; // !< inject burst faults?
|
||||||
|
|
||||||
public:
|
public:
|
||||||
DatabaseCampaign() {};
|
DatabaseCampaign() {};
|
||||||
|
|
||||||
@ -61,7 +63,9 @@ public:
|
|||||||
* there are less result rows, the pilot will be again sent to the clients
|
* there are less result rows, the pilot will be again sent to the clients
|
||||||
* @return \c exptected number of results
|
* @return \c exptected number of results
|
||||||
*/
|
*/
|
||||||
virtual int expected_number_of_results(std::string variant, std::string benchmark) { return 8;}
|
virtual int expected_number_of_results(std::string variant, std::string benchmark) {
|
||||||
|
return (m_inject_bursts ? 1 : 8);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Callback function that can be used to add command line options
|
* Callback function that can be used to add command line options
|
||||||
|
|||||||
@ -13,6 +13,7 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
//#define LOCAL
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
using namespace fail;
|
using namespace fail;
|
||||||
@ -27,6 +28,18 @@ DatabaseExperiment::~DatabaseExperiment() {
|
|||||||
delete this->m_jc;
|
delete this->m_jc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsigned DatabaseExperiment::injectBurst(address_t data_address) {
|
||||||
|
unsigned value, burst_value;
|
||||||
|
value = m_mm.getByte(data_address);
|
||||||
|
burst_value = value ^ 0xff;
|
||||||
|
m_mm.setByte(data_address, burst_value);
|
||||||
|
|
||||||
|
m_log << "INJECTED BURST at: 0x" << hex<< setw(2) << setfill('0') << data_address
|
||||||
|
<< " value: 0x" << setw(2) << setfill('0') << value << " -> 0x"
|
||||||
|
<< setw(2) << setfill('0') << burst_value << endl;
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
unsigned DatabaseExperiment::injectBitFlip(address_t data_address, unsigned bitpos){
|
unsigned DatabaseExperiment::injectBitFlip(address_t data_address, unsigned bitpos){
|
||||||
unsigned int value, injectedval;
|
unsigned int value, injectedval;
|
||||||
|
|
||||||
@ -79,21 +92,32 @@ bool DatabaseExperiment::run()
|
|||||||
while (executed_jobs < 25 || m_jc->getNumberOfUndoneJobs() > 0) {
|
while (executed_jobs < 25 || m_jc->getNumberOfUndoneJobs() > 0) {
|
||||||
m_log << "asking jobserver for parameters" << endl;
|
m_log << "asking jobserver for parameters" << endl;
|
||||||
ExperimentData * param = this->cb_allocate_experiment_data();
|
ExperimentData * param = this->cb_allocate_experiment_data();
|
||||||
|
#ifndef LOCAL
|
||||||
if (!m_jc->getParam(*param)){
|
if (!m_jc->getParam(*param)){
|
||||||
m_log << "Dying." << endl; // We were told to die.
|
m_log << "Dying." << endl; // We were told to die.
|
||||||
simulator.terminate(1);
|
simulator.terminate(1);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
m_current_param = param;
|
m_current_param = param;
|
||||||
|
|
||||||
DatabaseCampaignMessage * fsppilot =
|
DatabaseCampaignMessage * fsppilot =
|
||||||
protobufFindSubmessageByTypename<DatabaseCampaignMessage>(¶m->getMessage(), "DatabaseCampaignMessage");
|
protobufFindSubmessageByTypename<DatabaseCampaignMessage>(¶m->getMessage(), "DatabaseCampaignMessage");
|
||||||
assert (fsppilot != 0);
|
assert (fsppilot != 0);
|
||||||
|
|
||||||
|
#ifdef LOCAL
|
||||||
|
fsppilot->set_injection_instr(0);
|
||||||
|
fsppilot->set_injection_instr_absolute(1048677);
|
||||||
|
fsppilot->set_data_address(2101240);
|
||||||
|
fsppilot->set_data_width(1);
|
||||||
|
fsppilot->set_inject_bursts(true);
|
||||||
|
#endif
|
||||||
|
|
||||||
unsigned injection_instr = fsppilot->injection_instr();
|
unsigned injection_instr = fsppilot->injection_instr();
|
||||||
address_t data_address = fsppilot->data_address();
|
address_t data_address = fsppilot->data_address();
|
||||||
unsigned width = fsppilot->data_width();
|
unsigned width = fsppilot->data_width();
|
||||||
|
unsigned injection_width = fsppilot->inject_bursts() ? 8 : 1;
|
||||||
|
|
||||||
for (unsigned bit_offset = 0; bit_offset < width * 8; ++bit_offset) {
|
for (unsigned bit_offset = 0; bit_offset < width * 8; bit_offset += injection_width) {
|
||||||
// 8 results in one job
|
// 8 results in one job
|
||||||
Message *outer_result = cb_new_result(param);
|
Message *outer_result = cb_new_result(param);
|
||||||
m_current_result = outer_result;
|
m_current_result = outer_result;
|
||||||
@ -107,7 +131,7 @@ bool DatabaseExperiment::run()
|
|||||||
|
|
||||||
m_log << "Trying to inject @ instr #" << dec << injection_instr << endl;
|
m_log << "Trying to inject @ instr #" << dec << injection_instr << endl;
|
||||||
|
|
||||||
simulator.clearListeners();
|
simulator.clearListeners(this);
|
||||||
|
|
||||||
if (!this->cb_before_fast_forward()) {
|
if (!this->cb_before_fast_forward()) {
|
||||||
continue;
|
continue;
|
||||||
@ -155,10 +179,16 @@ bool DatabaseExperiment::run()
|
|||||||
simulator.terminate(1);
|
simulator.terminate(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
simulator.clearListeners();
|
simulator.clearListeners(this);
|
||||||
|
|
||||||
/// INJECT BITFLIP:
|
if (fsppilot->inject_bursts()) {
|
||||||
result->set_original_value(injectBitFlip(data_address, bit_offset));
|
/// INJECT BURST:
|
||||||
|
result->set_original_value(injectBurst((data_address+bit_offset/8)));
|
||||||
|
} else {
|
||||||
|
/// INJECT BITFLIP:
|
||||||
|
result->set_original_value(injectBitFlip(data_address, bit_offset));
|
||||||
|
}
|
||||||
|
result->set_injection_width(injection_width);
|
||||||
|
|
||||||
if (!this->cb_before_resume()) {
|
if (!this->cb_before_resume()) {
|
||||||
continue; // Continue to next experiment
|
continue; // Continue to next experiment
|
||||||
@ -175,9 +205,13 @@ bool DatabaseExperiment::run()
|
|||||||
m_log << "Resume done" << std::endl;
|
m_log << "Resume done" << std::endl;
|
||||||
this->cb_after_resume(listener);
|
this->cb_after_resume(listener);
|
||||||
|
|
||||||
simulator.clearListeners();
|
simulator.clearListeners(this);
|
||||||
}
|
}
|
||||||
|
#ifndef LOCAL
|
||||||
m_jc->sendResult(*param);
|
m_jc->sendResult(*param);
|
||||||
|
#else
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
this->cb_free_experiment_data(param);
|
this->cb_free_experiment_data(param);
|
||||||
}
|
}
|
||||||
// Explicitly terminate, or the simulator will continue to run.
|
// Explicitly terminate, or the simulator will continue to run.
|
||||||
|
|||||||
@ -15,6 +15,7 @@ class DatabaseExperiment : public fail::ExperimentFlow {
|
|||||||
fail::JobClient *m_jc;
|
fail::JobClient *m_jc;
|
||||||
|
|
||||||
unsigned injectBitFlip(fail::address_t data_address, unsigned bitpos);
|
unsigned injectBitFlip(fail::address_t data_address, unsigned bitpos);
|
||||||
|
unsigned injectBurst(fail::address_t data_address);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
The current experiment data as returned by the job client. This
|
The current experiment data as returned by the job client. This
|
||||||
|
|||||||
@ -42,6 +42,23 @@ google::protobuf::Message* GenericExperiment::cb_new_result(ExperimentData* data
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector<char> loadFile(std::string filename)
|
||||||
|
{
|
||||||
|
std::vector<char> data;
|
||||||
|
FILE *f = fopen(filename.c_str(), "rb");
|
||||||
|
if (!f) {
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
fseek(f, 0, SEEK_END);
|
||||||
|
long len = ftell(f);
|
||||||
|
fseek(f, 0, SEEK_SET);
|
||||||
|
if (len > 0) {
|
||||||
|
data.resize(len);
|
||||||
|
fread(&data[0], len, 1, f);
|
||||||
|
}
|
||||||
|
fclose(f);
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
void handleEvent(GenericExperimentMessage_Result& result,
|
void handleEvent(GenericExperimentMessage_Result& result,
|
||||||
GenericExperimentMessage_Result_ResultType restype,
|
GenericExperimentMessage_Result_ResultType restype,
|
||||||
@ -56,7 +73,7 @@ void GenericExperiment::parseSymbols(const std::string &args, std::set<fail::Bas
|
|||||||
std::stringstream ss(args);
|
std::stringstream ss(args);
|
||||||
std::string item;
|
std::string item;
|
||||||
while (std::getline(ss, item, ',')) {
|
while (std::getline(ss, item, ',')) {
|
||||||
const ElfSymbol * symbol = &m_elf.getSymbol(item);
|
const ElfSymbol * symbol = &(m_elf->getSymbol(item));
|
||||||
if (!symbol->isValid()) {
|
if (!symbol->isValid()) {
|
||||||
m_log << "ELF Symbol not found: " << item << endl;
|
m_log << "ELF Symbol not found: " << item << endl;
|
||||||
simulator.terminate(1);
|
simulator.terminate(1);
|
||||||
@ -76,6 +93,9 @@ bool GenericExperiment::cb_start_experiment() {
|
|||||||
cmd.addOption("", "", Arg::None, "USAGE: fail-client -Wf,[option] -Wf,[option] ... <BochsOptions...>\n\n");
|
cmd.addOption("", "", Arg::None, "USAGE: fail-client -Wf,[option] -Wf,[option] ... <BochsOptions...>\n\n");
|
||||||
CommandLine::option_handle HELP = cmd.addOption("h", "help", Arg::None, "-h,--help \tPrint usage and exit");
|
CommandLine::option_handle HELP = cmd.addOption("h", "help", Arg::None, "-h,--help \tPrint usage and exit");
|
||||||
|
|
||||||
|
CommandLine::option_handle ELF_FILE = cmd.addOption("", "elf-file", Arg::Required,
|
||||||
|
"--elf-file \tELF Binary File (default: $FAIL_ELF_PATH)");
|
||||||
|
|
||||||
CommandLine::option_handle STATE_DIR = cmd.addOption("", "state-dir", Arg::Required,
|
CommandLine::option_handle STATE_DIR = cmd.addOption("", "state-dir", Arg::Required,
|
||||||
"--state-dir \t Path to the state directory");
|
"--state-dir \t Path to the state directory");
|
||||||
|
|
||||||
@ -92,6 +112,9 @@ bool GenericExperiment::cb_start_experiment() {
|
|||||||
CommandLine::option_handle TIMEOUT = cmd.addOption("", "timeout", Arg::Required,
|
CommandLine::option_handle TIMEOUT = cmd.addOption("", "timeout", Arg::Required,
|
||||||
"--timeout \t Experiment Timeout in uS");
|
"--timeout \t Experiment Timeout in uS");
|
||||||
|
|
||||||
|
CommandLine::option_handle E9_FILE = cmd.addOption("", "e9-file", Arg::Required,
|
||||||
|
"--e9-file FILE \t data logged via port 0xE9 in golden run");
|
||||||
|
|
||||||
|
|
||||||
std::map<std::string, CommandLine::option_handle> option_handles;
|
std::map<std::string, CommandLine::option_handle> option_handles;
|
||||||
for (std::map<std::string, ListenerSet *>::iterator it = end_marker_groups.begin();
|
for (std::map<std::string, ListenerSet *>::iterator it = end_marker_groups.begin();
|
||||||
@ -104,7 +127,7 @@ bool GenericExperiment::cb_start_experiment() {
|
|||||||
|
|
||||||
if (!cmd.parse()) {
|
if (!cmd.parse()) {
|
||||||
cerr << "Error parsing arguments." << endl;
|
cerr << "Error parsing arguments." << endl;
|
||||||
exit(-1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cmd[HELP]) {
|
if (cmd[HELP]) {
|
||||||
@ -112,13 +135,32 @@ bool GenericExperiment::cb_start_experiment() {
|
|||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (cmd[ELF_FILE]) {
|
||||||
|
elf_file = cmd[ELF_FILE].first()->arg;
|
||||||
|
m_elf = new ElfReader(elf_file.c_str());
|
||||||
|
m_log << "ELF file specified: " << elf_file << std::endl;
|
||||||
|
} else {
|
||||||
|
char *elfpath = getenv("FAIL_ELF_PATH");
|
||||||
|
if (elfpath == NULL) {
|
||||||
|
m_elf = NULL;
|
||||||
|
} else {
|
||||||
|
elf_file = elfpath;
|
||||||
|
m_elf = new ElfReader(elf_file.c_str());
|
||||||
|
m_log << "ELF file via environment variable: " << elf_file << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (m_elf == NULL) {
|
||||||
|
m_log << "ERROR: no FAIL_ELF_PATH set or --elf-file given. exiting!" << std::endl;
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
address_t minimal_ip = INT_MAX; // Every address is lower
|
address_t minimal_ip = INT_MAX; // Every address is lower
|
||||||
address_t maximal_ip = 0;
|
address_t maximal_ip = 0;
|
||||||
address_t minimal_data = 0x100000; // 1 Mbyte
|
address_t minimal_data = 0x100000; // 1 Mbyte
|
||||||
address_t maximal_data = 0;
|
address_t maximal_data = 0;
|
||||||
|
|
||||||
for (ElfReader::section_iterator it = m_elf.sec_begin();
|
for (ElfReader::section_iterator it = m_elf->sec_begin();
|
||||||
it != m_elf.sec_end(); ++it) {
|
it != m_elf->sec_end(); ++it) {
|
||||||
const ElfSymbol &symbol = *it;
|
const ElfSymbol &symbol = *it;
|
||||||
std::string prefix(".text");
|
std::string prefix(".text");
|
||||||
if (symbol.getName().compare(0, prefix.size(), prefix) == 0) {
|
if (symbol.getName().compare(0, prefix.size(), prefix) == 0) {
|
||||||
@ -130,6 +172,20 @@ bool GenericExperiment::cb_start_experiment() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (cmd[E9_FILE]) {
|
||||||
|
m_log << "enabled logging on port E9 for SDC-detection" << std::endl;
|
||||||
|
enabled_e9_sol = true;
|
||||||
|
e9_file = std::string(cmd[E9_FILE].first()->arg);
|
||||||
|
e9_goldenrun = loadFile(e9_file);
|
||||||
|
|
||||||
|
// Limit the serial-output logger buffer to prevent overly large memory
|
||||||
|
// consumption in case the target system ends up, e.g., in an endless
|
||||||
|
// loop. "+ 1" to be able to detect the case when the target system
|
||||||
|
// makes a correct output but faultily adds extra characters
|
||||||
|
// afterwards.
|
||||||
|
e9_sol.setLimit(e9_goldenrun.size() + 1);
|
||||||
|
}
|
||||||
|
|
||||||
if (cmd[WRITE_MEM_TEXT]) {
|
if (cmd[WRITE_MEM_TEXT]) {
|
||||||
m_log << "Catch writes to text segment from " << hex << minimal_ip << " to " << maximal_ip << std::endl;
|
m_log << "Catch writes to text segment from " << hex << minimal_ip << " to " << maximal_ip << std::endl;
|
||||||
enabled_mem_text = true;
|
enabled_mem_text = true;
|
||||||
@ -145,7 +201,7 @@ bool GenericExperiment::cb_start_experiment() {
|
|||||||
|
|
||||||
l_mem_outerspace.setWatchAddress(maximal_data);
|
l_mem_outerspace.setWatchAddress(maximal_data);
|
||||||
l_mem_outerspace.setTriggerAccessType(MemAccessEvent::MEM_WRITE);
|
l_mem_outerspace.setTriggerAccessType(MemAccessEvent::MEM_WRITE);
|
||||||
l_mem_outerspace.setWatchWidth(0xfffffff0);
|
l_mem_outerspace.setWatchWidth(0xfffffff0 - maximal_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cmd[TRAP]) {
|
if (cmd[TRAP]) {
|
||||||
@ -187,6 +243,15 @@ bool GenericExperiment::cb_start_experiment() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool GenericExperiment::cb_before_fast_forward()
|
||||||
|
{
|
||||||
|
if (enabled_e9_sol) {
|
||||||
|
// output may already appear *before* FI
|
||||||
|
simulator.addFlow(&e9_sol);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool GenericExperiment::cb_before_resume() {
|
bool GenericExperiment::cb_before_resume() {
|
||||||
if (enabled_trap)
|
if (enabled_trap)
|
||||||
simulator.addListener(&l_trap);
|
simulator.addListener(&l_trap);
|
||||||
@ -216,7 +281,6 @@ void GenericExperiment::cb_after_resume(fail::BaseListener *event) {
|
|||||||
// Record the crash time
|
// Record the crash time
|
||||||
result->set_crash_time(simulator.getTimerTicks());
|
result->set_crash_time(simulator.getTimerTicks());
|
||||||
|
|
||||||
|
|
||||||
if (event == &l_timeout) {
|
if (event == &l_timeout) {
|
||||||
handleEvent(*result, result->TIMEOUT, m_Timeout);
|
handleEvent(*result, result->TIMEOUT, m_Timeout);
|
||||||
} else if (event == &l_trap) {
|
} else if (event == &l_trap) {
|
||||||
@ -236,6 +300,16 @@ void GenericExperiment::cb_after_resume(fail::BaseListener *event) {
|
|||||||
const ElfSymbol *symbol = listener_to_symbol[event];
|
const ElfSymbol *symbol = listener_to_symbol[event];
|
||||||
handleEvent(*result, result->OK_MARKER, symbol->getAddress());
|
handleEvent(*result, result->OK_MARKER, symbol->getAddress());
|
||||||
|
|
||||||
|
// check experiment's data for SDC
|
||||||
|
if (enabled_e9_sol) {
|
||||||
|
// compare golden run to experiment
|
||||||
|
std::string e9_experiment = e9_sol.getOutput();
|
||||||
|
if ( ! (e9_experiment.size() == e9_goldenrun.size()
|
||||||
|
&& equal(e9_experiment.begin(), e9_experiment.end(), e9_goldenrun.begin())) ) {
|
||||||
|
handleEvent(*result, result->SDC, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} else if (FAIL_marker.find(event) != FAIL_marker.end()) {
|
} else if (FAIL_marker.find(event) != FAIL_marker.end()) {
|
||||||
const ElfSymbol *symbol = listener_to_symbol[event];
|
const ElfSymbol *symbol = listener_to_symbol[event];
|
||||||
handleEvent(*result, result->FAIL_MARKER, symbol->getAddress());
|
handleEvent(*result, result->FAIL_MARKER, symbol->getAddress());
|
||||||
@ -263,4 +337,10 @@ void GenericExperiment::cb_after_resume(fail::BaseListener *event) {
|
|||||||
} else {
|
} else {
|
||||||
handleEvent(*result, result->UNKNOWN, 0);
|
handleEvent(*result, result->UNKNOWN, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// remove and reset 0xE9 logger even if this run was not "OK"
|
||||||
|
if (enabled_e9_sol) {
|
||||||
|
simulator.removeFlow(&e9_sol);
|
||||||
|
e9_sol.resetOutput();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -7,6 +7,7 @@
|
|||||||
#include "efw/JobClient.hpp"
|
#include "efw/JobClient.hpp"
|
||||||
#include "util/Logger.hpp"
|
#include "util/Logger.hpp"
|
||||||
#include "util/ElfReader.hpp"
|
#include "util/ElfReader.hpp"
|
||||||
|
#include "../plugins/serialoutput/SerialOutputLogger.hpp"
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <map>
|
#include <map>
|
||||||
@ -14,10 +15,16 @@
|
|||||||
|
|
||||||
|
|
||||||
class GenericExperiment : public fail::DatabaseExperiment {
|
class GenericExperiment : public fail::DatabaseExperiment {
|
||||||
fail::ElfReader m_elf;
|
fail::ElfReader *m_elf;
|
||||||
|
std::string elf_file;
|
||||||
|
|
||||||
std::string m_state_dir;
|
std::string m_state_dir;
|
||||||
|
|
||||||
|
bool enabled_e9_sol;
|
||||||
|
std::string e9_file;
|
||||||
|
SerialOutputLogger e9_sol;
|
||||||
|
std::vector<char> e9_goldenrun;
|
||||||
|
|
||||||
bool enabled_mem_text;
|
bool enabled_mem_text;
|
||||||
fail::MemAccessListener l_mem_text;
|
fail::MemAccessListener l_mem_text;
|
||||||
|
|
||||||
@ -51,6 +58,7 @@ class GenericExperiment : public fail::DatabaseExperiment {
|
|||||||
public:
|
public:
|
||||||
GenericExperiment() : DatabaseExperiment("GenericExperiment"),
|
GenericExperiment() : DatabaseExperiment("GenericExperiment"),
|
||||||
m_state_dir("state"),
|
m_state_dir("state"),
|
||||||
|
e9_sol(0xE9),
|
||||||
l_trap(fail::ANY_TRAP), l_timeout(0) {
|
l_trap(fail::ANY_TRAP), l_timeout(0) {
|
||||||
enabled_mem_text = false;
|
enabled_mem_text = false;
|
||||||
enabled_mem_outerspace = false;
|
enabled_mem_outerspace = false;
|
||||||
@ -90,6 +98,14 @@ public:
|
|||||||
*/
|
*/
|
||||||
virtual bool cb_start_experiment();
|
virtual bool cb_start_experiment();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Callback that is called before the fast forward is done. This
|
||||||
|
* can be used to add additional event listeners during the fast
|
||||||
|
* forward phase. If returning false, the experiment is canceled.
|
||||||
|
* @return \c true on success, \c false otherwise
|
||||||
|
*/
|
||||||
|
virtual bool cb_before_fast_forward();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Callback that is called before the resuming till crash has
|
* Callback that is called before the resuming till crash has
|
||||||
* started. This is called after the fault was injected. Here the
|
* started. This is called after the fault was injected. Here the
|
||||||
|
|||||||
@ -13,7 +13,7 @@ message GenericExperimentMessage {
|
|||||||
OK_MARKER = 1;
|
OK_MARKER = 1;
|
||||||
FAIL_MARKER = 2;
|
FAIL_MARKER = 2;
|
||||||
DETECTED_MARKER = 3;
|
DETECTED_MARKER = 3;
|
||||||
|
|
||||||
GROUP1_MARKER = 4;
|
GROUP1_MARKER = 4;
|
||||||
GROUP2_MARKER = 5;
|
GROUP2_MARKER = 5;
|
||||||
GROUP3_MARKER = 6;
|
GROUP3_MARKER = 6;
|
||||||
@ -24,6 +24,8 @@ message GenericExperimentMessage {
|
|||||||
WRITE_TEXTSEGMENT = 10;
|
WRITE_TEXTSEGMENT = 10;
|
||||||
WRITE_OUTERSPACE = 11;
|
WRITE_OUTERSPACE = 11;
|
||||||
|
|
||||||
|
SDC = 12;
|
||||||
|
|
||||||
UNKNOWN = 100;
|
UNKNOWN = 100;
|
||||||
}
|
}
|
||||||
// result type, see above
|
// result type, see above
|
||||||
|
|||||||
@ -62,11 +62,13 @@ void GenericTracing::parseOptions() {
|
|||||||
CommandLine::option_handle START_ADDRESS = cmd.addOption("B", "start-address", Arg::Required,
|
CommandLine::option_handle START_ADDRESS = cmd.addOption("B", "start-address", Arg::Required,
|
||||||
"-B,--start-address \tStart Address to start tracing");
|
"-B,--start-address \tStart Address to start tracing");
|
||||||
CommandLine::option_handle STOP_ADDRESS = cmd.addOption("E", "end-address",Arg::Required,
|
CommandLine::option_handle STOP_ADDRESS = cmd.addOption("E", "end-address",Arg::Required,
|
||||||
"-E--end-address \tEnd Address to end tracing");
|
"-E,--end-address \tEnd Address to end tracing");
|
||||||
CommandLine::option_handle SERIAL_PORT = cmd.addOption("", "serial-port", Arg::Required,
|
CommandLine::option_handle SERIAL_PORT = cmd.addOption("", "serial-port", Arg::Required,
|
||||||
"--serial-port \tListen to a given I/O address (default: 0x3F8)");
|
"--serial-port \tListen to a given I/O address (default: 0x3F8)");
|
||||||
CommandLine::option_handle SERIAL_FILE = cmd.addOption("", "serial-file", Arg::Required,
|
CommandLine::option_handle SERIAL_FILE = cmd.addOption("", "serial-file", Arg::Required,
|
||||||
"--serial-file \tSave the serial output to file");
|
"--serial-file \tSave the serial output to file");
|
||||||
|
CommandLine::option_handle E9_FILE = cmd.addOption("", "e9-file", Arg::Required,
|
||||||
|
"--e9-file FILE \tData logged via port 0xE9 is stored in this file");
|
||||||
|
|
||||||
if (!cmd.parse()) {
|
if (!cmd.parse()) {
|
||||||
cerr << "Error parsing arguments." << endl;
|
cerr << "Error parsing arguments." << endl;
|
||||||
@ -228,6 +230,14 @@ void GenericTracing::parseOptions() {
|
|||||||
serial_file = "";
|
serial_file = "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (cmd[E9_FILE]) {
|
||||||
|
e9_file = std::string(cmd[E9_FILE].first()->arg);
|
||||||
|
m_log << "port E9 output is written to: " << e9_file << std::endl;
|
||||||
|
} else {
|
||||||
|
e9_file = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
if (m_elf != NULL) {
|
if (m_elf != NULL) {
|
||||||
m_log << "start/save symbol: " << start_symbol << " 0x" << std::hex << start_address << std::endl;
|
m_log << "start/save symbol: " << start_symbol << " 0x" << std::hex << start_address << std::endl;
|
||||||
m_log << "stop symbol: " << stop_symbol << " 0x" << std::hex << stop_address << std::endl;
|
m_log << "stop symbol: " << stop_symbol << " 0x" << std::hex << stop_address << std::endl;
|
||||||
@ -287,6 +297,12 @@ bool GenericTracing::run()
|
|||||||
simulator.addFlow(&sol);
|
simulator.addFlow(&sol);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SerialOutputLogger e9_sol(0xE9);
|
||||||
|
if (e9_file != "") {
|
||||||
|
simulator.addFlow(&e9_sol);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////
|
||||||
// Step 2: Continue to the stop point
|
// Step 2: Continue to the stop point
|
||||||
simulator.addListener(&l_stop_symbol);
|
simulator.addListener(&l_stop_symbol);
|
||||||
@ -314,6 +330,17 @@ bool GenericTracing::run()
|
|||||||
of_serial.close();
|
of_serial.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (e9_file != "") {
|
||||||
|
simulator.removeFlow(&e9_sol);
|
||||||
|
ofstream of_e9(e9_file.c_str(), ios::out|ios::binary);
|
||||||
|
if (!of_e9.fail()) {
|
||||||
|
of_e9 << e9_sol.getOutput();
|
||||||
|
} else {
|
||||||
|
m_log << "failed to write " << e9_file << endl;
|
||||||
|
}
|
||||||
|
of_e9.close();
|
||||||
|
}
|
||||||
|
|
||||||
simulator.clearListeners();
|
simulator.clearListeners();
|
||||||
simulator.terminate();
|
simulator.terminate();
|
||||||
|
|
||||||
|
|||||||
@ -28,6 +28,8 @@ class GenericTracing : public fail::ExperimentFlow {
|
|||||||
fail::guest_address_t serial_port;
|
fail::guest_address_t serial_port;
|
||||||
std::string serial_file;
|
std::string serial_file;
|
||||||
|
|
||||||
|
std::string e9_file;
|
||||||
|
|
||||||
fail::Logger m_log;
|
fail::Logger m_log;
|
||||||
fail::ElfReader *m_elf;
|
fail::ElfReader *m_elf;
|
||||||
|
|
||||||
|
|||||||
@ -40,6 +40,11 @@ public:
|
|||||||
* Returns the output variable.
|
* Returns the output variable.
|
||||||
*/
|
*/
|
||||||
std::string getOutput();
|
std::string getOutput();
|
||||||
|
/**
|
||||||
|
* Sets the character limit. Does not truncate the stored data if it
|
||||||
|
* already exceeds the new limit. 0 = unlimited.
|
||||||
|
*/
|
||||||
|
void setLimit(unsigned char_limit) { m_limit = char_limit; }
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // __SERIAL_OUTPUT_LOGGER_HPP__
|
#endif // __SERIAL_OUTPUT_LOGGER_HPP__
|
||||||
|
|||||||
@ -6,6 +6,9 @@ option(BUILD_CONVERT_TRACE "Build the trace converter tool?" OFF)
|
|||||||
option(BUILD_COMPUTE_HOPS "Build the compute hops tool?" OFF)
|
option(BUILD_COMPUTE_HOPS "Build the compute hops tool?" OFF)
|
||||||
option(BUILD_DUMP_HOPS "Build the hops dump tool?" OFF)
|
option(BUILD_DUMP_HOPS "Build the hops dump tool?" OFF)
|
||||||
|
|
||||||
|
option(BUILD_FAULTSPACEPLOT "Build the faultspace plotting tool?" OFF)
|
||||||
|
option(BUILD_DATA_AGGREGATOR "Build the data aggregation tools?" OFF)
|
||||||
|
|
||||||
### Setup search paths for headers ##
|
### Setup search paths for headers ##
|
||||||
include_directories(${CMAKE_CURRENT_BINARY_DIR}/../src/core)
|
include_directories(${CMAKE_CURRENT_BINARY_DIR}/../src/core)
|
||||||
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../src/core)
|
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../src/core)
|
||||||
@ -33,3 +36,11 @@ endif(BUILD_COMPUTE_HOPS)
|
|||||||
if(BUILD_DUMP_HOPS)
|
if(BUILD_DUMP_HOPS)
|
||||||
add_subdirectory(dump-hops)
|
add_subdirectory(dump-hops)
|
||||||
endif(BUILD_DUMP_HOPS)
|
endif(BUILD_DUMP_HOPS)
|
||||||
|
|
||||||
|
if(BUILD_FAULTSPACEPLOT)
|
||||||
|
add_subdirectory(analysis/faultspaceplot)
|
||||||
|
endif(BUILD_FAULTSPACEPLOT)
|
||||||
|
|
||||||
|
if(BUILD_DATA_AGGREGATOR)
|
||||||
|
add_subdirectory(analysis/data-aggregator)
|
||||||
|
endif(BUILD_DATA_AGGREGATOR)
|
||||||
|
|||||||
1
tools/analysis/data-aggregator/CMakeLists.txt
Normal file
1
tools/analysis/data-aggregator/CMakeLists.txt
Normal file
@ -0,0 +1 @@
|
|||||||
|
install(PROGRAMS function-occurrences.sh resulttype-occurrences.sh resulttype-occurrences_coverage.sh symbol-occurrences.sh symbol-occurrences_coverage.sh translation-unit-occurrences.sh variant-durations.sh DESTINATION bin)
|
||||||
38
tools/analysis/data-aggregator/function-occurrences.sh
Executable file
38
tools/analysis/data-aggregator/function-occurrences.sh
Executable file
@ -0,0 +1,38 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
set -e
|
||||||
|
|
||||||
|
if [ "$1" = -t ]; then
|
||||||
|
FORMAT=-t
|
||||||
|
shift
|
||||||
|
else
|
||||||
|
FORMAT=-B
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ ! $# -eq 3 ]; then
|
||||||
|
echo "usage: $0 [ -t ] DATABASE VARIANT BENCHMARK" >&2
|
||||||
|
echo " -t Display output in table format (tab-separated CSV otherwise)" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
DATABASE=$1
|
||||||
|
VARIANT=$2
|
||||||
|
BENCHMARK=$3
|
||||||
|
MYSQL="mysql $FORMAT $DATABASE"
|
||||||
|
|
||||||
|
$MYSQL << EOT
|
||||||
|
SELECT s.name, s.address, r.resulttype, SUM(t.time2-t.time1+1) AS occurrences
|
||||||
|
FROM variant v
|
||||||
|
JOIN symbol s
|
||||||
|
ON s.variant_id = v.id
|
||||||
|
JOIN trace t
|
||||||
|
ON t.variant_id = s.variant_id AND t.instr2_absolute BETWEEN s.address AND s.address + s.size - 1
|
||||||
|
JOIN fspgroup g
|
||||||
|
ON g.variant_id = t.variant_id AND g.data_address = t.data_address AND g.instr2 = t.instr2
|
||||||
|
JOIN result_GenericExperimentMessage r
|
||||||
|
ON r.pilot_id = g.pilot_id
|
||||||
|
WHERE v.variant="$VARIANT"
|
||||||
|
AND v.benchmark="$BENCHMARK"
|
||||||
|
GROUP BY s.variant_id, s.address, r.resulttype
|
||||||
|
ORDER BY s.address, r.resulttype
|
||||||
|
;
|
||||||
|
EOT
|
||||||
50
tools/analysis/data-aggregator/resulttype-occurrences.sh
Executable file
50
tools/analysis/data-aggregator/resulttype-occurrences.sh
Executable file
@ -0,0 +1,50 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
set -e
|
||||||
|
|
||||||
|
if [ "$1" = -t ]; then
|
||||||
|
FORMAT=-t
|
||||||
|
shift
|
||||||
|
else
|
||||||
|
FORMAT=-B
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ $# -ne 3 -a $# -ne 1 ]; then
|
||||||
|
echo "usage: $0 [ -t ] DATABASE [ VARIANT BENCHMARK ]" >&2
|
||||||
|
echo " -t Display output in table format (tab-separated CSV otherwise)" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
DATABASE=$1
|
||||||
|
VARIANT=$2
|
||||||
|
BENCHMARK=$3
|
||||||
|
MYSQL="mysql $FORMAT $DATABASE"
|
||||||
|
|
||||||
|
if [ -z "$VARIANT" ]; then
|
||||||
|
$MYSQL << EOT
|
||||||
|
SET sql_mode = 'NO_UNSIGNED_SUBTRACTION';
|
||||||
|
SELECT v.benchmark, v.variant, r.resulttype, SUM((t.time2-t.time1+1) * t.width) AS occurrences
|
||||||
|
FROM result_GenericExperimentMessage r
|
||||||
|
INNER JOIN fspgroup g ON g.pilot_id=r.pilot_id
|
||||||
|
INNER JOIN trace t ON g.instr2=t.instr2
|
||||||
|
AND g.data_address=t.data_address
|
||||||
|
AND g.variant_id=t.variant_id
|
||||||
|
INNER JOIN variant v ON t.variant_id=v.id
|
||||||
|
GROUP BY v.id, r.resulttype
|
||||||
|
ORDER BY v.benchmark, v.variant, r.resulttype;
|
||||||
|
EOT
|
||||||
|
else
|
||||||
|
$MYSQL << EOT
|
||||||
|
SET sql_mode = 'NO_UNSIGNED_SUBTRACTION';
|
||||||
|
SELECT r.resulttype, SUM((t.time2-t.time1+1) * t.width) AS occurrences
|
||||||
|
FROM result_GenericExperimentMessage r
|
||||||
|
INNER JOIN fspgroup g ON g.pilot_id=r.pilot_id
|
||||||
|
INNER JOIN trace t ON g.instr2=t.instr2
|
||||||
|
AND g.data_address=t.data_address
|
||||||
|
AND g.variant_id=t.variant_id
|
||||||
|
INNER JOIN variant v ON t.variant_id=v.id
|
||||||
|
WHERE v.variant="$VARIANT"
|
||||||
|
AND v.benchmark="$BENCHMARK"
|
||||||
|
GROUP BY r.resulttype
|
||||||
|
ORDER BY r.resulttype ASC;
|
||||||
|
EOT
|
||||||
|
fi
|
||||||
70
tools/analysis/data-aggregator/resulttype-occurrences_coverage.sh
Executable file
70
tools/analysis/data-aggregator/resulttype-occurrences_coverage.sh
Executable file
@ -0,0 +1,70 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
set -e
|
||||||
|
|
||||||
|
if [ "$1" = -t ]; then
|
||||||
|
FORMAT=-t
|
||||||
|
shift
|
||||||
|
else
|
||||||
|
FORMAT=-B
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ $# -ne 3 -a $# -ne 1 ]; then
|
||||||
|
echo "usage: $0 [ -t ] DATABASE [ VARIANT BENCHMARK ]" >&2
|
||||||
|
echo " -t Display output in table format (tab-separated CSV otherwise)" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
DATABASE=$1
|
||||||
|
VARIANT=$2
|
||||||
|
BENCHMARK=$3
|
||||||
|
MYSQL="mysql $FORMAT $DATABASE"
|
||||||
|
|
||||||
|
if [ -z "$VARIANT" ]; then
|
||||||
|
$MYSQL << EOT
|
||||||
|
SET sql_mode = 'NO_UNSIGNED_SUBTRACTION';
|
||||||
|
SELECT v.benchmark, v.variant, r.resulttype,
|
||||||
|
SUM((t.time2-t.time1+1) * t.width)
|
||||||
|
/
|
||||||
|
(SELECT SUM(t.time2-t.time1+1)*t.width
|
||||||
|
FROM result_GenericExperimentMessage r
|
||||||
|
INNER JOIN fspgroup g ON g.pilot_id=r.pilot_id
|
||||||
|
INNER JOIN trace t ON g.instr2=t.instr2
|
||||||
|
AND g.data_address=t.data_address
|
||||||
|
AND g.variant_id=t.variant_id
|
||||||
|
WHERE t.variant_id = v.id -- refers to parent query
|
||||||
|
) AS coverage
|
||||||
|
FROM result_GenericExperimentMessage r
|
||||||
|
INNER JOIN fspgroup g ON g.pilot_id=r.pilot_id
|
||||||
|
INNER JOIN trace t ON g.instr2=t.instr2
|
||||||
|
AND g.data_address=t.data_address
|
||||||
|
AND g.variant_id=t.variant_id
|
||||||
|
INNER JOIN variant v ON t.variant_id=v.id
|
||||||
|
GROUP BY v.id, r.resulttype
|
||||||
|
ORDER BY v.benchmark, v.variant, r.resulttype;
|
||||||
|
EOT
|
||||||
|
else
|
||||||
|
$MYSQL << EOT
|
||||||
|
SET sql_mode = 'NO_UNSIGNED_SUBTRACTION';
|
||||||
|
SELECT r.resulttype,
|
||||||
|
SUM((t.time2-t.time1+1) * t.width)
|
||||||
|
/
|
||||||
|
(SELECT SUM(t.time2-t.time1+1)*t.width
|
||||||
|
FROM result_GenericExperimentMessage r
|
||||||
|
INNER JOIN fspgroup g ON g.pilot_id=r.pilot_id
|
||||||
|
INNER JOIN trace t ON g.instr2=t.instr2
|
||||||
|
AND g.data_address=t.data_address
|
||||||
|
AND g.variant_id=t.variant_id
|
||||||
|
WHERE t.variant_id = v.id -- refers to parent query
|
||||||
|
) AS coverage
|
||||||
|
FROM result_GenericExperimentMessage r
|
||||||
|
INNER JOIN fspgroup g ON g.pilot_id=r.pilot_id
|
||||||
|
INNER JOIN trace t ON g.instr2=t.instr2
|
||||||
|
AND g.data_address=t.data_address
|
||||||
|
AND g.variant_id=t.variant_id
|
||||||
|
INNER JOIN variant v ON t.variant_id=v.id
|
||||||
|
WHERE v.variant="$VARIANT"
|
||||||
|
AND v.benchmark="$BENCHMARK"
|
||||||
|
GROUP BY r.resulttype
|
||||||
|
ORDER BY r.resulttype;
|
||||||
|
EOT
|
||||||
|
fi
|
||||||
33
tools/analysis/data-aggregator/symbol-occurrences.sh
Executable file
33
tools/analysis/data-aggregator/symbol-occurrences.sh
Executable file
@ -0,0 +1,33 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
set -e
|
||||||
|
|
||||||
|
if [ "$1" = -t ]; then
|
||||||
|
FORMAT=-t
|
||||||
|
shift
|
||||||
|
else
|
||||||
|
FORMAT=-B
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ ! $# -eq 3 ]; then
|
||||||
|
echo "usage: $0 [ -t ] DATABASE VARIANT BENCHMARK" >&2
|
||||||
|
echo " -t Display output in table format (tab-separated CSV otherwise)" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
DATABASE=$1
|
||||||
|
VARIANT=$2
|
||||||
|
BENCHMARK=$3
|
||||||
|
MYSQL="mysql $FORMAT $DATABASE"
|
||||||
|
|
||||||
|
$MYSQL << EOT
|
||||||
|
SELECT v.benchmark, v.variant, s.name, s.size, r.resulttype, SUM(t.time2-t.time1+1) AS occurrences
|
||||||
|
FROM variant v
|
||||||
|
INNER JOIN symbol s ON v.id = s.variant_id
|
||||||
|
INNER JOIN trace t ON t.variant_id = v.id AND t.data_address BETWEEN s.address AND s.address + s.size - 1
|
||||||
|
INNER JOIN fspgroup g ON t.variant_id = g.variant_id AND t.data_address = g.data_address AND t.instr2 = g.instr2
|
||||||
|
INNER JOIN result_GenericExperimentMessage r ON r.pilot_id = g.pilot_id
|
||||||
|
WHERE v.variant="$VARIANT"
|
||||||
|
AND v.benchmark="$BENCHMARK"
|
||||||
|
GROUP BY v.benchmark, v.variant, s.name, r.resulttype
|
||||||
|
ORDER BY v.benchmark, v.variant, s.name, r.resulttype;
|
||||||
|
EOT
|
||||||
44
tools/analysis/data-aggregator/symbol-occurrences_coverage.sh
Executable file
44
tools/analysis/data-aggregator/symbol-occurrences_coverage.sh
Executable file
@ -0,0 +1,44 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
set -e
|
||||||
|
|
||||||
|
if [ "$1" = -t ]; then
|
||||||
|
FORMAT=-t
|
||||||
|
shift
|
||||||
|
else
|
||||||
|
FORMAT=-B
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ ! $# -eq 3 ]; then
|
||||||
|
echo "usage: $0 [ -t ] DATABASE VARIANT BENCHMARK" >&2
|
||||||
|
echo " -t Display output in table format (tab-separated CSV otherwise)" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
DATABASE=$1
|
||||||
|
VARIANT=$2
|
||||||
|
BENCHMARK=$3
|
||||||
|
MYSQL="mysql $FORMAT $DATABASE"
|
||||||
|
|
||||||
|
$MYSQL << EOT
|
||||||
|
SELECT v.benchmark, v.variant, s.name, s.size, r.resulttype,
|
||||||
|
SUM(t.time2-t.time1+1)
|
||||||
|
/
|
||||||
|
(SELECT SUM(t.time2-t.time1+1)
|
||||||
|
FROM variant v
|
||||||
|
INNER JOIN symbol s ON v.id = s.variant_id
|
||||||
|
INNER JOIN trace t ON t.variant_id = v.id AND t.data_address BETWEEN s.address AND s.address + s.size - 1
|
||||||
|
INNER JOIN fspgroup g ON t.variant_id = g.variant_id AND t.data_address = g.data_address AND t.instr2 = g.instr2
|
||||||
|
INNER JOIN result_GenericExperimentMessage r ON r.pilot_id = g.pilot_id
|
||||||
|
WHERE v.variant="$VARIANT"
|
||||||
|
AND v.benchmark="$BENCHMARK"
|
||||||
|
) AS coverage
|
||||||
|
FROM variant v
|
||||||
|
INNER JOIN symbol s ON v.id = s.variant_id
|
||||||
|
INNER JOIN trace t ON t.variant_id = v.id AND t.data_address BETWEEN s.address AND s.address + s.size - 1
|
||||||
|
INNER JOIN fspgroup g ON t.variant_id = g.variant_id AND t.data_address = g.data_address AND t.instr2 = g.instr2
|
||||||
|
INNER JOIN result_GenericExperimentMessage r ON r.pilot_id = g.pilot_id
|
||||||
|
WHERE v.variant="$VARIANT"
|
||||||
|
AND v.benchmark="$BENCHMARK"
|
||||||
|
GROUP BY v.benchmark, v.variant, s.name, r.resulttype
|
||||||
|
ORDER BY v.benchmark, v.variant, s.name, r.resulttype;
|
||||||
|
EOT
|
||||||
40
tools/analysis/data-aggregator/translation-unit-occurrences.sh
Executable file
40
tools/analysis/data-aggregator/translation-unit-occurrences.sh
Executable file
@ -0,0 +1,40 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
set -e
|
||||||
|
|
||||||
|
if [ "$1" = -t ]; then
|
||||||
|
FORMAT=-t
|
||||||
|
shift
|
||||||
|
else
|
||||||
|
FORMAT=-B
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ ! $# -eq 3 ]; then
|
||||||
|
echo "usage: $0 [ -t ] DATABASE VARIANT BENCHMARK" >&2
|
||||||
|
echo " -t Display output in table format (tab-separated CSV otherwise)" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
DATABASE=$1
|
||||||
|
VARIANT=$2
|
||||||
|
BENCHMARK=$3
|
||||||
|
MYSQL="mysql $FORMAT $DATABASE"
|
||||||
|
|
||||||
|
$MYSQL << EOT
|
||||||
|
SELECT v.benchmark, v.variant, f.path, r.resulttype, SUM(t.time2-t.time1+1) AS occurrences
|
||||||
|
FROM variant v
|
||||||
|
JOIN dbg_filename f
|
||||||
|
ON f.variant_id = v.id
|
||||||
|
JOIN dbg_mapping m
|
||||||
|
ON f.variant_id = m.variant_id AND f.file_id = m.file_id
|
||||||
|
JOIN trace t
|
||||||
|
ON t.variant_id = m.variant_id AND t.instr2_absolute BETWEEN m.instr_absolute AND m.instr_absolute + m.line_range_size - 1
|
||||||
|
JOIN fspgroup g
|
||||||
|
ON g.variant_id = t.variant_id AND g.data_address = t.data_address AND g.instr2 = t.instr2
|
||||||
|
JOIN result_GenericExperimentMessage r
|
||||||
|
ON r.pilot_id = g.pilot_id
|
||||||
|
WHERE v.variant="$VARIANT"
|
||||||
|
AND v.benchmark="$BENCHMARK"
|
||||||
|
GROUP BY v.id, f.file_id, r.resulttype
|
||||||
|
ORDER BY v.benchmark, v.variant, f.path, r.resulttype
|
||||||
|
;
|
||||||
|
EOT
|
||||||
44
tools/analysis/data-aggregator/variant-durations.sh
Executable file
44
tools/analysis/data-aggregator/variant-durations.sh
Executable file
@ -0,0 +1,44 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
set -e
|
||||||
|
|
||||||
|
if [ "$1" = -t ]; then
|
||||||
|
FORMAT=-t
|
||||||
|
shift
|
||||||
|
else
|
||||||
|
FORMAT=-B
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ $# -ne 3 -a $# -ne 1 ]; then
|
||||||
|
echo "usage: $0 [ -t ] DATABASE [ VARIANT BENCHMARK ]" >&2
|
||||||
|
echo " -t Display output in table format (tab-separated CSV otherwise)" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
DATABASE=$1
|
||||||
|
VARIANT=$2
|
||||||
|
BENCHMARK=$3
|
||||||
|
MYSQL="mysql $FORMAT $DATABASE"
|
||||||
|
|
||||||
|
if [ -z "$VARIANT" ]; then
|
||||||
|
$MYSQL << EOT
|
||||||
|
SET sql_mode = 'NO_UNSIGNED_SUBTRACTION';
|
||||||
|
SELECT v.benchmark, v.variant,
|
||||||
|
MAX(t.time2)-MIN(t.time1)+1 AS duration,
|
||||||
|
MAX(t.instr2)-MIN(t.instr1)+1 AS dyn_instr
|
||||||
|
FROM trace t
|
||||||
|
JOIN variant v ON t.variant_id = v.id
|
||||||
|
GROUP BY v.id
|
||||||
|
ORDER BY v.benchmark, v.variant;
|
||||||
|
EOT
|
||||||
|
else
|
||||||
|
$MYSQL << EOT
|
||||||
|
SET sql_mode = 'NO_UNSIGNED_SUBTRACTION';
|
||||||
|
SELECT
|
||||||
|
MAX(t.time2)-MIN(t.time1)+1 AS duration,
|
||||||
|
MAX(t.instr2)-MIN(t.instr1)+1 AS dyn_instr
|
||||||
|
FROM trace t
|
||||||
|
JOIN variant v ON t.variant_id = v.id
|
||||||
|
WHERE v.variant = "$VARIANT"
|
||||||
|
AND v.benchmark = "$BENCHMARK"
|
||||||
|
EOT
|
||||||
|
fi
|
||||||
1
tools/analysis/faultspaceplot/CMakeLists.txt
Normal file
1
tools/analysis/faultspaceplot/CMakeLists.txt
Normal file
@ -0,0 +1 @@
|
|||||||
|
install(PROGRAMS faultspaceplot.sh fsp.compact-horizontal.sh fsp.compact.sh fsp.compact-vertical.sh fsp.plot.py DESTINATION bin)
|
||||||
101
tools/analysis/faultspaceplot/faultspaceplot.sh
Executable file
101
tools/analysis/faultspaceplot/faultspaceplot.sh
Executable file
@ -0,0 +1,101 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
set -e
|
||||||
|
|
||||||
|
if [ "$1" = -k ]; then
|
||||||
|
KEEPCSV=yes
|
||||||
|
shift
|
||||||
|
else
|
||||||
|
KEEPCSV=no
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ ! $# -eq 3 ]; then
|
||||||
|
echo "usage: $0 [ -k ] DATABASE VARIANT BENCHMARK" >&2
|
||||||
|
echo " -k Keep compacted plot (and symbols) CSV" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
DATABASE=$1
|
||||||
|
VARIANT=$2
|
||||||
|
BENCHMARK=$3
|
||||||
|
MYSQL="mysql -B --quick $DATABASE"
|
||||||
|
|
||||||
|
MYDIR=$(dirname $0)
|
||||||
|
|
||||||
|
function table_exists()
|
||||||
|
{
|
||||||
|
N=$(echo "SHOW TABLES LIKE '$1'" | $MYSQL $DATABASE | wc -l)
|
||||||
|
[ $N -gt 0 ]
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
# get data
|
||||||
|
RAWCSV=$(mktemp)
|
||||||
|
echo "getting faultspace data.."
|
||||||
|
$MYSQL <<EOT > $RAWCSV
|
||||||
|
SELECT t.time1 - (SELECT MIN(t2.time1) FROM trace t2 WHERE t.variant_id = t2.variant_id) AS time1,
|
||||||
|
t.time2 - (SELECT MIN(t2.time1) FROM trace t2 WHERE t.variant_id = t2.variant_id) AS time2,
|
||||||
|
t.data_address, r.bitoffset, r.injection_width,
|
||||||
|
CASE
|
||||||
|
WHEN r.resulttype = 'OK_MARKER' THEN '#FFFFFF'
|
||||||
|
WHEN r.resulttype = 'FAIL_MARKER' THEN '#EE0000'
|
||||||
|
WHEN r.resulttype = 'DETECTED_MARKER' THEN '#00FF00'
|
||||||
|
WHEN r.resulttype = 'GROUP0_MARKER' THEN '#EAEAEA'
|
||||||
|
WHEN r.resulttype = 'GROUP1_MARKER' THEN '#EBEBEB'
|
||||||
|
WHEN r.resulttype = 'GROUP2_MARKER' THEN '#ECECEC'
|
||||||
|
WHEN r.resulttype = 'GROUP3_MARKER' THEN '#EDEDED'
|
||||||
|
WHEN r.resulttype = 'TIMEOUT' THEN '#CCCC00'
|
||||||
|
WHEN r.resulttype = 'TRAP' THEN '#00CCCC'
|
||||||
|
WHEN r.resulttype = 'WRITE_TEXTSEGMENT' THEN '#0000AA'
|
||||||
|
WHEN r.resulttype = 'WRITE_OUTERSPACE' THEN '#0000BB'
|
||||||
|
WHEN r.resulttype = 'SDC' THEN '#FF0000'
|
||||||
|
WHEN r.resulttype = 'UNKNOWN' THEN '#000000'
|
||||||
|
END AS color
|
||||||
|
FROM trace t
|
||||||
|
JOIN fspgroup g ON t.variant_id = g.variant_id AND t.data_address = g.data_address AND t.instr2 = g.instr2
|
||||||
|
JOIN variant v ON v.id = t.variant_id
|
||||||
|
JOIN result_GenericExperimentMessage r ON r.pilot_id=g.pilot_id
|
||||||
|
WHERE
|
||||||
|
v.variant = '$VARIANT' AND v.benchmark = '$BENCHMARK'
|
||||||
|
AND r.resulttype != 'OK_MARKER'
|
||||||
|
AND t.accesstype = 'R';
|
||||||
|
EOT
|
||||||
|
|
||||||
|
# compact data
|
||||||
|
echo "compacting data.."
|
||||||
|
COMPACTCSV=$(mktemp)
|
||||||
|
"$MYDIR"/fsp.compact.sh $RAWCSV $COMPACTCSV
|
||||||
|
rm $RAWCSV
|
||||||
|
|
||||||
|
# fetch symbols if available
|
||||||
|
SYMBOLCSV=
|
||||||
|
if table_exists symbol; then
|
||||||
|
SYMBOLCSV=$(mktemp)
|
||||||
|
echo "getting symbol information ..."
|
||||||
|
$MYSQL <<EOT > $SYMBOLCSV
|
||||||
|
SELECT s.address, s.size, s.name
|
||||||
|
FROM variant v
|
||||||
|
JOIN symbol s ON s.variant_id = v.id
|
||||||
|
WHERE v.variant = '$VARIANT' AND v.benchmark = '$BENCHMARK'
|
||||||
|
ORDER BY s.address
|
||||||
|
EOT
|
||||||
|
fi
|
||||||
|
|
||||||
|
# plot data
|
||||||
|
echo "plotting.."
|
||||||
|
if [ $KEEPCSV = yes ]; then
|
||||||
|
KEPT="$VARIANT"_"$BENCHMARK"-plot.csv
|
||||||
|
mv "$COMPACTCSV" "$KEPT"
|
||||||
|
COMPACTCSV=$KEPT
|
||||||
|
fi
|
||||||
|
if [ ! -z "$SYMBOLCSV" -a $(wc -l < $SYMBOLCSV) -gt 1 ]; then
|
||||||
|
if [ $KEEPCSV = yes ]; then
|
||||||
|
KEPT="$VARIANT"_"$BENCHMARK"-symbols.csv
|
||||||
|
mv "$SYMBOLCSV" "$KEPT"
|
||||||
|
SYMBOLCSV=$KEPT
|
||||||
|
fi
|
||||||
|
"$MYDIR"/fsp.plot.py "$COMPACTCSV" "$SYMBOLCSV"
|
||||||
|
[ $KEEPCSV = no ] && rm "$SYMBOLCSV"
|
||||||
|
else
|
||||||
|
"$MYDIR"/fsp.plot.py "$COMPACTCSV"
|
||||||
|
fi
|
||||||
|
[ $KEEPCSV = no ] && rm "$COMPACTCSV"
|
||||||
52
tools/analysis/faultspaceplot/fsp.compact-horizontal.sh
Executable file
52
tools/analysis/faultspaceplot/fsp.compact-horizontal.sh
Executable file
@ -0,0 +1,52 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
set -e
|
||||||
|
|
||||||
|
TMP=$(mktemp)
|
||||||
|
|
||||||
|
read HEADER
|
||||||
|
echo "$HEADER"
|
||||||
|
|
||||||
|
BASE=''
|
||||||
|
LAST=''
|
||||||
|
sort -snk 1 | sort -snk 4 | sort -snk 3 > $TMP
|
||||||
|
|
||||||
|
while read CUR
|
||||||
|
do
|
||||||
|
a=($CUR)
|
||||||
|
C_I1=${a[0]}
|
||||||
|
C_I2=${a[1]}
|
||||||
|
C_ADDR=${a[2]}
|
||||||
|
C_BIT=${a[3]}
|
||||||
|
C_BW=${a[4]}
|
||||||
|
C_COL=${a[5]}
|
||||||
|
|
||||||
|
if [ -z "$BASE" ]
|
||||||
|
then
|
||||||
|
BASE=$CUR
|
||||||
|
LAST=$CUR
|
||||||
|
elif (($C_I1 != $L_I2 + 1 || $L_ADDR != $C_ADDR || $L_BIT != $C_BIT || $L_BW != $C_BW)) || \
|
||||||
|
[ "$C_COL" != "$L_COL" ]
|
||||||
|
then
|
||||||
|
a=($BASE)
|
||||||
|
B_I1=${a[0]}
|
||||||
|
|
||||||
|
echo -e "$B_I1\t$L_I2\t$L_ADDR\t$L_BIT\t$L_BW\t$L_COL"
|
||||||
|
|
||||||
|
BASE=$CUR
|
||||||
|
fi
|
||||||
|
|
||||||
|
LAST="$CUR"
|
||||||
|
L_I1=$C_I1
|
||||||
|
L_I2=$C_I2
|
||||||
|
L_ADDR=$C_ADDR
|
||||||
|
L_BIT=$C_BIT
|
||||||
|
L_BW=$C_BW
|
||||||
|
L_COL=$C_COL
|
||||||
|
done < $TMP
|
||||||
|
|
||||||
|
a=($BASE)
|
||||||
|
B_I1=${a[0]}
|
||||||
|
|
||||||
|
echo -e "$B_I1\t$L_I2\t$L_ADDR\t$L_BIT\t$L_BW\t$L_COL"
|
||||||
|
|
||||||
|
rm $TMP
|
||||||
63
tools/analysis/faultspaceplot/fsp.compact-vertical.sh
Executable file
63
tools/analysis/faultspaceplot/fsp.compact-vertical.sh
Executable file
@ -0,0 +1,63 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
set -e
|
||||||
|
|
||||||
|
TMP=$(mktemp)
|
||||||
|
|
||||||
|
read HEADER
|
||||||
|
echo "$HEADER"
|
||||||
|
|
||||||
|
BASE=''
|
||||||
|
LAST=''
|
||||||
|
sort -snk 4 | sort -snk 3 | sort -snk 1 > $TMP
|
||||||
|
|
||||||
|
while read CUR
|
||||||
|
do
|
||||||
|
a=($CUR)
|
||||||
|
C_I1=${a[0]}
|
||||||
|
C_I2=${a[1]}
|
||||||
|
C_ADDR=${a[2]}
|
||||||
|
C_BIT=${a[3]}
|
||||||
|
C_BW=${a[4]}
|
||||||
|
C_COL=${a[5]}
|
||||||
|
C_N=$(($C_ADDR*8 + $C_BIT))
|
||||||
|
|
||||||
|
if [ -z "$BASE" ]
|
||||||
|
then
|
||||||
|
BASE=$CUR
|
||||||
|
LAST=$CUR
|
||||||
|
elif (($C_I1 != $L_I1 || $C_I2 != $L_I2 || \
|
||||||
|
$L_N + $L_BW != $C_N)) || \
|
||||||
|
[ "$C_COL" != "$L_COL" ]
|
||||||
|
then
|
||||||
|
a=($BASE)
|
||||||
|
B_ADDR=${a[2]}
|
||||||
|
B_BIT=${a[3]}
|
||||||
|
B_N=$(($B_ADDR*8 + $B_BIT))
|
||||||
|
|
||||||
|
BW=$(($L_N + $L_BW - $B_N))
|
||||||
|
|
||||||
|
echo -e "$L_I1\t$L_I2\t$B_ADDR\t$B_BIT\t$BW\t$L_COL"
|
||||||
|
|
||||||
|
BASE=$CUR
|
||||||
|
fi
|
||||||
|
|
||||||
|
LAST="$CUR"
|
||||||
|
L_I1=$C_I1
|
||||||
|
L_I2=$C_I2
|
||||||
|
L_ADDR=$C_ADDR
|
||||||
|
L_BIT=$C_BIT
|
||||||
|
L_BW=$C_BW
|
||||||
|
L_COL=$C_COL
|
||||||
|
L_N=$C_N
|
||||||
|
done < $TMP
|
||||||
|
|
||||||
|
a=($BASE)
|
||||||
|
B_ADDR=${a[2]}
|
||||||
|
B_BIT=${a[3]}
|
||||||
|
B_N=$(($B_ADDR*8 + $B_BIT))
|
||||||
|
|
||||||
|
BW=$(($L_N + $L_BW - $B_N))
|
||||||
|
|
||||||
|
echo -e "$L_I1\t$L_I2\t$B_ADDR\t$B_BIT\t$BW\t$L_COL"
|
||||||
|
|
||||||
|
rm $TMP
|
||||||
43
tools/analysis/faultspaceplot/fsp.compact.sh
Executable file
43
tools/analysis/faultspaceplot/fsp.compact.sh
Executable file
@ -0,0 +1,43 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
set -e
|
||||||
|
|
||||||
|
FIRST=vertical
|
||||||
|
|
||||||
|
[ $# -lt 2 -o $# -gt 3 ] && echo "usage: $0 input.csv output.csv [vertical|horizontal]" >&2 && exit 1
|
||||||
|
|
||||||
|
if [ -z $3 ]; then
|
||||||
|
FIRST=vertical
|
||||||
|
else
|
||||||
|
FIRST=$3
|
||||||
|
fi
|
||||||
|
|
||||||
|
TMP1=$(mktemp)
|
||||||
|
TMP2=$(mktemp)
|
||||||
|
|
||||||
|
cp $1 $TMP1
|
||||||
|
COUNT=$(wc -l <$TMP1)
|
||||||
|
|
||||||
|
NEXT=$FIRST
|
||||||
|
|
||||||
|
while true
|
||||||
|
do
|
||||||
|
echo "at $COUNT, $NEXT ..."
|
||||||
|
fsp.compact-$NEXT.sh < $TMP1 > $TMP2
|
||||||
|
|
||||||
|
PREVCOUNT=$COUNT
|
||||||
|
COUNT=$(wc -l <$TMP2)
|
||||||
|
|
||||||
|
if (($COUNT >= $PREVCOUNT))
|
||||||
|
then
|
||||||
|
echo "no improvement (now $COUNT), stop."
|
||||||
|
cp $TMP1 $2
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
|
||||||
|
mv $TMP2 $TMP1
|
||||||
|
if [ $NEXT = vertical ]; then
|
||||||
|
NEXT=horizontal
|
||||||
|
else
|
||||||
|
NEXT=vertical
|
||||||
|
fi
|
||||||
|
done
|
||||||
167
tools/analysis/faultspaceplot/fsp.plot.py
Executable file
167
tools/analysis/faultspaceplot/fsp.plot.py
Executable file
@ -0,0 +1,167 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
# -------------------------------------------------------------------------
|
||||||
|
# Import modules
|
||||||
|
import csv, sys
|
||||||
|
import matplotlib.pyplot as plt
|
||||||
|
import numpy as np
|
||||||
|
import matplotlib.patches as mpatches
|
||||||
|
import matplotlib.pylab as pylab
|
||||||
|
|
||||||
|
ENTRY_COUNT_PER_LINE = 6
|
||||||
|
RESULT_RECT_HEIGHT = 1.0/8
|
||||||
|
|
||||||
|
# -------------------------------------------------------------------------
|
||||||
|
# Basic drawing class
|
||||||
|
class Rectangle:
|
||||||
|
def __init__(self, x, y, w, h, color):
|
||||||
|
# w
|
||||||
|
self.xpos = x # |-------------------|
|
||||||
|
self.ypos = y # | | h
|
||||||
|
self.width = w # | |
|
||||||
|
self.height = h # (x,y)---------------|
|
||||||
|
self.color = color # fill color
|
||||||
|
self.alpha = None # transparency level [0,1]
|
||||||
|
def draw(self):
|
||||||
|
""" Draw the rectangle. """
|
||||||
|
if self.color == (1,1,1):
|
||||||
|
return
|
||||||
|
tmp = self.xpos, self.ypos,
|
||||||
|
p = mpatches.Rectangle(tmp, self.width, self.height, color=self.color, \
|
||||||
|
alpha=self.alpha)
|
||||||
|
plt.gca().add_patch(p)
|
||||||
|
|
||||||
|
# -------------------------------------------------------------------------
|
||||||
|
# Check provided arguments:
|
||||||
|
if len(sys.argv) <= 1:
|
||||||
|
print "ERROR: Not enough arguments provided! See -h for more infos."
|
||||||
|
exit(1)
|
||||||
|
if sys.argv[1] == '-h':
|
||||||
|
print "Displays experiment results for the weather-monitor-experiment."
|
||||||
|
print " CALL-SYNTAX: fsp.plot.py DATA_FILE [USER_TAG_FILE]"
|
||||||
|
print "DATA_FILE is a CSV-file, storing the tab-separated values"
|
||||||
|
print "retrieved by the experiment run. USER_TAG_FILE is an optional"
|
||||||
|
print "CSV-file which can be used to add user-specific marks to the"
|
||||||
|
print "plot." # TODO: be more precise here
|
||||||
|
exit(0)
|
||||||
|
|
||||||
|
print "Opening and processing \"" + sys.argv[1] + "\"..."
|
||||||
|
file = open(sys.argv[1], "r")
|
||||||
|
dialect = csv.Sniffer().sniff(file.read(1024))
|
||||||
|
file.seek(0)
|
||||||
|
reader = csv.reader(file, dialect)
|
||||||
|
reader.next() # Move down a line to skip the header
|
||||||
|
|
||||||
|
if len(sys.argv) >= 3:
|
||||||
|
print "Opening and processing \"" + sys.argv[2] + "\"..."
|
||||||
|
symbolfile = open(sys.argv[2], "r")
|
||||||
|
dialect = csv.Sniffer().sniff(symbolfile.read(1024))
|
||||||
|
symbolfile.seek(0)
|
||||||
|
symbolreader = csv.reader(symbolfile, dialect)
|
||||||
|
symbolreader.next() # Move down a line to skip the header
|
||||||
|
have_symbols = True
|
||||||
|
else:
|
||||||
|
have_symbols = False
|
||||||
|
|
||||||
|
fig = plt.figure()
|
||||||
|
|
||||||
|
xmin = 99999999
|
||||||
|
xmax = 0
|
||||||
|
ymin = 99999999
|
||||||
|
ymax = 0
|
||||||
|
|
||||||
|
line_counter = 1
|
||||||
|
for row in reader:
|
||||||
|
line_counter += 1
|
||||||
|
# Check if there are at least ENTRY_COUNT_PER_LINE entries per line:
|
||||||
|
if len(row) != ENTRY_COUNT_PER_LINE:
|
||||||
|
print "ERROR: Line " + str(line_counter) + " is invalid (" +\
|
||||||
|
str(ENTRY_COUNT_PER_LINE) + " entries expected)"
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
# Some constants to access the row-entries much easier:
|
||||||
|
IDX_INSTR1 = 0; IDX_INSTR2 = 1; IDX_DATA_ADDRESS = 2;
|
||||||
|
IDX_BITNR = 3; IDX_BITWIDTH = 4; IDX_COLOR = 5;
|
||||||
|
|
||||||
|
# Update xmin/xmax/ymin/ymax
|
||||||
|
x1 = int(row[IDX_INSTR1])
|
||||||
|
x2 = int(row[IDX_INSTR2]) + 1 # inclusive
|
||||||
|
width = x2 - x1
|
||||||
|
if xmin > x1:
|
||||||
|
xmin = x1
|
||||||
|
if xmax < x2:
|
||||||
|
xmax = x2
|
||||||
|
|
||||||
|
y1 = float(row[IDX_DATA_ADDRESS]) + float(row[IDX_BITNR]) / 8.0
|
||||||
|
height = float(row[IDX_BITWIDTH]) / 8.0
|
||||||
|
y2 = y1 + height
|
||||||
|
|
||||||
|
if ymin > y1:
|
||||||
|
ymin = y1
|
||||||
|
if ymax < y2:
|
||||||
|
ymax = y2
|
||||||
|
|
||||||
|
Rectangle(x1, y1, width, height, row[IDX_COLOR]).draw()
|
||||||
|
if line_counter == 50000: # debug stuff
|
||||||
|
pass
|
||||||
|
#break
|
||||||
|
|
||||||
|
# round down to nearest 1000
|
||||||
|
#ymin = int(ymin / 1000) * 1000
|
||||||
|
|
||||||
|
file.close()
|
||||||
|
plt.xlim(xmin, xmax)
|
||||||
|
plt.ylim(ymin, ymax)
|
||||||
|
|
||||||
|
plt.ylabel('Data Memory (RAM)')
|
||||||
|
plt.xlabel('Time (Cycles)')
|
||||||
|
|
||||||
|
# show symbols
|
||||||
|
if have_symbols:
|
||||||
|
# Adding 2nd y-axis for object names
|
||||||
|
ax1 = fig.add_subplot(111)
|
||||||
|
ax2 = ax1.twinx()
|
||||||
|
ax2.set_ylabel('Symbols')
|
||||||
|
|
||||||
|
# necessary for proper symbol placement
|
||||||
|
plt.ylim(ymin, ymax)
|
||||||
|
|
||||||
|
ticks = []
|
||||||
|
symbols = []
|
||||||
|
|
||||||
|
IDX_SYMBOL_ADDRESS = 0; IDX_SYMBOL_SIZE = 1; IDX_SYMBOL_NAME = 2;
|
||||||
|
|
||||||
|
for row in symbolreader:
|
||||||
|
# TODO: somehow plot size as well
|
||||||
|
address = int(row[IDX_SYMBOL_ADDRESS])
|
||||||
|
size = int(row[IDX_SYMBOL_SIZE])
|
||||||
|
if (address >= ymin) and (address <= ymax):
|
||||||
|
ticks.append(address)
|
||||||
|
symbols.append(row[IDX_SYMBOL_NAME])
|
||||||
|
#print "symbol: " + str(address) + " " + str(size) + " " + row[IDX_SYMBOL_NAME]
|
||||||
|
elif (address < ymin) and (address + size >= ymin):
|
||||||
|
ticks.append(ymin)
|
||||||
|
symbols.append("(" + row[IDX_SYMBOL_NAME] + ")")
|
||||||
|
#print "partial symbol: " + str(address) + " " + str(size) + " " + row[IDX_SYMBOL_NAME]
|
||||||
|
else:
|
||||||
|
#print "skipped symbol: " + str(address) + " " + str(size) + " " + row[IDX_SYMBOL_NAME]
|
||||||
|
pass
|
||||||
|
|
||||||
|
# list of interesting addresses
|
||||||
|
ax2.yaxis.set_ticks(ticks)
|
||||||
|
ax2.yaxis.grid(b=True, color='gray')
|
||||||
|
|
||||||
|
# create minor ticks centered between major tick marks
|
||||||
|
centered_ticks = []
|
||||||
|
major_locator = ax2.yaxis.get_major_locator()
|
||||||
|
major_locs = major_locator()
|
||||||
|
for i in range(1,len(major_locs)):
|
||||||
|
y_last,y = major_locs[i-1],major_locs[i]
|
||||||
|
centered_ticks.append(0.5*(y+y_last))
|
||||||
|
ax2.yaxis.set_ticks(centered_ticks, minor=True)
|
||||||
|
|
||||||
|
# list of corresponding symbol names
|
||||||
|
ax2.set_yticklabels(symbols, minor=False, rotation=0, rotation_mode='anchor')
|
||||||
|
|
||||||
|
plt.show()
|
||||||
|
#pylab.savefig('baseline.pdf', bbox_inches='tight')
|
||||||
@ -42,3 +42,4 @@ if (BUILD_LLVM_DISASSEMBLER)
|
|||||||
endif (BUILD_LLVM_DISASSEMBLER)
|
endif (BUILD_LLVM_DISASSEMBLER)
|
||||||
|
|
||||||
install(TARGETS import-trace RUNTIME DESTINATION bin)
|
install(TARGETS import-trace RUNTIME DESTINATION bin)
|
||||||
|
install(PROGRAMS import-symbols.sh DESTINATION bin)
|
||||||
|
|||||||
86
tools/import-trace/import-symbols.sh
Executable file
86
tools/import-trace/import-symbols.sh
Executable file
@ -0,0 +1,86 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# TODO: make this part of import-trace
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# handle command line arguments
|
||||||
|
if [ ! $# -eq 4 ]; then
|
||||||
|
echo "usage: $0 DATABASE VARIANT BENCHMARK ELF" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
DATABASE=$1
|
||||||
|
VARIANT=$2
|
||||||
|
BENCHMARK=$3
|
||||||
|
ELF=$4
|
||||||
|
TABLE=symbol
|
||||||
|
MYSQL="mysql -B --quick $DATABASE"
|
||||||
|
|
||||||
|
|
||||||
|
# check if ELF exists
|
||||||
|
if [ ! -e $ELF ]; then
|
||||||
|
echo "$ELF not found" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
echo "importing $VARIANT/$BENCHMARK symbols from $ELF ..."
|
||||||
|
|
||||||
|
|
||||||
|
# get fail*'s variant_id
|
||||||
|
ID=$(echo "SELECT id FROM variant WHERE variant='$VARIANT' AND benchmark='$BENCHMARK'" | $MYSQL -N)
|
||||||
|
if [ -z $ID ]; then
|
||||||
|
echo "no such variant/benchmark!" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
# generate huge SQL statement and execute
|
||||||
|
$MYSQL <<EOT
|
||||||
|
CREATE TABLE IF NOT EXISTS $TABLE (
|
||||||
|
variant_id INT NOT NULL,
|
||||||
|
address INT UNSIGNED NOT NULL,
|
||||||
|
size INT UNSIGNED NOT NULL,
|
||||||
|
name VARCHAR(255) NOT NULL,
|
||||||
|
PRIMARY KEY (variant_id, address)
|
||||||
|
) ENGINE=MyISAM;
|
||||||
|
EOT
|
||||||
|
(
|
||||||
|
# clean symbol table
|
||||||
|
echo "DELETE FROM $TABLE WHERE variant_id = $ID;"
|
||||||
|
|
||||||
|
LAST_ADDR=
|
||||||
|
LAST_SYMBOL=
|
||||||
|
|
||||||
|
# The "dummy" entry at the end makes sure the last real symbol from the
|
||||||
|
# nm output makes it into the database.
|
||||||
|
(nm -n -S -C $ELF; echo ffffffff a dummy) \
|
||||||
|
| egrep '^[0-9a-fA-F]' | while read line
|
||||||
|
do
|
||||||
|
ADDR=$(echo "$line"|awk '{print $1}')
|
||||||
|
SIZE=$(echo "$line"|awk '{print $2}')
|
||||||
|
if echo $SIZE | egrep -q '^[0-9a-fA-F]{8}'; then
|
||||||
|
SYMBOL=$(echo "$line"|awk '{for (i=1; i<=NF-3; i++) $i = $(i+3); NF-=3; print}')
|
||||||
|
else
|
||||||
|
SIZE=unknown
|
||||||
|
SYMBOL=$(echo "$line"|awk '{for (i=1; i<=NF-2; i++) $i = $(i+2); NF-=2; print}')
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ $LAST_ADDR ]; then
|
||||||
|
# only create INSERT-line, if $ADDR is new to us
|
||||||
|
if [ ! $ADDR = $LAST_ADDR ]; then
|
||||||
|
echo "INSERT INTO $TABLE (variant_id, address, size, name) VALUES "
|
||||||
|
echo "($ID, cast(0x$LAST_ADDR AS UNSIGNED), CAST(0x$ADDR AS UNSIGNED)-CAST(0x$LAST_ADDR AS UNSIGNED), '$LAST_SYMBOL');"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ $SIZE != unknown ]; then
|
||||||
|
echo "INSERT INTO $TABLE (variant_id, address, size, name) VALUES "
|
||||||
|
echo "($ID, cast(0x$ADDR AS UNSIGNED), CAST(0x$SIZE AS UNSIGNED), '$SYMBOL');"
|
||||||
|
LAST_ADDR=
|
||||||
|
LAST_SYMBOL=
|
||||||
|
else
|
||||||
|
LAST_ADDR=$ADDR
|
||||||
|
LAST_SYMBOL=$SYMBOL
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
) | $MYSQL
|
||||||
|
|
||||||
|
echo "ANALYZE TABLE $TABLE;" | $MYSQL
|
||||||
Reference in New Issue
Block a user