From 1ad99c96306fd883b13dd2873a0334fe934846df Mon Sep 17 00:00:00 2001 From: Horst Schirmeier Date: Thu, 29 Aug 2013 19:21:31 +0200 Subject: [PATCH 1/8] cmake: find MySQL client lib This change introduces a CMake-style FindMySQL.cmake properly looking for libmysqlclient_r with mysql_config. This also fixes linking on some machines. Change-Id: Ifdbfdc3c7440dead37a8b63aaa86732d636aa0e2 --- cmake/FindMySQL.cmake | 59 +++++++++++++++++++ .../dciao-kernelstructs/CMakeLists.txt | 5 +- .../ecos_kernel_test/CMakeLists.txt | 7 ++- src/experiments/kesorefs/CMakeLists.txt | 5 +- tools/import-trace/CMakeLists.txt | 5 +- tools/prune-trace/CMakeLists.txt | 5 +- 6 files changed, 79 insertions(+), 7 deletions(-) create mode 100644 cmake/FindMySQL.cmake diff --git a/cmake/FindMySQL.cmake b/cmake/FindMySQL.cmake new file mode 100644 index 00000000..a8edcd3a --- /dev/null +++ b/cmake/FindMySQL.cmake @@ -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) diff --git a/src/experiments/dciao-kernelstructs/CMakeLists.txt b/src/experiments/dciao-kernelstructs/CMakeLists.txt index a1834697..a14aacf7 100644 --- a/src/experiments/dciao-kernelstructs/CMakeLists.txt +++ b/src/experiments/dciao-kernelstructs/CMakeLists.txt @@ -21,6 +21,9 @@ find_package(Protobuf REQUIRED) include_directories(${PROTOBUF_INCLUDE_DIRS}) include_directories(${CMAKE_CURRENT_BINARY_DIR}) +find_package(MySQL REQUIRED) +include_directories(${MYSQL_INCLUDE_DIR}) + PROTOBUF_GENERATE_CPP(PROTO_SRCS PROTO_HDRS ${MY_PROTOS}) ## Build library @@ -30,6 +33,6 @@ target_link_libraries(fail-${EXPERIMENT_NAME} ${PROTOBUF_LIBRARY}) ## This is the example's campaign server distributing experiment parameters 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) diff --git a/src/experiments/ecos_kernel_test/CMakeLists.txt b/src/experiments/ecos_kernel_test/CMakeLists.txt index 883e2039..7546f9c6 100644 --- a/src/experiments/ecos_kernel_test/CMakeLists.txt +++ b/src/experiments/ecos_kernel_test/CMakeLists.txt @@ -22,14 +22,17 @@ find_package(Protobuf REQUIRED) include_directories(${PROTOBUF_INCLUDE_DIRS}) include_directories(${CMAKE_CURRENT_BINARY_DIR}) +find_package(MySQL REQUIRED) +include_directories(${MYSQL_INCLUDE_DIR}) + 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} -lmysqlclient_r) +target_link_libraries(fail-${EXPERIMENT_NAME} ${PROTOBUF_LIBRARY} ${MYSQL_LIBRARIES}) ## 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} -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) diff --git a/src/experiments/kesorefs/CMakeLists.txt b/src/experiments/kesorefs/CMakeLists.txt index d3dfb253..37298030 100644 --- a/src/experiments/kesorefs/CMakeLists.txt +++ b/src/experiments/kesorefs/CMakeLists.txt @@ -21,6 +21,9 @@ find_package(Protobuf REQUIRED) include_directories(${PROTOBUF_INCLUDE_DIRS}) include_directories(${CMAKE_CURRENT_BINARY_DIR}) +find_package(MySQL REQUIRED) +include_directories(${MYSQL_INCLUDE_DIR}) + PROTOBUF_GENERATE_CPP(PROTO_SRCS PROTO_HDRS ${MY_PROTOS}) ## Build library @@ -30,5 +33,5 @@ target_link_libraries(fail-${EXPERIMENT_NAME} ${PROTOBUF_LIBRARY}) ## This is the example's campaign server distributing experiment parameters 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) diff --git a/tools/import-trace/CMakeLists.txt b/tools/import-trace/CMakeLists.txt index 80fce373..561a9c9c 100644 --- a/tools/import-trace/CMakeLists.txt +++ b/tools/import-trace/CMakeLists.txt @@ -17,13 +17,14 @@ if (BUILD_LLVM_DISASSEMBLER) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${LLVM_CXX_FLAGS} -fexceptions") endif(BUILD_LLVM_DISASSEMBLER) - +find_package(MySQL REQUIRED) +include_directories(${MYSQL_INCLUDE_DIR}) add_executable(import-trace main.cc ${SRCS}) target_link_libraries(import-trace ${PROTOBUF_LIBRARY} - -lmysqlclient + ${MYSQL_LIBRARIES} fail-util fail-comm fail-sal) diff --git a/tools/prune-trace/CMakeLists.txt b/tools/prune-trace/CMakeLists.txt index 32328f6d..a79e3451 100644 --- a/tools/prune-trace/CMakeLists.txt +++ b/tools/prune-trace/CMakeLists.txt @@ -3,7 +3,10 @@ set(SRCS BasicPruner.cc ) +find_package(MySQL REQUIRED) +include_directories(${MYSQL_INCLUDE_DIR}) + ## This is the example's campaign server distributing experiment parameters 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) From 2108c8932f4247a5330308c342e82f125c44fb39 Mon Sep 17 00:00:00 2001 From: Horst Schirmeier Date: Fri, 30 Aug 2013 17:03:37 +0200 Subject: [PATCH 2/8] util: disassembler register/address mapping fix For def/use pruning, the linear address mapping of the x86 sub-registers (e.g., AX represents the lower 16 bits of EAX) must overlap. If it doesn't, e.g., AX and EAX are considered separate registers by def/use pruning, resulting in a failure to correlate an EAX def with a subsequent AX use. The only user of this mapping up to now, RegisterImporter, forced all register widths to 8 bits, thereby fortunately canceling out this problem. Nevertheless it makes no sense to continue encoding a constant width in these virtual addresses. Existing trace, fspgroup, fsppilot and result tables may be converted to the new encoding by using this query: UPDATE SET data_address = ((data_address >> 4) & ~0xf) | data_address & 0xf; Change-Id: I7a942b78c34f6140803a86af639eeedef3550f34 --- .../llvmdisassembler/LLVMtoFailTranslator.hpp | 21 ++++++++++++------- tools/import-trace/RegisterImporter.cc | 5 ++--- 2 files changed, 15 insertions(+), 11 deletions(-) diff --git a/src/core/util/llvmdisassembler/LLVMtoFailTranslator.hpp b/src/core/util/llvmdisassembler/LLVMtoFailTranslator.hpp index 4e9444c2..5849e12c 100644 --- a/src/core/util/llvmdisassembler/LLVMtoFailTranslator.hpp +++ b/src/core/util/llvmdisassembler/LLVMtoFailTranslator.hpp @@ -13,6 +13,12 @@ namespace fail { */ class LLVMtoFailTranslator { 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 { int id; regwidth_t width; @@ -20,18 +26,17 @@ public: byte_t offset; int toDataAddress() const { - // .. 5 4 | 7 6 5 4 | 3 2 1 0 - // | | - return (id << 8) | ((width/8) << 4) | (offset / 8); + // .. 5 4 | 3 2 1 0 + // | + return (id << 4) | (offset / 8); } + // does not recreate width or mask static reginfo_t fromDataAddress(int addr) { - int id = addr >> 8; - regwidth_t width = ((addr >> 4) & 0xf) * 8; - byte_t offset = (addr & 0xf) * 8; - return reginfo_t(id, width, offset); + int id = addr >> 4; + byte_t offset = (addr & 0xf) * 8; + return reginfo_t(id, 0, offset); } - 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) {}; }; diff --git a/tools/import-trace/RegisterImporter.cc b/tools/import-trace/RegisterImporter.cc index 6b44969e..5564a184 100644 --- a/tools/import-trace/RegisterImporter.cc +++ b/tools/import-trace/RegisterImporter.cc @@ -33,9 +33,8 @@ bool RegisterImporter::addRegisterTrace(simtime_t curtime, instruction_count_t i const Trace_Event &ev, const LLVMtoFailTranslator::reginfo_t &info, char access_type) { - LLVMtoFailTranslator::reginfo_t one_byte_window = info; - one_byte_window.width = 8; - address_t from = one_byte_window.toDataAddress(), to = one_byte_window.toDataAddress() + (info.width) / 8; + address_t from = info.toDataAddress(); + address_t to = from + info.width / 8; // Iterate over all accessed bytes for (address_t data_address = from; data_address < to; ++data_address) { From 89aff7df659f330d6443e501b95ee7fa90da6c23 Mon Sep 17 00:00:00 2001 From: Horst Schirmeier Date: Mon, 2 Sep 2013 12:07:27 +0200 Subject: [PATCH 3/8] util: Bochs/Fail register mapping fix CL and DL are 8 bits wide, not 255. Change-Id: Ic454215344d08ba2f8374db251792f82d106305b --- src/core/util/llvmdisassembler/LLVMtoFailBochs.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/core/util/llvmdisassembler/LLVMtoFailBochs.cpp b/src/core/util/llvmdisassembler/LLVMtoFailBochs.cpp index f1b47325..869bf064 100644 --- a/src/core/util/llvmdisassembler/LLVMtoFailBochs.cpp +++ b/src/core/util/llvmdisassembler/LLVMtoFailBochs.cpp @@ -19,12 +19,12 @@ LLVMtoFailBochs::LLVMtoFailBochs() { 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[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[46] = reginfo_t(RID_CCX); // ECX 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[48] = reginfo_t(RID_CDX); // EDX From 203ec6c5cc9d69daf0f3087925d2f31e4f7f5843 Mon Sep 17 00:00:00 2001 From: Horst Schirmeier Date: Tue, 9 Jul 2013 16:06:14 +0200 Subject: [PATCH 4/8] remove #ifndef __puma from code using LLVM Contemporary AspectC++ versions can deal with the LLVM headers very well, and #ifdef __puma stuff in Fail* headers results in unmaintainable #ifdef __puma blocks in other parts of Fail* (e.g., the trace importer). Make sure you're using a 64-bit ac++ when living in a 64-bit userland (the 32-bit version doesn't know about __int128), and be aware that AspectC++ r325 introduced a regression that has not been fixed yet. Change-Id: I5bb759b08995a74b020d44a2b40e9d7a6e18111c --- src/core/util/llvmdisassembler/LLVMDisassembler.cpp | 3 --- src/core/util/llvmdisassembler/LLVMDisassembler.hpp | 3 --- src/core/util/llvmdisassembler/LLVMtoFailBochs.cpp | 2 -- src/core/util/llvmdisassembler/LLVMtoFailGem5.cpp | 2 -- src/core/util/llvmdisassembler/LLVMtoFailTranslator.cpp | 2 -- src/core/util/llvmdisassembler/LLVMtoFailTranslator.hpp | 3 --- tools/import-trace/InstructionImporter.cc | 4 ---- tools/import-trace/InstructionImporter.hpp | 5 ----- tools/import-trace/RandomJumpImporter.cc | 4 ---- tools/import-trace/RandomJumpImporter.hpp | 5 ----- tools/import-trace/RegisterImporter.cc | 4 ---- tools/import-trace/RegisterImporter.hpp | 5 ----- 12 files changed, 42 deletions(-) diff --git a/src/core/util/llvmdisassembler/LLVMDisassembler.cpp b/src/core/util/llvmdisassembler/LLVMDisassembler.cpp index f1154e44..590e3b11 100644 --- a/src/core/util/llvmdisassembler/LLVMDisassembler.cpp +++ b/src/core/util/llvmdisassembler/LLVMDisassembler.cpp @@ -1,4 +1,3 @@ -#ifndef __puma #include "LLVMDisassembler.hpp" using namespace fail; @@ -147,5 +146,3 @@ void LLVMDisassembler::disassemble() } void LLVMDisassembler::StringRefMemoryObject::anchor() {} - -#endif diff --git a/src/core/util/llvmdisassembler/LLVMDisassembler.hpp b/src/core/util/llvmdisassembler/LLVMDisassembler.hpp index 7a0a4fe9..75535053 100644 --- a/src/core/util/llvmdisassembler/LLVMDisassembler.hpp +++ b/src/core/util/llvmdisassembler/LLVMDisassembler.hpp @@ -1,8 +1,6 @@ #ifndef __LLVMDISASSEMBLER_HPP__ #define __LLVMDISASSEMBLER_HPP__ -#ifndef __puma - #include #include #include @@ -137,5 +135,4 @@ public: } -#endif // puma #endif // __LLVMDISASSEMBLER_HPP__ diff --git a/src/core/util/llvmdisassembler/LLVMtoFailBochs.cpp b/src/core/util/llvmdisassembler/LLVMtoFailBochs.cpp index f1b47325..c7493bfe 100644 --- a/src/core/util/llvmdisassembler/LLVMtoFailBochs.cpp +++ b/src/core/util/llvmdisassembler/LLVMtoFailBochs.cpp @@ -4,7 +4,6 @@ using namespace fail; LLVMtoFailBochs::LLVMtoFailBochs() { -#ifndef __puma /* These magic numbers are taken from the llvm compiler (MC), they do not appear in any header. They hopefully will never change */ @@ -46,5 +45,4 @@ LLVMtoFailBochs::LLVMtoFailBochs() { 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[118] = reginfo_t(RID_CSP, 8, 0); // SPL -#endif } diff --git a/src/core/util/llvmdisassembler/LLVMtoFailGem5.cpp b/src/core/util/llvmdisassembler/LLVMtoFailGem5.cpp index bac70b29..e89a6419 100644 --- a/src/core/util/llvmdisassembler/LLVMtoFailGem5.cpp +++ b/src/core/util/llvmdisassembler/LLVMtoFailGem5.cpp @@ -4,7 +4,6 @@ using namespace fail; LLVMtoFailGem5::LLVMtoFailGem5() { -#ifndef __puma /* These magic numbers are taken from the machine descriptions of LLVM they (hopefully) will not change, since they are not exported via a header */ @@ -24,5 +23,4 @@ LLVMtoFailGem5::LLVMtoFailGem5() { llvm_to_fail_map[105] = reginfo_t(RI_SP); llvm_to_fail_map[40] = reginfo_t(RI_LR); llvm_to_fail_map[43] = reginfo_t(RI_IP); -#endif } diff --git a/src/core/util/llvmdisassembler/LLVMtoFailTranslator.cpp b/src/core/util/llvmdisassembler/LLVMtoFailTranslator.cpp index 0d10e1a2..82f88304 100644 --- a/src/core/util/llvmdisassembler/LLVMtoFailTranslator.cpp +++ b/src/core/util/llvmdisassembler/LLVMtoFailTranslator.cpp @@ -4,7 +4,6 @@ using namespace fail; const LLVMtoFailTranslator::reginfo_t & LLVMtoFailTranslator::getFailRegisterID(unsigned int regid) { -#ifndef __puma ltof_map_t::iterator it = llvm_to_fail_map.find(regid); if( it != llvm_to_fail_map.end() ) {// found return (*it).second; @@ -13,7 +12,6 @@ const LLVMtoFailTranslator::reginfo_t & LLVMtoFailTranslator::getFailRegisterID //exit(EXIT_FAILURE); return notfound; } -#endif } regdata_t LLVMtoFailTranslator::getRegisterContent(ConcreteCPU& cpu, const reginfo_t ®info){ diff --git a/src/core/util/llvmdisassembler/LLVMtoFailTranslator.hpp b/src/core/util/llvmdisassembler/LLVMtoFailTranslator.hpp index 4e9444c2..c6ae698f 100644 --- a/src/core/util/llvmdisassembler/LLVMtoFailTranslator.hpp +++ b/src/core/util/llvmdisassembler/LLVMtoFailTranslator.hpp @@ -39,11 +39,8 @@ protected: LLVMtoFailTranslator(){}; -#ifndef __puma typedef std::map ltof_map_t; ltof_map_t llvm_to_fail_map; -#endif - public: const reginfo_t & getFailRegisterID(unsigned int regid); diff --git a/tools/import-trace/InstructionImporter.cc b/tools/import-trace/InstructionImporter.cc index e5472f3e..a1e72f79 100644 --- a/tools/import-trace/InstructionImporter.cc +++ b/tools/import-trace/InstructionImporter.cc @@ -1,4 +1,3 @@ -#ifndef __puma #include #include #include "InstructionImporter.hpp" @@ -77,6 +76,3 @@ bool InstructionImporter::handle_ip_event(fail::simtime_t curtime, instruction_c return true; } - - -#endif // !__puma diff --git a/tools/import-trace/InstructionImporter.hpp b/tools/import-trace/InstructionImporter.hpp index a60f5f57..81b58436 100644 --- a/tools/import-trace/InstructionImporter.hpp +++ b/tools/import-trace/InstructionImporter.hpp @@ -3,16 +3,11 @@ #include "Importer.hpp" -#ifndef __puma #include "util/llvmdisassembler/LLVMDisassembler.hpp" -#endif - class InstructionImporter : public Importer { -#ifndef __puma llvm::OwningPtr binary; llvm::OwningPtr disas; -#endif public: virtual bool handle_ip_event(fail::simtime_t curtime, instruction_count_t instr, diff --git a/tools/import-trace/RandomJumpImporter.cc b/tools/import-trace/RandomJumpImporter.cc index b83f1851..857c0b28 100644 --- a/tools/import-trace/RandomJumpImporter.cc +++ b/tools/import-trace/RandomJumpImporter.cc @@ -1,4 +1,3 @@ -#ifndef __puma #include #include #include "util/Logger.hpp" @@ -129,6 +128,3 @@ bool RandomJumpImporter::handle_ip_event(fail::simtime_t curtime, instruction_co return true; } - - -#endif // !__puma diff --git a/tools/import-trace/RandomJumpImporter.hpp b/tools/import-trace/RandomJumpImporter.hpp index 088f58ca..e9e38575 100644 --- a/tools/import-trace/RandomJumpImporter.hpp +++ b/tools/import-trace/RandomJumpImporter.hpp @@ -5,16 +5,11 @@ #include "util/CommandLine.hpp" #include "Importer.hpp" -#ifndef __puma #include "util/llvmdisassembler/LLVMDisassembler.hpp" -#endif - class RandomJumpImporter : public Importer { -#ifndef __puma llvm::OwningPtr binary; llvm::OwningPtr disas; -#endif fail::CommandLine::option_handle FROM, TO; diff --git a/tools/import-trace/RegisterImporter.cc b/tools/import-trace/RegisterImporter.cc index 6b44969e..982c0d44 100644 --- a/tools/import-trace/RegisterImporter.cc +++ b/tools/import-trace/RegisterImporter.cc @@ -1,4 +1,3 @@ -#ifndef __puma #include #include #include "RegisterImporter.hpp" @@ -168,6 +167,3 @@ bool RegisterImporter::handle_ip_event(fail::simtime_t curtime, instruction_coun return true; } - - -#endif // !__puma diff --git a/tools/import-trace/RegisterImporter.hpp b/tools/import-trace/RegisterImporter.hpp index 94c51ead..5cfacd49 100644 --- a/tools/import-trace/RegisterImporter.hpp +++ b/tools/import-trace/RegisterImporter.hpp @@ -5,13 +5,10 @@ #include "util/CommandLine.hpp" #include "Importer.hpp" -#ifndef __puma #include "util/llvmdisassembler/LLVMDisassembler.hpp" -#endif class RegisterImporter : public Importer { -#ifndef __puma llvm::OwningPtr binary; llvm::OwningPtr disas; @@ -19,8 +16,6 @@ class RegisterImporter : public Importer { const Trace_Event &ev, const fail::LLVMtoFailTranslator::reginfo_t &info, char access_type); -#endif - fail::CommandLine::option_handle NO_GP, FLAGS, IP; bool do_gp, do_flags, do_ip; From 6d4dfeb913f0d3d0bb98195fd7db5ace02cd5553 Mon Sep 17 00:00:00 2001 From: Horst Schirmeier Date: Thu, 27 Jun 2013 17:25:43 +0200 Subject: [PATCH 5/8] shutdown cleanups revisited This change became necessary as we observed weird fail-client SIGSEGV crashes with both Bochs and Gem5 backends and different experiments. Some Fail* components are instantiated statically: the SimulatorController instance "simulator", containing the ListenerManager and the CoroutineManager, and the active ExperimentFlow subclass(es) (experiments/instantiate-experiment*.ah.in). The experiment(s) is registered as an active flow in the CoroutineManager at startup. As plugins (which are ExperimentFlows themselves) are often created on an experiment's stack, ExperimentFlows deregister themselves on destruction (e.g., when leaving the plugin variable's scope). The core problem is, that the creation and destruction order of statically instantiated objects depends on the link order; if the experiment is destroyed after the CoroutineManager, its automatic self-deregistering feature talks to the smoking ruins of the latter. This change removes all static instantiations of ExperimentFlow and replaces them with constructions on the heap. Additionally it makes sure that the CoroutineManager recognizes that a shutdown is in progress, and refrains from touching potentially already destroyed data structures when a (mistakenly globally instantiated) ExperimentFlow deregisters in this case. Change-Id: I8a7d42fb141222cd2cce6040ab1a01f9de61be24 --- src/core/efw/CoroutineManager.cc | 21 +++++++++++++------ src/core/efw/CoroutineManager.hpp | 10 ++++++++- src/core/efw/ExperimentFlow.hpp | 5 +++++ src/core/sal/SimulatorController.cc | 2 ++ .../ecos_kernel_test/instantiateExperiment.cc | 3 +-- .../instantiate-experiment-indirect.ah.in | 4 ++++ src/experiments/instantiate-experiment.ah.in | 8 +++++-- .../nanojpeg/instantiateExperiment.cc | 3 +-- .../rampage/instantiateExperiment.cc | 3 +-- 9 files changed, 44 insertions(+), 15 deletions(-) diff --git a/src/core/efw/CoroutineManager.cc b/src/core/efw/CoroutineManager.cc index 4dd35e4c..1b8be303 100644 --- a/src/core/efw/CoroutineManager.cc +++ b/src/core/efw/CoroutineManager.cc @@ -8,9 +8,9 @@ namespace fail { void CoroutineManager::m_invoke(void* pData) { - //std::cerr << "CORO m_invoke " << co_current() << std::endl; - // TODO: Log-Level? - reinterpret_cast(pData)->coroutine_entry(); + ExperimentFlow *flow = reinterpret_cast(pData); + flow->coroutine_entry(); + simulator.removeFlow(flow); //m_togglerstack.pop(); // FIXME: need to pop our caller co_exit(); // deletes the associated coroutine memory as well @@ -20,7 +20,12 @@ void CoroutineManager::m_invoke(void* pData) 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) { @@ -53,7 +58,9 @@ void CoroutineManager::remove(ExperimentFlow* flow) // find coroutine handle for this flow flowmap_t::iterator it = m_Flows.find(flow); 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; } corohandle_t coro = it->second; @@ -67,7 +74,9 @@ void CoroutineManager::remove(ExperimentFlow* flow) // delete coroutine (and handle the special case we're removing // ourselves) if (coro == co_current()) { - co_exit(); + if (!m_Terminated) { + co_exit(); + } } else { co_delete(coro); } diff --git a/src/core/efw/CoroutineManager.hpp b/src/core/efw/CoroutineManager.hpp index 13d9ce58..ec550f8e 100644 --- a/src/core/efw/CoroutineManager.hpp +++ b/src/core/efw/CoroutineManager.hpp @@ -29,10 +29,12 @@ private: std::stack m_togglerstack; //! manages the run-calls for each ExperimentFlow-object static void m_invoke(void* pData); + //! \c true if terminated explicitly using simulator.terminate() + bool m_Terminated; public: static const ExperimentFlow* SIM_FLOW; //!< the simulator coroutine flow - CoroutineManager() : m_simCoro(co_current()) { } + CoroutineManager() : m_simCoro(co_current()), m_Terminated(false) { } ~CoroutineManager(); /** * Creates a new coroutine for the specified experiment flow. @@ -63,6 +65,12 @@ public: * @return the current experiment flow. */ 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 diff --git a/src/core/efw/ExperimentFlow.hpp b/src/core/efw/ExperimentFlow.hpp index 6279491f..0166a2fe 100644 --- a/src/core/efw/ExperimentFlow.hpp +++ b/src/core/efw/ExperimentFlow.hpp @@ -13,6 +13,11 @@ namespace fail { class ExperimentFlow { public: ExperimentFlow() { } + virtual ~ExperimentFlow() + { + simulator.clearListeners(this); // remove residual events + simulator.removeFlow(this); + } /** * Defines the experiment flow. * @return \c true if the experiment was successful, \c false otherwise diff --git a/src/core/sal/SimulatorController.cc b/src/core/sal/SimulatorController.cc index 26ea73dd..be5d9864 100644 --- a/src/core/sal/SimulatorController.cc +++ b/src/core/sal/SimulatorController.cc @@ -217,6 +217,8 @@ void SimulatorController::terminate(int exCode) // 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; // TODO: (Non-)Verbose-Mode? Log-Level? + + m_Flows.setTerminated(); // we are about to terminate exit(exCode); } diff --git a/src/experiments/ecos_kernel_test/instantiateExperiment.cc b/src/experiments/ecos_kernel_test/instantiateExperiment.cc index 520be8a3..414a7172 100644 --- a/src/experiments/ecos_kernel_test/instantiateExperiment.cc +++ b/src/experiments/ecos_kernel_test/instantiateExperiment.cc @@ -1,8 +1,7 @@ #include "experiment.hpp" #include "sal/SALInst.hpp" -static EcosKernelTestExperiment experiment; void instantiateEcosKernelTestExperiment() { - fail::simulator.addFlow(&experiment); + fail::simulator.addFlow(new EcosKernelTestExperiment); } diff --git a/src/experiments/instantiate-experiment-indirect.ah.in b/src/experiments/instantiate-experiment-indirect.ah.in index d309617b..b3a72752 100644 --- a/src/experiments/instantiate-experiment-indirect.ah.in +++ b/src/experiments/instantiate-experiment-indirect.ah.in @@ -12,6 +12,10 @@ // You need to provide the implementation of this function in your experiment // directory: 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 { advice execution ("void fail::SimulatorController::initExperiments()") : after () { diff --git a/src/experiments/instantiate-experiment.ah.in b/src/experiments/instantiate-experiment.ah.in index 765d7214..5bf1ed32 100644 --- a/src/experiments/instantiate-experiment.ah.in +++ b/src/experiments/instantiate-experiment.ah.in @@ -9,10 +9,14 @@ #include "../experiments/@EXPERIMENT_NAME@/experiment.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 { - @EXPERIMENT_TYPE@ experiment; advice execution ("void fail::SimulatorController::initExperiments()") : after () { - fail::simulator.addFlow(&experiment); + fail::simulator.addFlow(new @EXPERIMENT_TYPE@); } }; diff --git a/src/experiments/nanojpeg/instantiateExperiment.cc b/src/experiments/nanojpeg/instantiateExperiment.cc index 98493577..84e8a80d 100644 --- a/src/experiments/nanojpeg/instantiateExperiment.cc +++ b/src/experiments/nanojpeg/instantiateExperiment.cc @@ -1,8 +1,7 @@ #include "experiment.hpp" #include "sal/SALInst.hpp" -static NanoJPEGExperiment experiment; void instantiateNanoJPEGExperiment() { - fail::simulator.addFlow(&experiment); + fail::simulator.addFlow(new NanoJPEGExperiment); } diff --git a/src/experiments/rampage/instantiateExperiment.cc b/src/experiments/rampage/instantiateExperiment.cc index ed51e4b8..b1efb310 100644 --- a/src/experiments/rampage/instantiateExperiment.cc +++ b/src/experiments/rampage/instantiateExperiment.cc @@ -1,8 +1,7 @@ #include "experiment.hpp" #include "sal/SALInst.hpp" -static RAMpageExperiment experiment; void instantiateRAMpageExperiment() { - fail::simulator.addFlow(&experiment); + fail::simulator.addFlow(new RAMpageExperiment); } From e4a5a7a5929ee43252590dd5bc835460eb21ba96 Mon Sep 17 00:00:00 2001 From: Horst Schirmeier Date: Sun, 8 Sep 2013 22:15:14 +0200 Subject: [PATCH 6/8] util: gzstream needs zlib This change is needed to build on Ubuntu 13.04. Change-Id: I683ed4427044264f58bc8f7c94cb5fbbff89cd95 --- src/core/util/CMakeLists.txt | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/core/util/CMakeLists.txt b/src/core/util/CMakeLists.txt index de9ed96d..77775dc0 100644 --- a/src/core/util/CMakeLists.txt +++ b/src/core/util/CMakeLists.txt @@ -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 ]") endif() +# libz required by gzstream +find_package(ZLIB REQUIRED) +include_directories(${ZLIB_INCLUDE_DIRS}) + # objdump required by Diassembler.cc set(THE_OBJDUMP "${ARCH_TOOL_PREFIX}objdump") @@ -61,7 +65,7 @@ mark_as_advanced(FAIL_OBJDUMP) add_library(fail-util ${SRCS}) 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) if (BUILD_LLVM_DISASSEMBLER) From 9cd40842d26b08893bcd89bb1cb63f17fa8d7b27 Mon Sep 17 00:00:00 2001 From: Horst Schirmeier Date: Sun, 8 Sep 2013 22:16:08 +0200 Subject: [PATCH 7/8] introduce convert-trace tool The input (taken on stdin) is a gem5.opt --debug-flags=MemoryAccess trace (--format gem5), or a dump-trace output (--format dump) for easy trace synthesis (for testing purposes). gem5 format: Currently imports physical, not virtual memory addresses. dump format: Currently ignores extended trace information. Change-Id: Ic26a996d6fb9ce4175c855fadcbcff9ac9263888 --- tools/CMakeLists.txt | 5 ++ tools/convert-trace/CMakeLists.txt | 10 +++ tools/convert-trace/DumpConverter.cc | 73 +++++++++++++++++++ tools/convert-trace/DumpConverter.hpp | 11 +++ tools/convert-trace/FormatConverter.hpp | 16 +++++ tools/convert-trace/Gem5Converter.cc | 93 +++++++++++++++++++++++++ tools/convert-trace/Gem5Converter.hpp | 11 +++ tools/convert-trace/main.cc | 65 +++++++++++++++++ tools/dump-trace/DumpTrace.cc | 2 +- 9 files changed, 285 insertions(+), 1 deletion(-) create mode 100644 tools/convert-trace/CMakeLists.txt create mode 100644 tools/convert-trace/DumpConverter.cc create mode 100644 tools/convert-trace/DumpConverter.hpp create mode 100644 tools/convert-trace/FormatConverter.hpp create mode 100644 tools/convert-trace/Gem5Converter.cc create mode 100644 tools/convert-trace/Gem5Converter.hpp create mode 100644 tools/convert-trace/main.cc diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt index ac2e2096..f11196d8 100644 --- a/tools/CMakeLists.txt +++ b/tools/CMakeLists.txt @@ -1,6 +1,7 @@ option(BUILD_DUMP_TRACE "Build the trace dump tool?" OFF) option(BUILD_IMPORT_TRACE "Build the trace import 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 ## @@ -18,3 +19,7 @@ endif(BUILD_PRUNE_TRACE) if(BUILD_DUMP_TRACE) add_subdirectory(dump-trace) endif(BUILD_DUMP_TRACE) + +if(BUILD_CONVERT_TRACE) + add_subdirectory(convert-trace) +endif(BUILD_CONVERT_TRACE) diff --git a/tools/convert-trace/CMakeLists.txt b/tools/convert-trace/CMakeLists.txt new file mode 100644 index 00000000..a226a7c3 --- /dev/null +++ b/tools/convert-trace/CMakeLists.txt @@ -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) diff --git a/tools/convert-trace/DumpConverter.cc b/tools/convert-trace/DumpConverter.cc new file mode 100644 index 00000000..75e59eb9 --- /dev/null +++ b/tools/convert-trace/DumpConverter.cc @@ -0,0 +1,73 @@ +#include +#include +#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; +} diff --git a/tools/convert-trace/DumpConverter.hpp b/tools/convert-trace/DumpConverter.hpp new file mode 100644 index 00000000..5648ea0d --- /dev/null +++ b/tools/convert-trace/DumpConverter.hpp @@ -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 diff --git a/tools/convert-trace/FormatConverter.hpp b/tools/convert-trace/FormatConverter.hpp new file mode 100644 index 00000000..58922e9d --- /dev/null +++ b/tools/convert-trace/FormatConverter.hpp @@ -0,0 +1,16 @@ +#ifndef __FORMATCONVERTER_HPP__ +#define __FORMATCONVERTER_HPP__ + +#include +#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 diff --git a/tools/convert-trace/Gem5Converter.cc b/tools/convert-trace/Gem5Converter.cc new file mode 100644 index 00000000..0a4e16f7 --- /dev/null +++ b/tools/convert-trace/Gem5Converter.cc @@ -0,0 +1,93 @@ +#include +#include +#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; +} diff --git a/tools/convert-trace/Gem5Converter.hpp b/tools/convert-trace/Gem5Converter.hpp new file mode 100644 index 00000000..9842a629 --- /dev/null +++ b/tools/convert-trace/Gem5Converter.hpp @@ -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 diff --git a/tools/convert-trace/main.cc b/tools/convert-trace/main.cc new file mode 100644 index 00000000..359d3806 --- /dev/null +++ b/tools/convert-trace/main.cc @@ -0,0 +1,65 @@ +#include +#include + +#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; + } +} diff --git a/tools/dump-trace/DumpTrace.cc b/tools/dump-trace/DumpTrace.cc index b99952af..d2799072 100644 --- a/tools/dump-trace/DumpTrace.cc +++ b/tools/dump-trace/DumpTrace.cc @@ -122,7 +122,7 @@ int main(int argc, char *argv[]) if (!stats_only) { cout << "MEM " << (ev.accesstype() == Trace_Event_AccessType_READ ? "R" : "W") << " " - << ev.memaddr() + << hex << ev.memaddr() << dec << " width " << ev.width() << hex << " IP " << ev.ip() << dec << " t=" << acctime From 11513ef78d63d65316936ce35ffc24e3bdaaa320 Mon Sep 17 00:00:00 2001 From: Horst Schirmeier Date: Mon, 2 Sep 2013 12:09:00 +0200 Subject: [PATCH 8/8] util: handle missing register mapping gracefully It's OK if we cannot map every register LLVM knows to a Fail register ID, but we need to explicitly skip these cases in the RegisterImporter. Change-Id: I2152f819fb94aa4de5720c5798b229b66988d382 --- .../util/llvmdisassembler/LLVMtoFailTranslator.cpp | 2 +- .../util/llvmdisassembler/LLVMtoFailTranslator.hpp | 8 +++++++- tools/import-trace/RegisterImporter.cc | 13 +++++++++++++ 3 files changed, 21 insertions(+), 2 deletions(-) diff --git a/src/core/util/llvmdisassembler/LLVMtoFailTranslator.cpp b/src/core/util/llvmdisassembler/LLVMtoFailTranslator.cpp index 0d10e1a2..f99f0070 100644 --- a/src/core/util/llvmdisassembler/LLVMtoFailTranslator.cpp +++ b/src/core/util/llvmdisassembler/LLVMtoFailTranslator.cpp @@ -9,7 +9,7 @@ const LLVMtoFailTranslator::reginfo_t & LLVMtoFailTranslator::getFailRegisterID if( it != llvm_to_fail_map.end() ) {// found return (*it).second; } 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); return notfound; } diff --git a/src/core/util/llvmdisassembler/LLVMtoFailTranslator.hpp b/src/core/util/llvmdisassembler/LLVMtoFailTranslator.hpp index 5849e12c..f64cf07a 100644 --- a/src/core/util/llvmdisassembler/LLVMtoFailTranslator.hpp +++ b/src/core/util/llvmdisassembler/LLVMtoFailTranslator.hpp @@ -51,6 +51,12 @@ protected: 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); regdata_t getRegisterContent(ConcreteCPU & cpu, const reginfo_t & reg); @@ -63,7 +69,7 @@ public: } int getFailRegisterId(unsigned int regid) { return this->getFailRegisterID(regid).id; }; -private: + reginfo_t notfound; }; diff --git a/tools/import-trace/RegisterImporter.cc b/tools/import-trace/RegisterImporter.cc index 5564a184..4d6605d6 100644 --- a/tools/import-trace/RegisterImporter.cc +++ b/tools/import-trace/RegisterImporter.cc @@ -130,6 +130,12 @@ bool RegisterImporter::handle_ip_event(fail::simtime_t curtime, instruction_coun for (std::vector::const_iterator it = opcode.reg_uses.begin(); it != opcode.reg_uses.end(); ++it) { const LLVMtoFailTranslator::reginfo_t &info = ltof.getFailRegisterID(*it); + if (&info == <of.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 gp, but ! flags -> ignore it*/ @@ -146,6 +152,13 @@ bool RegisterImporter::handle_ip_event(fail::simtime_t curtime, instruction_coun for (std::vector::const_iterator it = opcode.reg_defs.begin(); it != opcode.reg_defs.end(); ++it) { const LLVMtoFailTranslator::reginfo_t &info = ltof.getFailRegisterID(*it); + if (&info == <of.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 gp, but ! flags -> ignore it*/ if (info.id == RID_FLAGS && !do_flags)