Merge branch 'master' of ssh://vamos.informatik.uni-erlangen.de:29418/fail

This commit is contained in:
Björn Döbel
2013-09-10 11:54:29 +02:00
37 changed files with 451 additions and 81 deletions

59
cmake/FindMySQL.cmake Normal file
View File

@ -0,0 +1,59 @@
# Find the MySQL includes and client library
# This module defines
# MYSQL_INCLUDE_DIR, where to find mysql.h
# MYSQL_LIBRARIES, the libraries needed to use MySQL.
# MYSQL_FOUND, If false, do not try to use MySQL.
set(MYSQL_CONFIG_PREFER_PATH "$ENV{MYSQL_HOME}/bin" CACHE FILEPATH
"preferred path to MySQL (mysql_config)")
find_program(MYSQL_CONFIG mysql_config
${MYSQL_CONFIG_PREFER_PATH}
/usr/local/mysql/bin/
/usr/local/bin/
/usr/bin/
)
if(MYSQL_CONFIG)
message(STATUS "Using mysql_config: ${MYSQL_CONFIG}")
# set INCLUDE_DIR
exec_program(${MYSQL_CONFIG}
ARGS --include
OUTPUT_VARIABLE MYSQL_INCLUDE_DIR)
# set LIBRARY_DIR
exec_program(${MYSQL_CONFIG}
ARGS --libs_r
OUTPUT_VARIABLE MYSQL_LIBRARIES)
else(MYSQL_CONFIG)
# FIXME incomplete
find_path(MYSQL_INCLUDE_DIR mysql.h
/usr/local/include
/usr/local/include/mysql
/usr/local/mysql/include
/usr/local/mysql/include/mysql
/usr/include
/usr/include/mysql
#find_library(mysqlclient ...
# PATHS
# ${MYSQL_ADD_LIBRARY_PATH}
# /usr/lib/mysql
# /usr/local/lib
# /usr/local/lib/mysql
# /usr/local/mysql/lib
#)
)
endif(MYSQL_CONFIG)
set(MYSQL_INCLUDE_DIR ${MYSQL_INCLUDE_DIR} CACHE FILEPATH INTERNAL)
set(MYSQL_LIBRARIES ${MYSQL_LIBRARIES} CACHE FILEPATH INTERNAL)
if(MYSQL_INCLUDE_DIR AND MYSQL_LIBRARIES)
set(MYSQL_FOUND TRUE CACHE INTERNAL "MySQL found")
message(STATUS "Found MySQL: ${MYSQL_INCLUDE_DIR}, ${MYSQL_LIBRARIES}")
else(MYSQL_INCLUDE_DIR AND MYSQL_LIBRARIES)
set(MYSQL_FOUND FALSE CACHE INTERNAL "MySQL found")
message(STATUS "MySQL not found.")
endif(MYSQL_INCLUDE_DIR AND MYSQL_LIBRARIES)
mark_as_advanced(MYSQL_INCLUDE_DIR MYSQL_LIBRARIES)

View File

@ -8,9 +8,9 @@ namespace fail {
void CoroutineManager::m_invoke(void* pData) void CoroutineManager::m_invoke(void* pData)
{ {
//std::cerr << "CORO m_invoke " << co_current() << std::endl; ExperimentFlow *flow = reinterpret_cast<ExperimentFlow*>(pData);
// TODO: Log-Level? flow->coroutine_entry();
reinterpret_cast<ExperimentFlow*>(pData)->coroutine_entry(); simulator.removeFlow(flow);
//m_togglerstack.pop(); //m_togglerstack.pop();
// FIXME: need to pop our caller // FIXME: need to pop our caller
co_exit(); // deletes the associated coroutine memory as well co_exit(); // deletes the associated coroutine memory as well
@ -20,7 +20,12 @@ void CoroutineManager::m_invoke(void* pData)
while (1); // freeze. while (1); // freeze.
} }
CoroutineManager::~CoroutineManager() { } CoroutineManager::~CoroutineManager()
{
// Note that we do not destroy the associated coroutines; this causes
// problems when shutting down.
m_Flows.clear();
}
void CoroutineManager::toggle(ExperimentFlow* flow) void CoroutineManager::toggle(ExperimentFlow* flow)
{ {
@ -53,7 +58,9 @@ void CoroutineManager::remove(ExperimentFlow* flow)
// find coroutine handle for this flow // find coroutine handle for this flow
flowmap_t::iterator it = m_Flows.find(flow); flowmap_t::iterator it = m_Flows.find(flow);
if (it == m_Flows.end()) { if (it == m_Flows.end()) {
assert(false && "FATAL ERROR: Cannot remove flow"); // Not finding the flow to remove is not an error; especially when
// shutting down this is the common case, as ~CoroutineManager probably
// clears the flow list before the ExperimentFlow destructors run.
return; return;
} }
corohandle_t coro = it->second; corohandle_t coro = it->second;
@ -67,7 +74,9 @@ void CoroutineManager::remove(ExperimentFlow* flow)
// delete coroutine (and handle the special case we're removing // delete coroutine (and handle the special case we're removing
// ourselves) // ourselves)
if (coro == co_current()) { if (coro == co_current()) {
co_exit(); if (!m_Terminated) {
co_exit();
}
} else { } else {
co_delete(coro); co_delete(coro);
} }

View File

@ -29,10 +29,12 @@ private:
std::stack<corohandle_t> m_togglerstack; std::stack<corohandle_t> m_togglerstack;
//! manages the run-calls for each ExperimentFlow-object //! manages the run-calls for each ExperimentFlow-object
static void m_invoke(void* pData); static void m_invoke(void* pData);
//! \c true if terminated explicitly using simulator.terminate()
bool m_Terminated;
public: public:
static const ExperimentFlow* SIM_FLOW; //!< the simulator coroutine flow static const ExperimentFlow* SIM_FLOW; //!< the simulator coroutine flow
CoroutineManager() : m_simCoro(co_current()) { } CoroutineManager() : m_simCoro(co_current()), m_Terminated(false) { }
~CoroutineManager(); ~CoroutineManager();
/** /**
* Creates a new coroutine for the specified experiment flow. * Creates a new coroutine for the specified experiment flow.
@ -63,6 +65,12 @@ public:
* @return the current experiment flow. * @return the current experiment flow.
*/ */
ExperimentFlow* getCurrent(); ExperimentFlow* getCurrent();
/**
* Sets the termination flag. This should be called when Fail
* exists due to a call to \c ::exit() (used, e.g., in
* \c SimulatorController::terminate()). This cannot be undone.
*/
void setTerminated() { m_Terminated = true; }
}; };
} // end-of-namespace: fail } // end-of-namespace: fail

