ecos: campaign rewrite for MySQL data store

We're not yet using the common DatabaseCampaign as it doesn't allow
for additional experiment parameters (such as "variant" and
"benchmark") yet.  TODO: Integrate changes in DatabaseCampaign in a
generic way and use it.

Change-Id: I45480003be433654aea8d3a417fbfa66be31155b
This commit is contained in:
Horst Schirmeier
2013-04-24 17:19:38 +02:00
committed by Gerrit Code Review
parent 392a6e6eb8
commit 0887a53d1d
5 changed files with 195 additions and 342 deletions

View File

@ -27,9 +27,9 @@ PROTOBUF_GENERATE_CPP(PROTO_SRCS PROTO_HDRS ${MY_PROTOS})
## Build library
add_library(fail-${EXPERIMENT_NAME} ${PROTO_SRCS} ${PROTO_HDRS} ${MY_CAMPAIGN_SRCS})
add_dependencies(fail-${EXPERIMENT_NAME} fail-tracing fail-comm)
target_link_libraries(fail-${EXPERIMENT_NAME} ${PROTOBUF_LIBRARY})
target_link_libraries(fail-${EXPERIMENT_NAME} ${PROTOBUF_LIBRARY} -lmysqlclient_r)
## This is the example's campaign server distributing experiment parameters
add_executable(${EXPERIMENT_NAME}-server main.cc)
target_link_libraries(${EXPERIMENT_NAME}-server fail-${EXPERIMENT_NAME} fail ${PROTOBUF_LIBRARY} ${Boost_THREAD_LIBRARY})
target_link_libraries(${EXPERIMENT_NAME}-server fail-${EXPERIMENT_NAME} fail ${PROTOBUF_LIBRARY} ${Boost_THREAD_LIBRARY} -lmysqlclient_r)
install(TARGETS ${EXPERIMENT_NAME}-server RUNTIME DESTINATION bin)

View File

