Merge branch 'failpanda'
Conflicts: src/core/comm/DatabaseCampaignMessage.proto.in src/core/cpn/CMakeLists.txt src/core/cpn/DatabaseCampaign.cc src/core/sal/ConcreteCPU.hpp src/core/sal/SALConfig.hpp src/core/util/CMakeLists.txt Change-Id: Id86b93d0e3ea4d9963fcc88605eec0603575ec83
This commit is contained in:
@ -7,8 +7,21 @@ set(SRCS
|
||||
find_package(MySQL REQUIRED)
|
||||
include_directories(${MYSQL_INCLUDE_DIR})
|
||||
|
||||
# only compile concrete implementation of InjectionPoint
|
||||
if(CONFIG_INJECTIONPOINT_HOPS)
|
||||
set (SRCS ${SRCS} InjectionPointHops.cc)
|
||||
else(CONFIG_INJECTIONPOINT_HOPS)
|
||||
set (SRCS ${SRCS} InjectionPointSteps.cc)
|
||||
endif(CONFIG_INJECTIONPOINT_HOPS)
|
||||
|
||||
add_library(fail-cpn ${SRCS})
|
||||
target_link_libraries(fail-cpn fail-comm fail-util ${MYSQL_LIBRARIES})
|
||||
|
||||
# if hop-chains need to be calculated by the server, we
|
||||
# the smarthopping module
|
||||
if(CONFIG_INJECTIONPOINT_HOPS)
|
||||
add_dependencies(fail-cpn fail-smarthops)
|
||||
endif(CONFIG_INJECTIONPOINT_HOPS)
|
||||
|
||||
# make sure protobufs are generated before we include them
|
||||
add_dependencies(fail-cpn fail-comm)
|
||||
|
||||
@ -4,7 +4,7 @@
|
||||
#include "util/Logger.hpp"
|
||||
#include "util/Database.hpp"
|
||||
#include "comm/ExperimentData.hpp"
|
||||
|
||||
#include "InjectionPoint.hpp"
|
||||
|
||||
#ifndef __puma
|
||||
#include <boost/thread.hpp>
|
||||
@ -131,10 +131,13 @@ bool DatabaseCampaign::run_variant(Database::Variant variant) {
|
||||
/* Gather jobs */
|
||||
int experiment_count;
|
||||
std::stringstream ss;
|
||||
std::string sql_select = "SELECT p.id, p.fspmethod_id, p.variant_id, p.injection_instr, p.injection_instr_absolute, p.data_address, p.data_width ";
|
||||
std::string sql_select = "SELECT p.id, p.injection_instr, p.injection_instr_absolute, p.data_address, p.data_width, t.instr1, t.instr2 ";
|
||||
ss << " FROM fsppilot p "
|
||||
<< " WHERE p.fspmethod_id = " << fspmethod_id
|
||||
<< " AND p.variant_id = " << variant.id;
|
||||
<< " JOIN trace t"
|
||||
<< " ON t.variant_id = p.variant_id AND t.data_address = p.data_address AND t.instr2 = p.instr2"
|
||||
<< " WHERE p.fspmethod_id = " << fspmethod_id
|
||||
<< " AND p.variant_id = " << variant.id
|
||||
<< " ORDER BY t.instr1"; // Smart-Hopping needs this ordering
|
||||
std::string sql_body = ss.str();
|
||||
|
||||
/* Get the number of unfinished experiments */
|
||||
@ -148,6 +151,12 @@ bool DatabaseCampaign::run_variant(Database::Variant variant) {
|
||||
log_send << "Found " << experiment_count << " jobs in database. ("
|
||||
<< variant.variant << "/" << variant.benchmark << ")" << std::endl;
|
||||
|
||||
// abstraction of injection point:
|
||||
// must not be initialized in loop, because hop chain calculator would lose
|
||||
// state after loop pass and so for every hop chain it would have to begin
|
||||
// calculating at trace instruction zero
|
||||
ConcreteInjectionPoint ip;
|
||||
|
||||
unsigned expected_results = expected_number_of_results(variant.variant, variant.benchmark);
|
||||
|
||||
unsigned sent_pilots = 0, skipped_pilots = 0;
|
||||
@ -158,20 +167,26 @@ bool DatabaseCampaign::run_variant(Database::Variant variant) {
|
||||
continue;
|
||||
}
|
||||
|
||||
unsigned injection_instr = strtoul(row[3], NULL, 10);
|
||||
unsigned data_address = strtoul(row[5], NULL, 10);
|
||||
unsigned data_width = strtoul(row[6], NULL, 10);
|
||||
unsigned injection_instr = strtoul(row[1], NULL, 10);
|
||||
unsigned data_address = strtoul(row[3], NULL, 10);
|
||||
unsigned data_width = strtoul(row[4], NULL, 10);
|
||||
unsigned instr1 = strtoul(row[5], NULL, 10);
|
||||
unsigned instr2 = strtoul(row[6], NULL, 10);
|
||||
|
||||
DatabaseCampaignMessage pilot;
|
||||
pilot.set_pilot_id(pilot_id);
|
||||
pilot.set_fspmethod_id(fspmethod_id);
|
||||
pilot.set_variant_id(variant.id);
|
||||
// ToDo: Remove this, if all experiments work with abstract API (InjectionPoint)
|
||||
pilot.set_injection_instr(injection_instr);
|
||||
pilot.set_variant(variant.variant);
|
||||
pilot.set_benchmark(variant.benchmark);
|
||||
|
||||
if (row[4]) {
|
||||
unsigned injection_instr_absolute = strtoul(row[4], NULL, 10);
|
||||
ip.parseFromInjectionInstr(instr1, instr2);
|
||||
ip.addToCampaignMessage(pilot);
|
||||
|
||||
if (row[2]) {
|
||||
unsigned injection_instr_absolute = strtoul(row[2], NULL, 10);
|
||||
pilot.set_injection_instr_absolute(injection_instr_absolute);
|
||||
}
|
||||
pilot.set_data_address(data_address);
|
||||
|
||||
119
src/core/cpn/InjectionPoint.hpp
Normal file
119
src/core/cpn/InjectionPoint.hpp
Normal file
@ -0,0 +1,119 @@
|
||||
#ifndef INJECTIONPOINT_HPP_
|
||||
#define INJECTIONPOINT_HPP_
|
||||
|
||||
#include "comm/DatabaseCampaignMessage.pb.h"
|
||||
#include "util/Logger.hpp"
|
||||
#include "config/FailConfig.hpp"
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace fail {
|
||||
|
||||
/**
|
||||
* \class InjectionPointBase
|
||||
*
|
||||
* Interface for a generic InjectionPoint (e.g. trace instruction offset or
|
||||
* hop chain) for use in the generic DatabaseCampaign. Every
|
||||
* DataBaseCampaignMessage contains a concrete InjectionPoint.
|
||||
*/
|
||||
class InjectionPointBase {
|
||||
protected:
|
||||
InjectionPointMessage m_ip; // !< Protobuf message of concrete injection point, this class wraps
|
||||
Logger m_log;
|
||||
public:
|
||||
InjectionPointBase() : m_log("InjectionPoint") {}
|
||||
|
||||
/**
|
||||
* Parses generic representation from a injection instruction (trace offset).
|
||||
* Used by server.
|
||||
* @param inj_instr trace instruction offset to be parsed
|
||||
*/
|
||||
virtual void parseFromInjectionInstr(unsigned instr1, unsigned instr2) = 0;
|
||||
|
||||
/**
|
||||
* Parses (extracts) generic representation from a DatabaseCampaignMessage.
|
||||
* Used by client.
|
||||
* @param pilot DatabaseCampaignMessage which contains a InjectionPoint
|
||||
*/
|
||||
void parseFromCampaignMessage(const DatabaseCampaignMessage &pilot) {m_ip.CopyFrom(pilot.injection_point());}
|
||||
|
||||
/**
|
||||
* Adds generic representation to a DatabaseCampaignMessage
|
||||
* @param pilot DatabaseCampaignMessage to which the generic protobuf representation will be added
|
||||
*/
|
||||
void addToCampaignMessage(DatabaseCampaignMessage &pilot) {pilot.mutable_injection_point()->CopyFrom(m_ip);}
|
||||
|
||||
/**
|
||||
* Get a copy of the contained InjectionPointMessage
|
||||
* @param ipm Generic InjectionPointMessage to which the content will be copied
|
||||
*/
|
||||
void copyInjectionPointMessage(InjectionPointMessage &ipm) {ipm.CopyFrom(m_ip);}
|
||||
};
|
||||
|
||||
#ifdef CONFIG_INJECTIONPOINT_HOPS
|
||||
#include "comm/InjectionPointHopsMessage.pb.h"
|
||||
|
||||
class SmartHops;
|
||||
|
||||
/**
|
||||
* \class InjectionPointHops
|
||||
*
|
||||
* Concrete injection point which contains a hop chain to the target
|
||||
* trace instruction.
|
||||
*/
|
||||
class InjectionPointHops : public InjectionPointBase {
|
||||
private:
|
||||
SmartHops *m_sa; // !< Hop calculator which generates the hop chain
|
||||
|
||||
// Boundaries must be signed to ensure, they can be initialized as outside of beginning
|
||||
// of the trace (instr is -1).
|
||||
long m_curr_instr1; // !< Lower end of instructions for which currently a hop chain is available
|
||||
long m_curr_instr2; // !< Upper end of instructions for which currently a hop chain is available
|
||||
|
||||
bool m_initialized;
|
||||
std::vector<InjectionPointMessage> m_results;
|
||||
|
||||
void init();
|
||||
public:
|
||||
InjectionPointHops() : InjectionPointBase(), m_sa(NULL), m_curr_instr1(-1),
|
||||
m_curr_instr2(-1), m_initialized(false) {}
|
||||
|
||||
virtual ~InjectionPointHops();
|
||||
|
||||
/**
|
||||
* Parses a hop chain from a injection instruction (trace offset).
|
||||
* @param instr1 trace instruction offset of beginning of equivalence class
|
||||
* @param instr2 trace instruction offset of ending of equivalence class
|
||||
*/
|
||||
virtual void parseFromInjectionInstr(unsigned instr1, unsigned instr2);
|
||||
};
|
||||
|
||||
typedef InjectionPointHops ConcreteInjectionPoint;
|
||||
|
||||
#else
|
||||
#include "comm/InjectionPointStepsMessage.pb.h"
|
||||
|
||||
/**
|
||||
* \class InjectionPointSteps
|
||||
*
|
||||
* Concrete injection point which contains a trace instruction offset.
|
||||
*/
|
||||
class InjectionPointSteps : public InjectionPointBase {
|
||||
public:
|
||||
virtual ~InjectionPointSteps() {}
|
||||
|
||||
/**
|
||||
* Parses a trace offset from a injection instruction (trace offset),
|
||||
* so it effectively just stores the value in the protobuf message.
|
||||
* @param instr1 trace instruction offset of beginning of equivalence class
|
||||
* @param instr2 trace instruction offset of ending of equivalence class
|
||||
*/
|
||||
virtual void parseFromInjectionInstr(unsigned instr1, unsigned instr2);
|
||||
};
|
||||
|
||||
typedef InjectionPointSteps ConcreteInjectionPoint;
|
||||
#endif
|
||||
|
||||
} /* namespace fail */
|
||||
|
||||
#endif /* INJECTIONPOINT_HPP_ */
|
||||
110
src/core/cpn/InjectionPointHops.cc
Normal file
110
src/core/cpn/InjectionPointHops.cc
Normal file
@ -0,0 +1,110 @@
|
||||
#include "InjectionPoint.hpp"
|
||||
#include "util/smarthops/SmartHops.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <limits>
|
||||
|
||||
namespace fail {
|
||||
|
||||
InjectionPointHops::~InjectionPointHops() {
|
||||
if (m_initialized) {
|
||||
delete m_sa;
|
||||
}
|
||||
}
|
||||
|
||||
void InjectionPointHops::init()
|
||||
{
|
||||
m_sa = new SmartHops();
|
||||
|
||||
char * elfpath = getenv("FAIL_TRACE_PATH");
|
||||
if (elfpath == NULL) {
|
||||
m_log << "FAIL_TRACE_PATH not set :(" << std::endl;
|
||||
exit(-1);
|
||||
} else {
|
||||
m_sa->init((const char*) elfpath);
|
||||
}
|
||||
|
||||
m_initialized = true;
|
||||
}
|
||||
|
||||
/*
|
||||
* if (!it->has_costs()) {
|
||||
m_log << "FATAL ERROR: Costs must be delivered in order to calculate minimum costs" << endl;
|
||||
}
|
||||
*/
|
||||
|
||||
void InjectionPointHops::parseFromInjectionInstr(unsigned instr1, unsigned instr2) {
|
||||
if (!m_initialized) {
|
||||
init();
|
||||
}
|
||||
|
||||
// clear results older than instr1, as the input needs to be sorted by instr1, these
|
||||
// results won't be needed anymore
|
||||
std::vector<InjectionPointMessage>::iterator it = m_results.begin(), delete_iterator = m_results.end();
|
||||
for (; it != m_results.end(); it++) {
|
||||
if (!it->has_target_trace_position()) {
|
||||
m_log << "FATAL ERROR: Target trace offset must be delivered in order to calculate minimum costs" << std::endl;
|
||||
m_log << m_results.size() << std::endl;
|
||||
exit(0);
|
||||
}
|
||||
if (it->target_trace_position() < instr1) {
|
||||
delete_iterator = it;
|
||||
}
|
||||
}
|
||||
|
||||
// Delete as chunk
|
||||
if (delete_iterator != m_results.end()) {
|
||||
m_results.erase(m_results.begin(), delete_iterator);
|
||||
m_curr_instr1 = instr1;
|
||||
}
|
||||
|
||||
// Calculate next needed results
|
||||
while ((long)instr2 > m_curr_instr2) {
|
||||
// if instr1 is bigger than nex instr2, we can skip instructions
|
||||
// And current instr1 will be newly defined
|
||||
unsigned new_curr_instr2;
|
||||
if ((long)instr1 > m_curr_instr2) {
|
||||
m_curr_instr1 = instr1;
|
||||
new_curr_instr2 = instr1;
|
||||
} else {
|
||||
new_curr_instr2 = m_curr_instr2 + 1;
|
||||
}
|
||||
|
||||
InjectionPointMessage m;
|
||||
if (!m_sa->calculateFollowingHop(m, new_curr_instr2)) {
|
||||
m_log << "FATAL ERROR: Trace does not contain enough instructions (no instruction with offset "
|
||||
<< new_curr_instr2 << ")" << std::endl;
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
m_results.push_back(m);
|
||||
m_curr_instr2 = new_curr_instr2;
|
||||
}
|
||||
|
||||
// Choose minimum
|
||||
InjectionPointMessage *min_cost_msg;
|
||||
uint32_t min_costs = std::numeric_limits<uint32_t>::max();
|
||||
|
||||
std::vector<InjectionPointMessage>::iterator search, search_end;
|
||||
search = m_results.begin() + (instr1 - m_curr_instr1);
|
||||
search_end = m_results.begin() + (instr2 - m_curr_instr1);
|
||||
|
||||
// Single-instruction eqivalence class
|
||||
if (search == search_end) {
|
||||
m_ip = *search;
|
||||
} else {
|
||||
for (;search != search_end; search++) {
|
||||
if (!search->has_costs()) {
|
||||
m_log << "FATAL ERROR: Costs must be delivered in order to calculate minimum costs" << std::endl;
|
||||
exit(-1);
|
||||
}
|
||||
if (search->costs() < min_costs) {
|
||||
min_cost_msg = &(*search);
|
||||
min_costs = search->costs();
|
||||
}
|
||||
}
|
||||
m_ip = *min_cost_msg;
|
||||
}
|
||||
}
|
||||
|
||||
} /* namespace fail */
|
||||
10
src/core/cpn/InjectionPointSteps.cc
Normal file
10
src/core/cpn/InjectionPointSteps.cc
Normal file
@ -0,0 +1,10 @@
|
||||
#include "InjectionPoint.hpp"
|
||||
|
||||
namespace fail {
|
||||
|
||||
void InjectionPointSteps::parseFromInjectionInstr(unsigned instr1, unsigned instr2) {
|
||||
// compute hops
|
||||
m_ip.set_injection_instr(instr2);
|
||||
}
|
||||
|
||||
} /* namespace fail */
|
||||
Reference in New Issue
Block a user