View File

@ -13,6 +13,11 @@ namespace fail {
class ExperimentFlow { class ExperimentFlow {
public: public:
ExperimentFlow() { } ExperimentFlow() { }
virtual ~ExperimentFlow()
{
simulator.clearListeners(this); // remove residual events
simulator.removeFlow(this);
}
/** /**
* Defines the experiment flow. * Defines the experiment flow.
* @return \c true if the experiment was successful, \c false otherwise * @return \c true if the experiment was successful, \c false otherwise

View File

@ -217,6 +217,8 @@ void SimulatorController::terminate(int exCode)
// Attention: This could cause problems, e.g., because of non-closed sockets // Attention: This could cause problems, e.g., because of non-closed sockets
std::cout << "[FAIL] Exit called by experiment with exit code: " << exCode << std::endl; std::cout << "[FAIL] Exit called by experiment with exit code: " << exCode << std::endl;
// TODO: (Non-)Verbose-Mode? Log-Level? // TODO: (Non-)Verbose-Mode? Log-Level?
m_Flows.setTerminated(); // we are about to terminate
exit(exCode); exit(exCode);
} }

View File

@ -48,6 +48,10 @@ if(${LIB_IBERTY} STREQUAL LIB_IBERTY-NOTFOUND)
message(FATAL_ERROR "libiberty not found. Try installing binutils-dev: [ sudo aptitude install binutils-dev ]") message(FATAL_ERROR "libiberty not found. Try installing binutils-dev: [ sudo aptitude install binutils-dev ]")
endif() endif()
# libz required by gzstream
find_package(ZLIB REQUIRED)
include_directories(${ZLIB_INCLUDE_DIRS})
# objdump required by Diassembler.cc # objdump required by Diassembler.cc
set(THE_OBJDUMP "${ARCH_TOOL_PREFIX}objdump") set(THE_OBJDUMP "${ARCH_TOOL_PREFIX}objdump")
@ -61,7 +65,7 @@ mark_as_advanced(FAIL_OBJDUMP)
add_library(fail-util ${SRCS}) add_library(fail-util ${SRCS})
add_dependencies(fail-util fail-comm) add_dependencies(fail-util fail-comm)
target_link_libraries(fail-util ${PROTOBUF_LIBRARY} ${Boost_LIBRARIES} ${LIB_IBERTY} ) target_link_libraries(fail-util ${PROTOBUF_LIBRARY} ${Boost_LIBRARIES} ${LIB_IBERTY} ${ZLIB_LIBRARIES})
option(BUILD_LLVM_DISASSEMBLER "Build the LLVM-based disassembler (LLVM 3.3 preferred, for 3.1 and 3.2 read doc/how-to-build.txt)" OFF) option(BUILD_LLVM_DISASSEMBLER "Build the LLVM-based disassembler (LLVM 3.3 preferred, for 3.1 and 3.2 read doc/how-to-build.txt)" OFF)
if (BUILD_LLVM_DISASSEMBLER) if (BUILD_LLVM_DISASSEMBLER)

View File

@ -1,4 +1,3 @@
#ifndef __puma
#include "LLVMDisassembler.hpp" #include "LLVMDisassembler.hpp"
using namespace fail; using namespace fail;
@ -147,5 +146,3 @@ void LLVMDisassembler::disassemble()
} }
void LLVMDisassembler::StringRefMemoryObject::anchor() {} void LLVMDisassembler::StringRefMemoryObject::anchor() {}
#endif

View File

@ -1,8 +1,6 @@
#ifndef __LLVMDISASSEMBLER_HPP__ #ifndef __LLVMDISASSEMBLER_HPP__
#define __LLVMDISASSEMBLER_HPP__ #define __LLVMDISASSEMBLER_HPP__
#ifndef __puma
#include <iostream> #include <iostream>
#include <vector> #include <vector>
#include <map> #include <map>
@ -137,5 +135,4 @@ public:
} }
#endif // puma
#endif // __LLVMDISASSEMBLER_HPP__ #endif // __LLVMDISASSEMBLER_HPP__

View File

@ -4,7 +4,6 @@
using namespace fail; using namespace fail;
LLVMtoFailBochs::LLVMtoFailBochs() { LLVMtoFailBochs::LLVMtoFailBochs() {
#ifndef __puma
/* These magic numbers are taken from the llvm compiler (MC), they /* These magic numbers are taken from the llvm compiler (MC), they
do not appear in any header. They hopefully will never do not appear in any header. They hopefully will never
change */ change */
@ -19,12 +18,12 @@ LLVMtoFailBochs::LLVMtoFailBochs() {
llvm_to_fail_map[45] = reginfo_t(RID_CBX, 32, 0); // EBX llvm_to_fail_map[45] = reginfo_t(RID_CBX, 32, 0); // EBX
llvm_to_fail_map[9] = reginfo_t(RID_CCX, 8, 8); // CH llvm_to_fail_map[9] = reginfo_t(RID_CCX, 8, 8); // CH
llvm_to_fail_map[10] = reginfo_t(RID_CCX, 0xff); // CL llvm_to_fail_map[10] = reginfo_t(RID_CCX, 8, 0); // CL
llvm_to_fail_map[28] = reginfo_t(RID_CCX, 16, 0); // CX llvm_to_fail_map[28] = reginfo_t(RID_CCX, 16, 0); // CX
llvm_to_fail_map[46] = reginfo_t(RID_CCX); // ECX llvm_to_fail_map[46] = reginfo_t(RID_CCX); // ECX
llvm_to_fail_map[29] = reginfo_t(RID_CDX, 8, 8); // DH llvm_to_fail_map[29] = reginfo_t(RID_CDX, 8, 8); // DH
llvm_to_fail_map[32] = reginfo_t(RID_CDX, 0xff); // DL llvm_to_fail_map[32] = reginfo_t(RID_CDX, 8, 0); // DL
llvm_to_fail_map[42] = reginfo_t(RID_CDX, 16, 0); // DX llvm_to_fail_map[42] = reginfo_t(RID_CDX, 16, 0); // DX
llvm_to_fail_map[48] = reginfo_t(RID_CDX); // EDX llvm_to_fail_map[48] = reginfo_t(RID_CDX); // EDX
@ -46,5 +45,4 @@ LLVMtoFailBochs::LLVMtoFailBochs() {
llvm_to_fail_map[54] = reginfo_t(RID_CSP); // ESP llvm_to_fail_map[54] = reginfo_t(RID_CSP); // ESP
llvm_to_fail_map[117] = reginfo_t(RID_CSP, 16, 0); // SP llvm_to_fail_map[117] = reginfo_t(RID_CSP, 16, 0); // SP
llvm_to_fail_map[118] = reginfo_t(RID_CSP, 8, 0); // SPL llvm_to_fail_map[118] = reginfo_t(RID_CSP, 8, 0); // SPL
#endif
} }

View File

@ -4,7 +4,6 @@
using namespace fail; using namespace fail;
LLVMtoFailGem5::LLVMtoFailGem5() { LLVMtoFailGem5::LLVMtoFailGem5() {
#ifndef __puma
/* These magic numbers are taken from the machine descriptions of /* These magic numbers are taken from the machine descriptions of
LLVM they (hopefully) will not change, since they are not exported LLVM they (hopefully) will not change, since they are not exported
via a header */ via a header */
@ -24,5 +23,4 @@ LLVMtoFailGem5::LLVMtoFailGem5() {
llvm_to_fail_map[105] = reginfo_t(RI_SP); llvm_to_fail_map[105] = reginfo_t(RI_SP);
llvm_to_fail_map[40] = reginfo_t(RI_LR); llvm_to_fail_map[40] = reginfo_t(RI_LR);
llvm_to_fail_map[43] = reginfo_t(RI_IP); llvm_to_fail_map[43] = reginfo_t(RI_IP);
#endif
} }

View File

@ -4,16 +4,14 @@
using namespace fail; using namespace fail;
const LLVMtoFailTranslator::reginfo_t & LLVMtoFailTranslator::getFailRegisterID(unsigned int regid) { const LLVMtoFailTranslator::reginfo_t & LLVMtoFailTranslator::getFailRegisterID(unsigned int regid) {
#ifndef __puma
ltof_map_t::iterator it = llvm_to_fail_map.find(regid); ltof_map_t::iterator it = llvm_to_fail_map.find(regid);
if( it != llvm_to_fail_map.end() ) {// found if( it != llvm_to_fail_map.end() ) {// found
return (*it).second; return (*it).second;
} else { // not found } else { // not found
std::cout << "Fail ID for LLVM Register id " << regid << " not found :(" << std::endl; std::cout << "Fail ID for LLVM Register id " << std::dec << regid << " not found :(" << std::endl;
//exit(EXIT_FAILURE); //exit(EXIT_FAILURE);
return notfound; return notfound;
} }
#endif
} }
regdata_t LLVMtoFailTranslator::getRegisterContent(ConcreteCPU& cpu, const reginfo_t &reginfo){ regdata_t LLVMtoFailTranslator::getRegisterContent(ConcreteCPU& cpu, const reginfo_t &reginfo){

View File

@ -13,6 +13,12 @@ namespace fail {
*/ */
class LLVMtoFailTranslator { class LLVMtoFailTranslator {
public: public:
/**
* Maps registers to/from linear addresses usable for def/use-pruning
* purposes and storage in the database. Takes care that the linear
* addresses of x86 subregisters (e.g., AX represents the lower 16 bits of
* EAX) overlap with their siblings.
*/
struct reginfo_t { struct reginfo_t {
int id; int id;
regwidth_t width; regwidth_t width;
@ -20,18 +26,17 @@ public:
byte_t offset; byte_t offset;
int toDataAddress() const { int toDataAddress() const {
// .. 5 4 | 7 6 5 4 | 3 2 1 0 // .. 5 4 | 3 2 1 0
// <reg> | <width> | <offset> // <reg> | <offset>
return (id << 8) | ((width/8) << 4) | (offset / 8); return (id << 4) | (offset / 8);
} }
// does not recreate width or mask
static reginfo_t fromDataAddress(int addr) { static reginfo_t fromDataAddress(int addr) {
int id = addr >> 8; int id = addr >> 4;
regwidth_t width = ((addr >> 4) & 0xf) * 8; byte_t offset = (addr & 0xf) * 8;
byte_t offset = (addr & 0xf) * 8; return reginfo_t(id, 0, offset);
return reginfo_t(id, width, offset);
} }
reginfo_t(int id=-1, regwidth_t width = 32, byte_t offs = 0) reginfo_t(int id=-1, regwidth_t width = 32, byte_t offs = 0)
: id(id), width(width), mask((regwidth_t)((((long long)1 << width) - 1) << offs)), offset(offs) {}; : id(id), width(width), mask((regwidth_t)((((long long)1 << width) - 1) << offs)), offset(offs) {};
}; };
@ -39,13 +44,16 @@ protected:
LLVMtoFailTranslator(){}; LLVMtoFailTranslator(){};
#ifndef __puma
typedef std::map<unsigned int, struct reginfo_t> ltof_map_t; typedef std::map<unsigned int, struct reginfo_t> ltof_map_t;
ltof_map_t llvm_to_fail_map; ltof_map_t llvm_to_fail_map;
#endif
public: public:
/**
* Translates a backend-specific register ID to a Fail register ID.
* @param regid A backend-specific register ID.
* @return A Fail* register ID, or LLVMtoFailTranslator::notfound if no
* mapping was found.
*/
const reginfo_t & getFailRegisterID(unsigned int regid); const reginfo_t & getFailRegisterID(unsigned int regid);
regdata_t getRegisterContent(ConcreteCPU & cpu, const reginfo_t & reg); regdata_t getRegisterContent(ConcreteCPU & cpu, const reginfo_t & reg);
@ -58,7 +66,7 @@ public:
} }
int getFailRegisterId(unsigned int regid) { return this->getFailRegisterID(regid).id; }; int getFailRegisterId(unsigned int regid) { return this->getFailRegisterID(regid).id; };
private:
reginfo_t notfound; reginfo_t notfound;
}; };

View File

@ -21,6 +21,9 @@ find_package(Protobuf REQUIRED)
include_directories(${PROTOBUF_INCLUDE_DIRS}) include_directories(${PROTOBUF_INCLUDE_DIRS})
include_directories(${CMAKE_CURRENT_BINARY_DIR}) include_directories(${CMAKE_CURRENT_BINARY_DIR})
find_package(MySQL REQUIRED)
include_directories(${MYSQL_INCLUDE_DIR})
PROTOBUF_GENERATE_CPP(PROTO_SRCS PROTO_HDRS ${MY_PROTOS}) PROTOBUF_GENERATE_CPP(PROTO_SRCS PROTO_HDRS ${MY_PROTOS})
## Build library ## Build library
@ -30,6 +33,6 @@ target_link_libraries(fail-${EXPERIMENT_NAME} ${PROTOBUF_LIBRARY})
## This is the example's campaign server distributing experiment parameters ## This is the example's campaign server distributing experiment parameters
add_executable(${EXPERIMENT_NAME}-server main.cc) add_executable(${EXPERIMENT_NAME}-server main.cc)
target_link_libraries(${EXPERIMENT_NAME}-server -Wl,--start-group fail-${EXPERIMENT_NAME} fail-sal fail-util fail-cpn fail-comm ${PROTOBUF_LIBRARY} ${Boost_THREAD_LIBRARY} -lmysqlclient -Wl,--end-group) target_link_libraries(${EXPERIMENT_NAME}-server -Wl,--start-group fail-${EXPERIMENT_NAME} fail-sal fail-util fail-cpn fail-comm ${PROTOBUF_LIBRARY} ${Boost_THREAD_LIBRARY} ${MYSQL_LIBRARIES} -Wl,--end-group)
install(TARGETS ${EXPERIMENT_NAME}-server RUNTIME DESTINATION bin) install(TARGETS ${EXPERIMENT_NAME}-server RUNTIME DESTINATION bin)

View File

@ -22,14 +22,17 @@ find_package(Protobuf REQUIRED)
include_directories(${PROTOBUF_INCLUDE_DIRS}) include_directories(${PROTOBUF_INCLUDE_DIRS})
include_directories(${CMAKE_CURRENT_BINARY_DIR}) include_directories(${CMAKE_CURRENT_BINARY_DIR})
find_package(MySQL REQUIRED)
include_directories(${MYSQL_INCLUDE_DIR})
PROTOBUF_GENERATE_CPP(PROTO_SRCS PROTO_HDRS ${MY_PROTOS}) PROTOBUF_GENERATE_CPP(PROTO_SRCS PROTO_HDRS ${MY_PROTOS})
## Build library ## Build library
add_library(fail-${EXPERIMENT_NAME} ${PROTO_SRCS} ${PROTO_HDRS} ${MY_CAMPAIGN_SRCS}) add_library(fail-${EXPERIMENT_NAME} ${PROTO_SRCS} ${PROTO_HDRS} ${MY_CAMPAIGN_SRCS})
add_dependencies(fail-${EXPERIMENT_NAME} fail-tracing fail-comm) add_dependencies(fail-${EXPERIMENT_NAME} fail-tracing fail-comm)
target_link_libraries(fail-${EXPERIMENT_NAME} ${PROTOBUF_LIBRARY} -lmysqlclient_r) target_link_libraries(fail-${EXPERIMENT_NAME} ${PROTOBUF_LIBRARY} ${MYSQL_LIBRARIES})
## This is the example's campaign server distributing experiment parameters ## This is the example's campaign server distributing experiment parameters
add_executable(${EXPERIMENT_NAME}-server main.cc) add_executable(${EXPERIMENT_NAME}-server main.cc)
target_link_libraries(${EXPERIMENT_NAME}-server fail-${EXPERIMENT_NAME} fail ${PROTOBUF_LIBRARY} ${Boost_THREAD_LIBRARY} -lmysqlclient_r) target_link_libraries(${EXPERIMENT_NAME}-server fail-${EXPERIMENT_NAME} fail ${PROTOBUF_LIBRARY} ${Boost_THREAD_LIBRARY} ${MYSQL_LIBRARIES})
install(TARGETS ${EXPERIMENT_NAME}-server RUNTIME DESTINATION bin) install(TARGETS ${EXPERIMENT_NAME}-server RUNTIME DESTINATION bin)

View File

@ -1,8 +1,7 @@
#include "experiment.hpp" #include "experiment.hpp"
#include "sal/SALInst.hpp" #include "sal/SALInst.hpp"
static EcosKernelTestExperiment experiment;
void instantiateEcosKernelTestExperiment() void instantiateEcosKernelTestExperiment()
{ {
fail::simulator.addFlow(&experiment); fail::simulator.addFlow(new EcosKernelTestExperiment);
} }

View File

@ -12,6 +12,10 @@
// You need to provide the implementation of this function in your experiment // You need to provide the implementation of this function in your experiment
// directory: // directory:
void instantiate@EXPERIMENT_TYPE@(); void instantiate@EXPERIMENT_TYPE@();
// The experiment needs to be instantiated dynamically (on the stack, or the
// heap), as the ExperimentFlow destructor deregisters from the
// CoroutineManager which may not exist anymore if the global
// construction/destruction order is inappropriate.
aspect @EXPERIMENT_TYPE@ExperimentHook { aspect @EXPERIMENT_TYPE@ExperimentHook {
advice execution ("void fail::SimulatorController::initExperiments()") : after () { advice execution ("void fail::SimulatorController::initExperiments()") : after () {

View File

@ -9,10 +9,14 @@
#include "../experiments/@EXPERIMENT_NAME@/experiment.hpp" #include "../experiments/@EXPERIMENT_NAME@/experiment.hpp"
#include "sal/SALInst.hpp" #include "sal/SALInst.hpp"
// The experiment needs to be instantiated dynamically (on the stack, or the
// heap), as the ExperimentFlow destructor deregisters from the
// CoroutineManager which may not exist anymore if the global
// construction/destruction order is inappropriate.
aspect @EXPERIMENT_TYPE@ExperimentHook { aspect @EXPERIMENT_TYPE@ExperimentHook {
@EXPERIMENT_TYPE@ experiment;
advice execution ("void fail::SimulatorController::initExperiments()") : after () { advice execution ("void fail::SimulatorController::initExperiments()") : after () {
fail::simulator.addFlow(&experiment); fail::simulator.addFlow(new @EXPERIMENT_TYPE@);
} }
}; };

View File

@ -21,6 +21,9 @@ find_package(Protobuf REQUIRED)
include_directories(${PROTOBUF_INCLUDE_DIRS}) include_directories(${PROTOBUF_INCLUDE_DIRS})
include_directories(${CMAKE_CURRENT_BINARY_DIR}) include_directories(${CMAKE_CURRENT_BINARY_DIR})
find_package(MySQL REQUIRED)
include_directories(${MYSQL_INCLUDE_DIR})
PROTOBUF_GENERATE_CPP(PROTO_SRCS PROTO_HDRS ${MY_PROTOS}) PROTOBUF_GENERATE_CPP(PROTO_SRCS PROTO_HDRS ${MY_PROTOS})
## Build library ## Build library
@ -30,5 +33,5 @@ target_link_libraries(fail-${EXPERIMENT_NAME} ${PROTOBUF_LIBRARY})
## This is the example's campaign server distributing experiment parameters ## This is the example's campaign server distributing experiment parameters
add_executable(${EXPERIMENT_NAME}-server main.cc) add_executable(${EXPERIMENT_NAME}-server main.cc)
target_link_libraries(${EXPERIMENT_NAME}-server -Wl,--start-group fail-${EXPERIMENT_NAME} fail-sal fail-util fail-cpn fail-comm ${PROTOBUF_LIBRARY} ${Boost_THREAD_LIBRARY} -lmysqlclient -Wl,--end-group) target_link_libraries(${EXPERIMENT_NAME}-server -Wl,--start-group fail-${EXPERIMENT_NAME} fail-sal fail-util fail-cpn fail-comm ${PROTOBUF_LIBRARY} ${Boost_THREAD_LIBRARY} ${MYSQL_LIBRARIES} -Wl,--end-group)
install(TARGETS ${EXPERIMENT_NAME}-server RUNTIME DESTINATION bin) install(TARGETS ${EXPERIMENT_NAME}-server RUNTIME DESTINATION bin)

View File

@ -1,8 +1,7 @@
#include "experiment.hpp" #include "experiment.hpp"
#include "sal/SALInst.hpp" #include "sal/SALInst.hpp"
static NanoJPEGExperiment experiment;
void instantiateNanoJPEGExperiment() void instantiateNanoJPEGExperiment()
{ {
fail::simulator.addFlow(&experiment); fail::simulator.addFlow(new NanoJPEGExperiment);
} }

View File

@ -1,8 +1,7 @@
#include "experiment.hpp" #include "experiment.hpp"
#include "sal/SALInst.hpp" #include "sal/SALInst.hpp"
static RAMpageExperiment experiment;
void instantiateRAMpageExperiment() void instantiateRAMpageExperiment()
{ {
fail::simulator.addFlow(&experiment); fail::simulator.addFlow(new RAMpageExperiment);
} }

View File

@ -1,6 +1,7 @@
option(BUILD_DUMP_TRACE "Build the trace dump tool?" OFF) option(BUILD_DUMP_TRACE "Build the trace dump tool?" OFF)
option(BUILD_IMPORT_TRACE "Build the trace import tool?" OFF) option(BUILD_IMPORT_TRACE "Build the trace import tool?" OFF)
option(BUILD_PRUNE_TRACE "Build the trace prune tool?" OFF) option(BUILD_PRUNE_TRACE "Build the trace prune tool?" OFF)
option(BUILD_CONVERT_TRACE "Build the trace converter tool?" OFF)
### Setup search paths for headers ## ### Setup search paths for headers ##
@ -18,3 +19,7 @@ endif(BUILD_PRUNE_TRACE)
if(BUILD_DUMP_TRACE) if(BUILD_DUMP_TRACE)
add_subdirectory(dump-trace) add_subdirectory(dump-trace)
endif(BUILD_DUMP_TRACE) endif(BUILD_DUMP_TRACE)
if(BUILD_CONVERT_TRACE)
add_subdirectory(convert-trace)
endif(BUILD_CONVERT_TRACE)

View File

@ -0,0 +1,10 @@
set(SRCS
main.cc
Gem5Converter.cc
DumpConverter.cc
)
add_executable(convert-trace ${SRCS})
target_link_libraries(convert-trace fail-util fail-comm)
install(TARGETS convert-trace RUNTIME DESTINATION bin)

View File

@ -0,0 +1,73 @@
#include <sstream>
#include <string>
#include "util/Logger.hpp"
#include "comm/TracePlugin.pb.h"
#include "DumpConverter.hpp"
using namespace fail;
using std::stringstream;
using std::endl;
using std::hex;
using std::dec;
static Logger LOG("DumpConverter", true);
// TODO: convert extended trace information, too
bool DumpConverter::convert()
{
char buf[2048], dummy[1024];
int64_t prev_cycle = 0, cycle;
while (m_input.getline(buf, sizeof(buf))) {
Trace_Event ev;
// IP 1035c9 t=0
// MEM R 123abc width 4 IP 1035c9 t=1
// MEM W 123abc width 4 IP 1035c9 t=1
std::stringstream ss(buf);
std::string ev_type;
ss >> ev_type;
if (ev_type == "MEM") {
std::string accesstype;
uint64_t data_address;
uint32_t data_width;
ss >> accesstype >> hex >> data_address >> dummy >> dec >> data_width >> ev_type;
if (!ss) {
LOG << "input mismatch (1), input = " << buf << endl;
continue;
}
ev.set_memaddr(data_address);
ev.set_width(data_width);
ev.set_accesstype(accesstype == "R" ? ev.READ : ev.WRITE);
}
assert(ev_type == "IP");
uint64_t instr_address;
ss >> hex >> instr_address >> dummy;
if (!ss || dummy[0] != 't' || dummy[1] != '=') {
LOG << "input mismatch (2), input = " << buf << endl;
continue;
}
ev.set_ip(instr_address);
ss.clear();
ss.str(dummy + 2);
ss >> dec >> cycle;
if (!ss) {
LOG << "input mismatch (3), input = " << buf << endl;
continue;
}
if (cycle - prev_cycle > 0) {
ev.set_time_delta(cycle - prev_cycle);
prev_cycle = cycle;
} else if (cycle - prev_cycle < 0) {
LOG << "ignoring time discontinuity " << dec << prev_cycle << " -> " << cycle << endl;
prev_cycle = cycle;
}
m_ps.writeMessage(&ev);
}
return true;
}

View File

@ -0,0 +1,11 @@
#ifndef __DUMPCONVERTER_HPP__
#define __DUMPCONVERTER_HPP__
#include "FormatConverter.hpp"
class DumpConverter : public FormatConverter {
public:
DumpConverter(std::istream& input, fail::ProtoOStream& ps) : FormatConverter(input, ps) {}
bool convert();
};
#endif

View File

@ -0,0 +1,16 @@
#ifndef __FORMATCONVERTER_HPP__
#define __FORMATCONVERTER_HPP__
#include <istream>
#include "util/ProtoStream.hpp"
class FormatConverter {
public:
FormatConverter(std::istream& input, fail::ProtoOStream& ps) : m_input(input), m_ps(ps) {}
virtual bool convert() = 0;
protected:
std::istream& m_input;
fail::ProtoOStream& m_ps;
};
#endif

View File

@ -0,0 +1,93 @@
#include <sstream>
#include <string>
#include "util/Logger.hpp"
#include "comm/TracePlugin.pb.h"
#include "Gem5Converter.hpp"
using namespace fail;
using std::stringstream;
using std::endl;
using std::hex;
using std::dec;
static Logger LOG("Gem5Converter", true);
bool Gem5Converter::convert()
{
char buf[2048], dummy[2048];
int64_t prev_cycle = 0, cycle;
uint64_t cur_ip = 0;
bool ifetch_seen = false;
while (m_input.getline(buf, sizeof(buf))) {
Trace_Event ev;
// reset ifetch_seen in case we're getting multiple concatenated gem5 traces
if (strstr(buf, "http://gem5.org")) {
ifetch_seen = false;
continue;
}
if (!strstr(buf, "system.physmem") || strstr(buf, "access wrote")) {
continue;
}
// 5000: system.physmem: access wrote 4 bytes to address f7ee8
// 5000: system.physmem: Write of size 4 on address 0xf7ee8 data 0x61190
// 6000: system.physmem: IFetch of size 4 on address 0xd58 data 0xe59f000c
// 6000: system.physmem: Read of size 4 on address 0xd6c data 0x8e2c
// 161000: system.physmem: 00000000 4c 69 6e 75 78 00 00 00 00 00 00 00 00 00 00 00 Linux
std::stringstream ss(buf);
std::string access_type;
unsigned access_width;
uint64_t access_address;
ss >> dec >> cycle >> dummy >> dummy >> access_type
>> dummy >> dummy >> dec >> access_width
>> dummy >> dummy >> hex >> access_address;
if (!ss) {
if (ifetch_seen && !access_type.c_str()[0] == '0') {
LOG << "input mismatch, input = " << buf << endl;
}
continue;
}
if (cycle - prev_cycle > 0) {
ev.set_time_delta(cycle - prev_cycle);
prev_cycle = cycle;
} else if (cycle - prev_cycle < 0) {
LOG << "ignoring time discontinuity " << dec << prev_cycle << " -> " << cycle << endl;
prev_cycle = cycle;
}
if (access_type == "IFetch") {
ifetch_seen = true;
cur_ip = access_address;
ev.set_ip(cur_ip);
//LOG << "ip = " << hex << cur_ip << endl;
} else {
bool is_read;
if (access_type == "Read") {
is_read = true;
} else if (access_type == "Write") {
is_read = false;
} else if (access_type.c_str()[0] == '0') {
continue;
} else {
LOG << "input mismatch, input = " << buf << endl;
continue;
}
if (!ifetch_seen) {
// skip all accesses before the first ifetch
continue;
}
ev.set_ip(cur_ip);
ev.set_memaddr(access_address);
ev.set_width(access_width);
ev.set_accesstype(is_read ? ev.READ : ev.WRITE);
//cout << "ip = " << hex << cur_ip << " mem " << access_address << " " << access_width << " " << (is_read ? 'R' : 'W') << endl;
}
m_ps.writeMessage(&ev);
}
return true;
}

View File

@ -0,0 +1,11 @@
#ifndef __GEM5CONVERTER_HPP__
#define __GEM5CONVERTER_HPP__
#include "FormatConverter.hpp"
class Gem5Converter : public FormatConverter {
public:
Gem5Converter(std::istream& input, fail::ProtoOStream& ps) : FormatConverter(input, ps) {}
bool convert();
};
#endif

View File

@ -0,0 +1,65 @@
#include <fstream>
#include <string>
#include "FormatConverter.hpp"
#include "Gem5Converter.hpp"
#include "DumpConverter.hpp"
#include "util/CommandLine.hpp"
#include "util/gzstream/gzstream.h"
#include "util/Logger.hpp"
using namespace fail;
using std::cin;
using std::endl;
static Logger LOG("convert-trace", true);
int main(int argc, char *argv[]) {
CommandLine &cmd = CommandLine::Inst();
cmd.addOption("", "", Arg::None, "usage: convert-trace -f dump|gem5 -t tracefile.tc");
CommandLine::option_handle HELP =
cmd.addOption("h", "help", Arg::None, "-h/--help \tPrint usage and exit");
CommandLine::option_handle FORMAT =
cmd.addOption("f", "format", Arg::Required, "-f/--format FORMAT \tInput format (dump|gem5)");
CommandLine::option_handle OUTFILE =
cmd.addOption("t", "trace", Arg::Required, "-t/--trace FILE \tOutput file");
for (int i = 1; i < argc; ++i) {
cmd.add_args(argv[i]);
}
if (!cmd.parse()) {
LOG << "Error parsing arguments." << endl;
return 1;
}
if (cmd[HELP] || !cmd[OUTFILE] || !cmd[FORMAT] || cmd.parser()->nonOptionsCount() != 0) {
cmd.printUsage();
if (cmd[HELP]) {
exit(0);
} else {
exit(1);
}
}
std::string format = cmd[FORMAT].first()->arg;
std::string trace_file = cmd[OUTFILE].first()->arg;
ogzstream gz_stream(trace_file.c_str());
std::ostream *os = &gz_stream;
ProtoOStream ps(os);
FormatConverter *converter;
if (format == "gem5") {
converter = new Gem5Converter(cin, ps);
} else if (format == "dump") {
converter = new DumpConverter(cin, ps);
} else {
LOG << "unknown input format '" << format << "'" << endl;
return 1;
}
if (!converter->convert()) {
LOG << "converter failed" << endl;
return 1;
}
}

View File

@ -122,7 +122,7 @@ int main(int argc, char *argv[])
if (!stats_only) { if (!stats_only) {
cout << "MEM " cout << "MEM "
<< (ev.accesstype() == Trace_Event_AccessType_READ ? "R" : "W") << " " << (ev.accesstype() == Trace_Event_AccessType_READ ? "R" : "W") << " "
<< ev.memaddr() << hex << ev.memaddr()
<< dec << " width " << ev.width() << dec << " width " << ev.width()
<< hex << " IP " << ev.ip() << hex << " IP " << ev.ip()
<< dec << " t=" << acctime << dec << " t=" << acctime

View File

@ -17,13 +17,14 @@ if (BUILD_LLVM_DISASSEMBLER)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${LLVM_CXX_FLAGS} -fexceptions") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${LLVM_CXX_FLAGS} -fexceptions")
endif(BUILD_LLVM_DISASSEMBLER) endif(BUILD_LLVM_DISASSEMBLER)
find_package(MySQL REQUIRED)
include_directories(${MYSQL_INCLUDE_DIR})
add_executable(import-trace main.cc ${SRCS}) add_executable(import-trace main.cc ${SRCS})
target_link_libraries(import-trace target_link_libraries(import-trace
${PROTOBUF_LIBRARY} ${PROTOBUF_LIBRARY}
-lmysqlclient ${MYSQL_LIBRARIES}
fail-util fail-util
fail-comm fail-comm
fail-sal) fail-sal)

View File

@ -1,4 +1,3 @@
#ifndef __puma
#include <sstream> #include <sstream>
#include <iostream> #include <iostream>
#include "InstructionImporter.hpp" #include "InstructionImporter.hpp"
@ -77,6 +76,3 @@ bool InstructionImporter::handle_ip_event(fail::simtime_t curtime, instruction_c
return true; return true;
} }
#endif // !__puma

View File

@ -3,16 +3,11 @@
#include "Importer.hpp" #include "Importer.hpp"
#ifndef __puma
#include "util/llvmdisassembler/LLVMDisassembler.hpp" #include "util/llvmdisassembler/LLVMDisassembler.hpp"
#endif
class InstructionImporter : public Importer { class InstructionImporter : public Importer {
#ifndef __puma
llvm::OwningPtr<llvm::object::Binary> binary; llvm::OwningPtr<llvm::object::Binary> binary;
llvm::OwningPtr<fail::LLVMDisassembler> disas; llvm::OwningPtr<fail::LLVMDisassembler> disas;
#endif
public: public:
virtual bool handle_ip_event(fail::simtime_t curtime, instruction_count_t instr, virtual bool handle_ip_event(fail::simtime_t curtime, instruction_count_t instr,

View File

@ -1,4 +1,3 @@
#ifndef __puma
#include <sstream> #include <sstream>
#include <iostream> #include <iostream>
#include "util/Logger.hpp" #include "util/Logger.hpp"
@ -129,6 +128,3 @@ bool RandomJumpImporter::handle_ip_event(fail::simtime_t curtime, instruction_co
return true; return true;
} }
#endif // !__puma

View File

@ -5,16 +5,11 @@
#include "util/CommandLine.hpp" #include "util/CommandLine.hpp"
#include "Importer.hpp" #include "Importer.hpp"
#ifndef __puma
#include "util/llvmdisassembler/LLVMDisassembler.hpp" #include "util/llvmdisassembler/LLVMDisassembler.hpp"
#endif
class RandomJumpImporter : public Importer { class RandomJumpImporter : public Importer {
#ifndef __puma
llvm::OwningPtr<llvm::object::Binary> binary; llvm::OwningPtr<llvm::object::Binary> binary;
llvm::OwningPtr<fail::LLVMDisassembler> disas; llvm::OwningPtr<fail::LLVMDisassembler> disas;
#endif
fail::CommandLine::option_handle FROM, TO; fail::CommandLine::option_handle FROM, TO;

View File

@ -1,4 +1,3 @@
#ifndef __puma
#include <sstream> #include <sstream>
#include <iostream> #include <iostream>
#include "RegisterImporter.hpp" #include "RegisterImporter.hpp"
@ -33,9 +32,8 @@ bool RegisterImporter::addRegisterTrace(simtime_t curtime, instruction_count_t i
const Trace_Event &ev, const Trace_Event &ev,
const LLVMtoFailTranslator::reginfo_t &info, const LLVMtoFailTranslator::reginfo_t &info,
char access_type) { char access_type) {
LLVMtoFailTranslator::reginfo_t one_byte_window = info; address_t from = info.toDataAddress();
one_byte_window.width = 8; address_t to = from + info.width / 8;
address_t from = one_byte_window.toDataAddress(), to = one_byte_window.toDataAddress() + (info.width) / 8;
// Iterate over all accessed bytes // Iterate over all accessed bytes
for (address_t data_address = from; data_address < to; ++data_address) { for (address_t data_address = from; data_address < to; ++data_address) {
@ -131,6 +129,12 @@ bool RegisterImporter::handle_ip_event(fail::simtime_t curtime, instruction_coun
for (std::vector<LLVMDisassembler::register_t>::const_iterator it = opcode.reg_uses.begin(); for (std::vector<LLVMDisassembler::register_t>::const_iterator it = opcode.reg_uses.begin();
it != opcode.reg_uses.end(); ++it) { it != opcode.reg_uses.end(); ++it) {
const LLVMtoFailTranslator::reginfo_t &info = ltof.getFailRegisterID(*it); const LLVMtoFailTranslator::reginfo_t &info = ltof.getFailRegisterID(*it);
if (&info == &ltof.notfound) {
LOG << "Could not find a mapping for LLVM input register #" << std::dec << *it
<< " at IP " << std::hex << ev.ip()
<< ", skipping" << std::endl;
continue;
}
/* if not tracing flags, but flags register -> ignore it /* if not tracing flags, but flags register -> ignore it
if not tracing gp, but ! flags -> ignore it*/ if not tracing gp, but ! flags -> ignore it*/
@ -147,6 +151,13 @@ bool RegisterImporter::handle_ip_event(fail::simtime_t curtime, instruction_coun
for (std::vector<LLVMDisassembler::register_t>::const_iterator it = opcode.reg_defs.begin(); for (std::vector<LLVMDisassembler::register_t>::const_iterator it = opcode.reg_defs.begin();
it != opcode.reg_defs.end(); ++it) { it != opcode.reg_defs.end(); ++it) {
const LLVMtoFailTranslator::reginfo_t &info = ltof.getFailRegisterID(*it); const LLVMtoFailTranslator::reginfo_t &info = ltof.getFailRegisterID(*it);
if (&info == &ltof.notfound) {
LOG << "Could not find a mapping for LLVM output register #" << std::dec << *it
<< " at IP " << std::hex << ev.ip()
<< ", skipping" << std::endl;
continue;
}
/* if not tracing flags, but flags register -> ignore it /* if not tracing flags, but flags register -> ignore it
if not tracing gp, but ! flags -> ignore it*/ if not tracing gp, but ! flags -> ignore it*/
if (info.id == RID_FLAGS && !do_flags) if (info.id == RID_FLAGS && !do_flags)
@ -168,6 +179,3 @@ bool RegisterImporter::handle_ip_event(fail::simtime_t curtime, instruction_coun
return true; return true;
} }
#endif // !__puma

View File

@ -5,13 +5,10 @@
#include "util/CommandLine.hpp" #include "util/CommandLine.hpp"
#include "Importer.hpp" #include "Importer.hpp"
#ifndef __puma
#include "util/llvmdisassembler/LLVMDisassembler.hpp" #include "util/llvmdisassembler/LLVMDisassembler.hpp"
#endif
class RegisterImporter : public Importer { class RegisterImporter : public Importer {
#ifndef __puma
llvm::OwningPtr<llvm::object::Binary> binary; llvm::OwningPtr<llvm::object::Binary> binary;
llvm::OwningPtr<fail::LLVMDisassembler> disas; llvm::OwningPtr<fail::LLVMDisassembler> disas;
@ -19,8 +16,6 @@ class RegisterImporter : public Importer {
const Trace_Event &ev, const Trace_Event &ev,
const fail::LLVMtoFailTranslator::reginfo_t &info, const fail::LLVMtoFailTranslator::reginfo_t &info,
char access_type); char access_type);
#endif
fail::CommandLine::option_handle NO_GP, FLAGS, IP; fail::CommandLine::option_handle NO_GP, FLAGS, IP;
bool do_gp, do_flags, do_ip; bool do_gp, do_flags, do_ip;

View File

@ -3,7 +3,10 @@ set(SRCS
BasicPruner.cc BasicPruner.cc
) )
find_package(MySQL REQUIRED)
include_directories(${MYSQL_INCLUDE_DIR})
## This is the example's campaign server distributing experiment parameters ## This is the example's campaign server distributing experiment parameters
add_executable(prune-trace main.cc ${SRCS}) add_executable(prune-trace main.cc ${SRCS})
target_link_libraries(prune-trace -lmysqlclient fail-util) target_link_libraries(prune-trace ${MYSQL_LIBRARIES} fail-util)
install(TARGETS prune-trace RUNTIME DESTINATION bin) install(TARGETS prune-trace RUNTIME DESTINATION bin)