@ -2,6 +2,7 @@
#include <fstream>
#include <vector>
#include <map>
#include <sstream>
#include "campaign.hpp"
#include "experimentInfo.hpp"
@ -9,11 +10,10 @@
#include "util/ProtoStream.hpp"
#include "util/MemoryMap.hpp"
#include "util/gzstream/gzstream.h"
#include "util/CommandLine.hpp"
#include "../plugins/tracing/TracingPlugin.hpp"
//#define PRUNING_DEBUG_OUTPUT
using namespace std;
using namespace fail;
@ -114,14 +114,6 @@ std::string EcosKernelTestCampaign::filename_traceinfo(const std::string& varian
return "traceinfo.txt";
}
std::string EcosKernelTestCampaign::filename_results(const std::string& variant, const std::string& benchmark)
{
if (variant.size() && benchmark.size()) {
return dir_results + "/" + variant + "-" + benchmark + "-" + "results.csv";
}
return "results.csv";
}
std::string EcosKernelTestCampaign::filename_elf(const std::string& variant, const std::string& benchmark)
{
if (variant.size() && benchmark.size()) {
@ -146,350 +138,217 @@ char const *variants[] = {
0
};
// big four (three): (mutex3,) bin_sem2, clocktruth, sync2
// busy waiters, sloooow at ips=2666mhz: kill, mutex3, clocktruth
// batch 1: line 1
char const *benchmarks[] = {
#if 1
"bin_sem0", "bin_sem1", "bin_sem2", "bin_sem3", "clock1", "clockcnv",
"clocktruth", "cnt_sem1", "except1", "flag1", "kill", "mqueue1", "mutex1",
"mutex2", "mutex3", "release", "sched1", "sync2", "sync3", "thread0",
/*"clocktruth",*/ "cnt_sem1", "except1", "flag1", /*"kill",*/ "mqueue1", "mutex1",
"mutex2", /*"mutex3",*/ "release", "sched1", "sync2", "sync3", "thread0",
"thread1", "thread2",
#elif 0
"sync2",
#endif
0
};
bool EcosKernelTestCampaign::run()
{
m_log << "startup" << endl;
CommandLine &cmd = CommandLine::Inst();
if (!init_results()) {
return false;
cmd.addOption("", "", Arg::None, "USAGE: fail-server [options...]");
CommandLine::option_handle HELP =
cmd.addOption("h", "help", Arg::None, "-h/--help \tPrint usage and exit");
CommandLine::option_handle RESULTTABLE =
cmd.addOption("r", "resulttable", Arg::Required, "-r/--resulttable \tTable to store results in (default: 'result')");
Database::cmdline_setup();
if (!cmd.parse()) {
m_log << "Error parsing arguments." << std::endl;
exit(1);
}
if (cmd[HELP].count() > 0) {
cmd.printUsage();
exit(0);
}
if (cmd[RESULTTABLE].count() > 0) {
m_result_table = std::string(cmd[RESULTTABLE].first()->arg);
} else {
m_result_table = std::string("result");
}
m_log << "Storing results in table '" << m_result_table << "'\n";
db = Database::cmdline_connect();
db_recv = Database::cmdline_connect();
fspmethod_id = 1; // constant for now
std::stringstream ss;
ss << "CREATE TABLE IF NOT EXISTS " << m_result_table << " ("
"pilot_id int(11) NOT NULL,\n"
"bitnr tinyint(4) NOT NULL,\n"
"bit_width tinyint(4) NOT NULL,\n"
"resulttype tinyint(4) NOT NULL,\n"
"ecos_test_result tinyint(4) NOT NULL,\n"
"latest_ip int(10) unsigned DEFAULT NULL,\n"
"error_corrected tinyint(4) NOT NULL,\n"
"details varchar(255) DEFAULT NULL,\n"
"runtime float NOT NULL,\n"
"PRIMARY KEY (pilot_id,bitnr))\n"
"ENGINE = MyISAM";
if (!db->query(ss.str().c_str())) return false;
// collect results in parallel to avoid deadlock
#ifndef __puma
boost::thread collect_thread(&EcosKernelTestCampaign::collect_results, this);
#endif
ss.str("");
/* Gather all unfinished jobs */
m_log << "Looking for unfinished jobs in the database ..." << std::endl;
ss << "(";
for (int variant_nr = 0; variants[variant_nr]; ++variant_nr) {
char const *variant = variants[variant_nr];
for (int benchmark_nr = 0; benchmarks[benchmark_nr]; ++benchmark_nr) {
char const *benchmark = benchmarks[benchmark_nr];
// local copies of experiment/job count (to calculate differences)
int local_count_exp = count_exp, local_count_exp_jobs = count_exp_jobs,
local_count_known = count_known, local_count_known_jobs = count_known_jobs;
// load trace
igzstream tracef(filename_trace(variant, benchmark).c_str());
if (tracef.fail()) {
m_log << "couldn't open " << filename_trace(variant, benchmark) << endl;
return false;
}
ProtoIStream ps(&tracef);
// read trace info
unsigned instr_counter, estimated_timeout, lowest_addr, highest_addr;
// FIXME properly deal with 2nd memory range
EcosKernelTestCampaign::readTraceInfo(instr_counter,
estimated_timeout, lowest_addr, highest_addr, lowest_addr, highest_addr, variant, benchmark);
// a map of addresses of ECC protected objects
MemoryMap mm;
mm.readFromFile(filename_memorymap(variant, benchmark).c_str());
// map for keeping one "open" EC for every address
// (maps injection data address => equivalence class)
AddrLastaccessMap open_ecs;
// instruction counter within trace
unsigned instr = 0;
// "rightmost" instr where we did a FI experiment
unsigned instr_rightmost = 0;
// fill open_ecs with one EC for every address
for (MemoryMap::iterator it = mm.begin(); it != mm.end(); ++it) {
open_ecs[*it] = instr;
}
// absolute address of current trace instruction
address_t instr_absolute = 0;
Trace_Event ev;
// for every event in the trace ...
while (ps.getNext(&ev) && instr < instr_counter) {
// instruction events just get counted
if (!ev.has_memaddr()) {
// new instruction
instr++;
instr_absolute = ev.ip();
continue;
}
// for each single byte in this memory access ...
for (address_t data_address = ev.memaddr();
data_address < ev.memaddr() + ev.width();
++data_address) {
// skip accesses to data outside our map of interesting addresses
AddrLastaccessMap::iterator lastuse_it;
if ((lastuse_it = open_ecs.find(data_address)) == open_ecs.end()) {
continue;
}
int instr1 = lastuse_it->second;
int instr2 = instr;
// skip zero-sized intervals: these can occur when an instruction
// accesses a memory location more than once (e.g., INC, CMPXCHG)
if (instr1 > instr2) {
continue;
}
// we now have an interval-terminating R/W event to the memaddr
// we're currently looking at; the EC is defined by
// data_address [instr1, instr2] (instr_absolute)
if (ev.accesstype() == ev.READ) {
// a sequence ending with READ: we need to do one experiment to
// cover it completely
add_experiment_ec(variant, benchmark, data_address, instr1, instr2, instr_absolute);
instr_rightmost = instr2;
} else if (ev.accesstype() == ev.WRITE) {
// a sequence ending with WRITE: an injection anywhere here
// would have no effect.
add_known_ec(variant, benchmark, data_address, instr1, instr2, instr_absolute);
} else {
m_log << "WAT" << endl;
}
// next interval must start at next instruction; the aforementioned
// skipping mechanism wouldn't work otherwise
lastuse_it->second = instr2 + 1;
}
}
// close all open intervals (right end of the fault-space)
for (AddrLastaccessMap::iterator lastuse_it = open_ecs.begin();
lastuse_it != open_ecs.end(); ++lastuse_it) {
address_t data_address = lastuse_it->first;
int instr1 = lastuse_it->second;
ss << "v.variant = '" << variant << "' OR ";
}
ss << "0) AND ("; // dummy terminator
for (int benchmark_nr = 0; benchmarks[benchmark_nr]; ++benchmark_nr) {
char const *benchmark = benchmarks[benchmark_nr];
ss << "v.benchmark = '" << benchmark << "' OR ";
}
ss << "0)"; // dummy terminator
std::string sql_variants = ss.str();
ss.str("");
#if 0
// Why -1? In most cases it does not make sense to inject before the
// very last instruction, as we won't execute it anymore. This *only*
// makes sense if we also inject into parts of the result vector. This
// is not the case in this experiment, and with -1 we'll get a result
// comparable to the non-pruned campaign.
int instr2 = instr - 1;
#else
// EcosKernelTestCampaign only variant: fault space ends with the last FI experiment
int instr2 = instr_rightmost;
ss << "SELECT STRAIGHT_JOIN p.id AS pilot_id, v.id AS variant_id, v.variant, v.benchmark, p.injection_instr, p.injection_instr_absolute, p.data_address, SUM(r.bit_width) AS existing_results "
<< "FROM variant v "
<< "JOIN fsppilot p ON p.variant_id = v.id "
<< "LEFT JOIN result r ON r.pilot_id = p.id "
<< "WHERE p.known_outcome = 0 "
<< " AND p.fspmethod_id = " << fspmethod_id << " "
<< " AND (" << sql_variants << ") "
<< "GROUP BY p.id "
<< "HAVING existing_results < 8 OR existing_results IS NULL "; // 8 results per pilot
#elif 0
std::string sql_select = "SELECT p.id AS pilot_id, v.id AS variant_id, v.variant, v.benchmark, p.injection_instr, p.injection_instr_absolute, p.data_address ";
ss << "FROM variant v "
<< "JOIN fsppilot p ON p.variant_id = v.id "
<< "LEFT JOIN " << m_result_table << " r ON r.pilot_id = p.id "
<< "WHERE p.known_outcome = 0 "
<< " AND p.fspmethod_id = " << fspmethod_id << " "
<< " AND (" << sql_variants << ") "
<< " AND r.pilot_id IS NULL ";
#elif 0
std::string sql_select = "SELECT p.id AS pilot_id, v.id AS variant_id, v.variant, v.benchmark, p.injection_instr, p.injection_instr_absolute, p.data_address ";
ss << "FROM variant v "
<< "JOIN fsppilot p ON p.variant_id = v.id "
// << "WHERE p.known_outcome = 0 "
<< " AND p.fspmethod_id = " << fspmethod_id << " "
<< " AND (" << sql_variants << ") ";
#elif 1
if (!db->query("CREATE TEMPORARY TABLE done_pilots (id INT UNSIGNED NOT NULL PRIMARY KEY)")) return false;
ss << "INSERT INTO done_pilots SELECT pilot_id FROM " << m_result_table << " GROUP BY pilot_id HAVING SUM(bit_width) = 8";
if (!db->query(ss.str().c_str())) return false;
unsigned finished_jobs = db->affected_rows();
ss.str("");
ss << "DELETE r FROM " << m_result_table << " r LEFT JOIN done_pilots ON r.pilot_id = done_pilots.id WHERE done_pilots.id IS NULL";
if (!db->query(ss.str().c_str())) return false;
unsigned deleted_rows = db->affected_rows();
ss.str("");
m_log << "Deleted " << deleted_rows << " rows from incomplete jobs" << std::endl;
std::string sql_select = "SELECT STRAIGHT_JOIN p.id AS pilot_id, v.id AS variant_id, v.variant, v.benchmark, p.injection_instr, p.injection_instr_absolute, p.data_address ";
ss << "FROM variant v "
<< "JOIN fsppilot p ON p.variant_id = v.id "
<< "LEFT JOIN done_pilots d ON d.id = p.id "
<< "WHERE d.id IS NULL "
<< " AND p.fspmethod_id = " << fspmethod_id << " "
<< " AND (" << sql_variants << ") ";
#endif
int instr_absolute = 0; // unknown
std::string sql_body = ss.str();
//std::string sql_order = "ORDER BY v.benchmark, v.variant";
std::string sql_order = "ORDER BY v.id";
//std::string sql_order = "";
// zero-sized? skip.
if (instr1 > instr2) {
continue;
}
/* Get the number of unfinished experiments */
std::string sql_count = "SELECT COUNT(*) " + sql_body;
m_log << sql_count << std::endl;
MYSQL_RES *count = db->query(sql_count.c_str(), true);
if (!count) {
return false;
}
MYSQL_ROW row = mysql_fetch_row(count);
unsigned unfinished_jobs;
unfinished_jobs = strtoul(row[0], NULL, 10);
#if 0
// the run continues after the FI window, so do this experiment
// XXX this creates at least one experiment for *every* bit!
// fix: full trace, limited FI window
m_log << "Found " << unfinished_jobs << " unfinished jobs (" << finished_jobs << " already finished)." << std::endl;
ecs_need_experiment.push_back(current_ec);
add_experiment_ec(variant, benchmark, data_address, instr1, instr2, instr_absolute);
#else
// as the experiment ends, this byte is a "don't care":
add_known_ec(variant, benchmark, data_address, instr1, instr2, instr_absolute);
#endif
}
// conserve some memory
open_ecs.clear();
// progress report
m_log << variant << "/" << benchmark
<< " exp " << (count_exp - local_count_exp) << " (" << (count_exp_jobs - local_count_exp_jobs) << " jobs)"
<< " known " << (count_known - local_count_known) << " (" << (count_known_jobs - local_count_known_jobs) << " jobs)"
<< " faultspace cutoff @ " << instr_rightmost << " out of " << instr
<< endl;
}
std::string sql_pilots = sql_select + sql_body + sql_order;
m_log << sql_pilots << std::endl;
MYSQL_RES *pilots = db->query_stream(sql_pilots.c_str());
if (!pilots) {
return false;
}
available_results.clear();
m_log << "Filling queue ..." << std::endl;
unsigned prev_variant_id = 0;
while ((row = mysql_fetch_row(pilots))) {
unsigned pilot_id = atoi(row[0]);
unsigned variant_id = atoi(row[1]);
unsigned injection_instr = atoi(row[4]);
unsigned data_address = atoi(row[6]);
EcosKernelTestExperimentData *d = new EcosKernelTestExperimentData;
d->msg.set_pilot_id(pilot_id);
d->msg.set_variant(row[2]);
d->msg.set_benchmark(row[3]);
d->msg.set_instr2_offset(injection_instr);
if (row[5]) {
unsigned injection_instr_absolute = atoi(row[5]);
d->msg.set_instr2_address(injection_instr_absolute);
}
d->msg.set_mem_addr(data_address);
d->msg.set_faultmodel(ECOS_FAULTMODEL_BURST ? d->msg.BURST : d->msg.SINGLEBITFLIP);
if (prev_variant_id != variant_id) {
m_log << "Enqueueing jobs for " << row[2] << "/" << row[3] << std::endl;
}
prev_variant_id = variant_id;
campaignmanager.addParam(d);
}
if (mysql_errno(db->getHandle())) {
std::cerr << "mysql_fetch_row failed: " << mysql_error(db->getHandle()) << std::endl;
}
delete db;
m_log << "finished, waiting for the clients to complete ..." << std::endl;
campaignmanager.noMoreParameters();
m_log << "total"
<< " exp " << count_exp << " (" << count_exp_jobs << " jobs)"
<< " known " << count_known << " (" << count_known_jobs << " jobs)"
<< endl;
// collect results
#ifndef __puma
collect_thread.join();
#endif
finalize_results();
m_log << "done." << endl;
delete db_recv;
m_log << "results complete, terminating." << std::endl;
return true;
}
bool EcosKernelTestCampaign::add_experiment_ec(const std::string& variant, const std::string& benchmark,
address_t data_address, int instr1, int instr2, address_t instr_absolute)
{
if (check_available(variant, benchmark, data_address, instr2)) {
return false;
}
count_exp_jobs++;
if (ECOS_FAULTMODEL_BURST) {
count_exp++;
} else {
count_exp += 8;
}
// enqueue job
#if 1
EcosKernelTestExperimentData *d = new EcosKernelTestExperimentData;
d->msg.set_variant(variant);
d->msg.set_benchmark(benchmark);
d->msg.set_instr1_offset(instr1);
d->msg.set_instr2_offset(instr2);
d->msg.set_instr2_address(instr_absolute);
d->msg.set_mem_addr(data_address);
d->msg.set_faultmodel(ECOS_FAULTMODEL_BURST ? d->msg.BURST : d->msg.SINGLEBITFLIP);
campaignmanager.addParam(d);
#endif
return true;
}
bool EcosKernelTestCampaign::add_known_ec(const std::string& variant, const std::string& benchmark,
address_t data_address, int instr1, int instr2, address_t instr_absolute)
{
if (check_available(variant, benchmark, data_address, instr2)) {
return false;
}
count_known_jobs++;
if (ECOS_FAULTMODEL_BURST) {
count_known++;
} else {
count_known += 8;
}
#if 1
add_result(variant, benchmark, instr1, instr2, instr_absolute, data_address,
0, 8, // bitnr, bit_width
1, // resulttype
1, // ecos_test_result
99, // latest_ip
0, // error_corrected
"", // details
0 // runtime
);
#endif
return true;
}
bool EcosKernelTestCampaign::init_results()
{
// read already existing results
bool file_exists = false;
ifstream oldresults(filename_results().c_str(), ios::in);
if (oldresults.is_open()) {
file_exists = true;
char buf[16*1024];
std::string variant, benchmark;
unsigned ignore;
int instr2;
address_t data_address;
int bit_width;
int rowcount = 0;
int expcount = 0;
m_log << "scanning existing results ..." << endl;
while (oldresults.getline(buf, sizeof(buf)).good()) {
stringstream ss;
ss << buf;
ss >> hex >> variant >> benchmark >> ignore >> instr2 >> ignore
>> data_address >> ignore >> bit_width;
if (ss.fail()) {
continue;
}
++rowcount;
expcount += bit_width;
// TODO: sanity check (duplicates?)
available_results
[AvailableResultMap::key_type(variant, benchmark)]
[data_address].insert(instr2);
}
m_log << "found " << dec << expcount << " existing experiment results ("
<< rowcount << " CSV rows)" << endl;
oldresults.close();
}
// non-destructive: due to the CSV header we can always manually recover
// from an accident (append mode)
resultstream.open(filename_results().c_str(), ios::out | ios::app);
if (!resultstream.is_open()) {
m_log << "failed to open " << filename_results() << endl;
return false;
}
// only write CSV header if file didn't exist before
if (!file_exists) {
resultstream << "variant\tbenchmark\tec_instr1\tec_instr2\t"
"ec_instr2_absolute\tec_data_address\tbitnr\tbit_width\t"
"resulttype\tecos_test_result\tlatest_ip\t"
"error_corrected\tdetails\truntime" << endl;
}
return true;
}
bool EcosKernelTestCampaign::check_available(const std::string& variant, const std::string& benchmark,
address_t data_address, int instr2)
{
AvailableResultMap::const_iterator it_variant =
available_results.find(AvailableResultMap::key_type(variant, benchmark));
if (it_variant == available_results.end()) {
return false;
}
AvailableResultMap::mapped_type::const_iterator it_address =
it_variant->second.find(data_address);
if (it_address == it_variant->second.end()) {
return false;
}
AvailableResultMap::mapped_type::mapped_type::const_iterator it_instr =
it_address->second.find(instr2);
if (it_instr == it_address->second.end()) {
return false;
}
return true;
}
void EcosKernelTestCampaign::add_result(const std::string& variant, const std::string& benchmark,
int instr1, int instr2, address_t instr2_absolute, address_t ec_data_address,
void EcosKernelTestCampaign::add_result(unsigned pilot_id,
int instr2, address_t instr2_absolute, address_t ec_data_address,
int bitnr, int bit_width, int resulttype, int ecos_test_result, address_t latest_ip,
int error_corrected, const std::string& details, float runtime)
{
#ifndef __puma
boost::lock_guard<boost::mutex> guard(m_result_mutex);
#endif
resultstream << hex
<< variant << "\t"
<< benchmark << "\t"
<< instr1 << "\t"
<< instr2 << "\t"
<< instr2_absolute << "\t"
<< ec_data_address << "\t"
<< bitnr << "\t"
<< bit_width << "\t"
<< resulttype << "\t"
<< ecos_test_result << "\t"
<< latest_ip << "\t"
<< error_corrected << "\t"
<< details << "\t"
<< runtime << "\n";
//resultstream.flush(); // for debugging purposes
}
void EcosKernelTestCampaign::finalize_results()
{
resultstream.close();
std::stringstream ss;
ss << "INSERT DELAYED INTO " << m_result_table << " "
<< "(pilot_id, bitnr, bit_width, resulttype, ecos_test_result, latest_ip, error_corrected, details, runtime) VALUES "
<< "(" << pilot_id << "," << bitnr << "," << bit_width << "," << resulttype << "," << ecos_test_result << ","
<< latest_ip << "," << error_corrected << ",'" << details << "'," << runtime << ")";
// Database::query is protected by a mutex
db_recv->query(ss.str().c_str());
}
void EcosKernelTestCampaign::collect_results()
@ -526,7 +385,7 @@ void EcosKernelTestCampaign::collect_results()
bit_width++;
continue;
}
add_result(res->msg.variant(), res->msg.benchmark(), res->msg.instr1_offset(),
add_result(res->msg.pilot_id(),
res->msg.instr2_offset(), res->msg.instr2_address(), res->msg.mem_addr(),
first_bit, bit_width, prev_singleres->resulttype(), prev_singleres->ecos_test_result(),
prev_singleres->latest_ip(), prev_singleres->error_corrected(), prev_singleres->details(),
@ -541,7 +400,7 @@ void EcosKernelTestCampaign::collect_results()
bit_width = 8;
prev_singleres = &res->msg.result(0);
#endif
add_result(res->msg.variant(), res->msg.benchmark(), res->msg.instr1_offset(),
add_result(res->msg.pilot_id(),
res->msg.instr2_offset(), res->msg.instr2_address(), res->msg.mem_addr(),
first_bit, bit_width, prev_singleres->resulttype(), prev_singleres->ecos_test_result(),
prev_singleres->latest_ip(), prev_singleres->error_corrected(), prev_singleres->details(),

View File

@ -2,11 +2,13 @@
#include <string>
#include <fstream>
#include <mysql/mysql.h>
#ifndef __puma
#include <boost/thread.hpp>
#endif
#include "util/Database.hpp"
#include "cpn/Campaign.hpp"
#include "comm/ExperimentData.hpp"
#include "ecos_kernel_test.pb.h"
@ -20,33 +22,21 @@ public:
};
class EcosKernelTestCampaign : public fail::Campaign {
fail::Database *db;
fail::Database *db_recv;
int fspmethod_id;
static const std::string dir_images;
static const std::string dir_prerequisites;
static const std::string dir_results;
std::string m_result_table;
fail::Logger m_log;
int count_exp, count_exp_jobs;
int count_known, count_known_jobs;
bool add_experiment_ec(const std::string& variant, const std::string& benchmark,
fail::address_t data_address, int instr1, int instr2, fail::address_t instr_absolute);
bool add_known_ec(const std::string& variant, const std::string& benchmark,
fail::address_t data_address, int instr1, int instr2, fail::address_t instr_absolute);
bool init_results();
void add_result(const std::string& variant, const std::string& benchmark,
int instr1, int instr2, fail::address_t instr2_absolute, fail::address_t ec_data_address,
void add_result(unsigned pilot_id,
int instr2, fail::address_t instr2_absolute, fail::address_t ec_data_address,
int bitnr, int bit_width, int resulttype, int ecos_test_result, fail::address_t latest_ip,
int error_corrected, const std::string& details, float runtime);
void finalize_results();
void collect_results();
bool check_available(const std::string& variant, const std::string& benchmark, fail::address_t data_address, int instr2);
std::ofstream resultstream;
typedef std::map<std::pair<const std::string, const std::string>, std::map<fail::address_t, std::set<int> > > AvailableResultMap;
AvailableResultMap available_results;
#ifndef __puma
boost::mutex m_result_mutex;
#endif
public:
EcosKernelTestCampaign() : m_log("EcosKernelTest Campaign"),
count_exp(0), count_exp_jobs(0), count_known(0), count_known_jobs(0) {}
EcosKernelTestCampaign() : m_log("EcosKernelTest Campaign") {}
virtual bool run();
static bool readMemoryMap(fail::MemoryMap &mm, char const * const filename);
static bool writeTraceInfo(unsigned instr_counter, unsigned timeout, unsigned mem1_low, unsigned mem1_high, unsigned mem2_low, unsigned mem2_high, const std::string& variant = "", const std::string& benchmark = "");
@ -55,6 +45,5 @@ public:
static std::string filename_state(unsigned instr_offset, const std::string& variant = "", const std::string& benchmark = "");
static std::string filename_trace(const std::string& variant = "", const std::string& benchmark = "");
static std::string filename_traceinfo(const std::string& variant = "", const std::string& benchmark = "");
static std::string filename_results(const std::string& variant = "", const std::string& benchmark = "");
static std::string filename_elf(const std::string& variant = "", const std::string& benchmark = "");
};

View File

@ -7,8 +7,8 @@ message EcosKernelTestProtoMsg {
// benchmark
required string benchmark = 2;
// equivalence class start (for storage)
required int32 instr1_offset = 3;
// pilot ID (database)
required int32 pilot_id = 3;
// FI at #instructions from experiment start
required int32 instr2_offset = 4;
// the exact IP value at this point in time (from golden run)

View File

@ -3,9 +3,14 @@
#include "cpn/CampaignManager.hpp"
#include "campaign.hpp"
#include "util/CommandLine.hpp"
int main(int argc, char **argv)
{
fail::CommandLine &cmd = fail::CommandLine::Inst();
for (int i = 1; i < argc; ++i)
cmd.add_args(argv[i]);
EcosKernelTestCampaign c;
if (fail::campaignmanager.runCampaign(&c)) {
return 0;