import-trace: alias-based (importer) registry
This change implements a generic registry in order to clean up import-trace's code - it's possible (and reasonable) to use the registry for pruners as well. Importer now extends AliasedRegisterable; all importers have been adapted to suit the interface/abstract methods. Each AliasedRegisterable should have at least one alias (the class' name is a sensible choice) but can have several. The first specified alias is the class' prime alias which can be used e.g. to list all registered objects. Change-Id: If6daa34edce35a3b0194e4ba67ed3b44b74a49b0
This commit is contained in:
16
src/core/util/AliasedRegisterable.hpp
Normal file
16
src/core/util/AliasedRegisterable.hpp
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
#ifndef __UTIL_ALIASEDREGISTERABLE_H__
|
||||||
|
#define __UTIL_ALIASEDREGISTERABLE_H__
|
||||||
|
|
||||||
|
#include <deque>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
namespace fail {
|
||||||
|
|
||||||
|
class AliasedRegisterable {
|
||||||
|
public:
|
||||||
|
virtual void getAliases(std::deque<std::string> *aliases) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
}; // end of namespace fail
|
||||||
|
|
||||||
|
#endif // __UTIL_ALIASEDREGISTERABLE_H__
|
||||||
68
src/core/util/AliasedRegistry.cc
Normal file
68
src/core/util/AliasedRegistry.cc
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
#include <iostream>
|
||||||
|
#include <deque>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include "util/AliasedRegistry.hpp"
|
||||||
|
#include "util/AliasedRegisterable.hpp"
|
||||||
|
|
||||||
|
namespace fail {
|
||||||
|
|
||||||
|
bool AliasedRegistry::add(AliasedRegisterable *obj) {
|
||||||
|
std::deque<std::string> aliases;
|
||||||
|
obj->getAliases(&aliases);
|
||||||
|
|
||||||
|
bool inserted = false;
|
||||||
|
for (std::deque<std::string>::iterator it = aliases.begin(); it != aliases.end(); ++it) {
|
||||||
|
if (m_registry.find(*it) == m_registry.end()) {
|
||||||
|
if (!inserted) {
|
||||||
|
m_primes[obj] = *it;
|
||||||
|
}
|
||||||
|
m_registry[*it] = obj;
|
||||||
|
inserted = true;
|
||||||
|
} else {
|
||||||
|
#ifndef __puma
|
||||||
|
std::cerr << "AliasedRegistry: alias '" << *it << "' already exists!" << std::endl;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return inserted;
|
||||||
|
}
|
||||||
|
|
||||||
|
AliasedRegisterable *AliasedRegistry::get(std::string key) {
|
||||||
|
std::map<std::string, AliasedRegisterable*>::iterator it = m_registry.find(key);
|
||||||
|
if (it != m_registry.end()) {
|
||||||
|
return it->second;
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AliasedRegistry::getPrimeAlias(AliasedRegisterable *obj, std::string& alias) {
|
||||||
|
std::map<AliasedRegisterable*, std::string>::iterator it = m_primes.find(obj);
|
||||||
|
if (it != m_primes.end()) {
|
||||||
|
alias = it->second;
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void AliasedRegistry::getPrimeAliases(std::deque<std::string>& aliases) {
|
||||||
|
std::map<AliasedRegisterable*, std::string>::iterator it = m_primes.begin();
|
||||||
|
for (;it != m_primes.end(); ++it) {
|
||||||
|
aliases.push_back(it->second);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string AliasedRegistry::getPrimeAliasesCSV(){
|
||||||
|
std::string csv = "";
|
||||||
|
std::deque<std::string> primes;
|
||||||
|
getPrimeAliases(primes);
|
||||||
|
for (std::deque<std::string>::iterator it = primes.begin(); it != primes.end(); ++it) {
|
||||||
|
csv += *it + ", ";
|
||||||
|
}
|
||||||
|
csv.resize(csv.size()-2);
|
||||||
|
return csv;
|
||||||
|
}
|
||||||
|
|
||||||
|
}; // end of namespace fail
|
||||||
43
src/core/util/AliasedRegistry.hpp
Normal file
43
src/core/util/AliasedRegistry.hpp
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
#ifndef __UTIL_ALIASEDREGISTRY_H__
|
||||||
|
#define __UTIL_ALIASEDREGISTRY_H__
|
||||||
|
|
||||||
|
#include "util/AliasedRegisterable.hpp"
|
||||||
|
#include <map>
|
||||||
|
|
||||||
|
namespace fail {
|
||||||
|
|
||||||
|
class AliasedRegistry {
|
||||||
|
private:
|
||||||
|
std::map<std::string, AliasedRegisterable*> m_registry;
|
||||||
|
std::map<AliasedRegisterable*, std::string> m_primes;
|
||||||
|
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* Register given AliasedRegisterable by it's aliases
|
||||||
|
*/
|
||||||
|
bool add(AliasedRegisterable* obj);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get an AliasedRegisterable by an arbitrary alias
|
||||||
|
*/
|
||||||
|
AliasedRegisterable *get(std::string alias);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the prime (i.e. first to be specified) alias for given object
|
||||||
|
*/
|
||||||
|
bool getPrimeAlias(AliasedRegisterable* target, std::string& alias);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get all registered prime aliases
|
||||||
|
*/
|
||||||
|
void getPrimeAliases(std::deque<std::string>& prime_aliases);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get prime aliases' names as CSV
|
||||||
|
*/
|
||||||
|
std::string getPrimeAliasesCSV();
|
||||||
|
};
|
||||||
|
|
||||||
|
}; // end of namespace fail
|
||||||
|
|
||||||
|
#endif // __UTIL_ALIASEDREGISTRY_H__
|
||||||
@ -29,6 +29,9 @@ set(SRCS
|
|||||||
SynchronizedQueue.hpp
|
SynchronizedQueue.hpp
|
||||||
WallclockTimer.cc
|
WallclockTimer.cc
|
||||||
WallclockTimer.hpp
|
WallclockTimer.hpp
|
||||||
|
AliasedRegistry.hpp
|
||||||
|
AliasedRegistry.cc
|
||||||
|
AliasedRegisterable.hpp
|
||||||
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@ -55,6 +55,10 @@ protected:
|
|||||||
virtual bool handle_mem_event(fail::simtime_t curtime, instruction_count_t instr,
|
virtual bool handle_mem_event(fail::simtime_t curtime, instruction_count_t instr,
|
||||||
Trace_Event &ev);
|
Trace_Event &ev);
|
||||||
virtual bool trace_end_reached();
|
virtual bool trace_end_reached();
|
||||||
|
|
||||||
|
void getAliases(std::deque<std::string> *aliases) {
|
||||||
|
aliases->push_back("AdvancedMemoryImporter");
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -71,6 +71,12 @@ public:
|
|||||||
virtual bool create_database();
|
virtual bool create_database();
|
||||||
virtual bool copy_to_database(fail::ProtoIStream &ps);
|
virtual bool copy_to_database(fail::ProtoIStream &ps);
|
||||||
virtual bool clear_database();
|
virtual bool clear_database();
|
||||||
|
|
||||||
|
void getAliases(std::deque<std::string> *aliases) {
|
||||||
|
aliases->push_back("ElfImporter");
|
||||||
|
aliases->push_back("ObjdumpImporter");
|
||||||
|
aliases->push_back("objdump");
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -20,6 +20,11 @@ protected:
|
|||||||
virtual bool add_trace_event(margin_info_t &begin, margin_info_t &end,
|
virtual bool add_trace_event(margin_info_t &begin, margin_info_t &end,
|
||||||
Trace_Event &event, bool is_fake = false);
|
Trace_Event &event, bool is_fake = false);
|
||||||
virtual bool trace_end_reached();
|
virtual bool trace_end_reached();
|
||||||
|
|
||||||
|
public:
|
||||||
|
void getAliases(std::deque<std::string> *aliases) {
|
||||||
|
aliases->push_back("FullTraceImporter");
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -11,8 +11,9 @@
|
|||||||
#include "util/Database.hpp"
|
#include "util/Database.hpp"
|
||||||
#include "util/MemoryMap.hpp"
|
#include "util/MemoryMap.hpp"
|
||||||
#include "comm/TracePlugin.pb.h"
|
#include "comm/TracePlugin.pb.h"
|
||||||
|
#include "util/AliasedRegisterable.hpp"
|
||||||
|
|
||||||
class Importer {
|
class Importer : public fail::AliasedRegisterable {
|
||||||
public:
|
public:
|
||||||
typedef unsigned instruction_count_t; //!< not big enough for some benchmarks
|
typedef unsigned instruction_count_t; //!< not big enough for some benchmarks
|
||||||
struct margin_info_t { instruction_count_t dyninstr; fail::guest_address_t ip; fail::simtime_t time; };
|
struct margin_info_t { instruction_count_t dyninstr; fail::guest_address_t ip; fail::simtime_t time; };
|
||||||
|
|||||||
@ -17,6 +17,11 @@ protected:
|
|||||||
/* ignore on purpose */
|
/* ignore on purpose */
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void getAliases(std::deque<std::string> *aliases) {
|
||||||
|
aliases->push_back("InstructionImporter");
|
||||||
|
aliases->push_back("code");
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -11,6 +11,13 @@ protected:
|
|||||||
Trace_Event &ev);
|
Trace_Event &ev);
|
||||||
virtual bool handle_mem_event(fail::simtime_t curtime, instruction_count_t instr,
|
virtual bool handle_mem_event(fail::simtime_t curtime, instruction_count_t instr,
|
||||||
Trace_Event &ev);
|
Trace_Event &ev);
|
||||||
|
public:
|
||||||
|
void getAliases(std::deque<std::string> *aliases) {
|
||||||
|
aliases->push_back("MemoryImporter");
|
||||||
|
aliases->push_back("BasicImporter");
|
||||||
|
aliases->push_back("memory");
|
||||||
|
aliases->push_back("mem");
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -35,6 +35,10 @@ protected:
|
|||||||
virtual void open_unused_ec_intervals() {
|
virtual void open_unused_ec_intervals() {
|
||||||
/* empty, Memory Map has a different meaning in this importer */
|
/* empty, Memory Map has a different meaning in this importer */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void getAliases(std::deque<std::string> *aliases) {
|
||||||
|
aliases->push_back("RandomJumpImporter");
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -44,6 +44,12 @@ protected:
|
|||||||
virtual void open_unused_ec_intervals() {
|
virtual void open_unused_ec_intervals() {
|
||||||
/* empty, Memory Map has a different meaning in this importer */
|
/* empty, Memory Map has a different meaning in this importer */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void getAliases(std::deque<std::string> *aliases) {
|
||||||
|
aliases->push_back("RegisterImporter");
|
||||||
|
aliases->push_back("regs");
|
||||||
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -8,6 +8,7 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include "MemoryImporter.hpp"
|
#include "MemoryImporter.hpp"
|
||||||
#include "FullTraceImporter.hpp"
|
#include "FullTraceImporter.hpp"
|
||||||
|
#include "util/AliasedRegistry.hpp"
|
||||||
|
|
||||||
#ifdef BUILD_LLVM_DISASSEMBLER
|
#ifdef BUILD_LLVM_DISASSEMBLER
|
||||||
#include "InstructionImporter.hpp"
|
#include "InstructionImporter.hpp"
|
||||||
@ -57,6 +58,28 @@ int main(int argc, char *argv[]) {
|
|||||||
ElfReader *elf_file = 0;
|
ElfReader *elf_file = 0;
|
||||||
MemoryMap *memorymap = 0;
|
MemoryMap *memorymap = 0;
|
||||||
|
|
||||||
|
AliasedRegistry registry;
|
||||||
|
Importer *importer;
|
||||||
|
|
||||||
|
MemoryImporter mem;
|
||||||
|
registry.add(&mem);
|
||||||
|
FullTraceImporter fti;
|
||||||
|
registry.add(&fti);
|
||||||
|
|
||||||
|
#ifdef BUILD_LLVM_DISASSEMBLER
|
||||||
|
RegisterImporter reg;
|
||||||
|
registry.add(®);
|
||||||
|
RandomJumpImporter rjump;
|
||||||
|
registry.add(&rjump);
|
||||||
|
AdvancedMemoryImporter adv;
|
||||||
|
registry.add(&adv);
|
||||||
|
ElfImporter elf;
|
||||||
|
registry.add(&elf);
|
||||||
|
InstructionImporter instr;
|
||||||
|
registry.add(&instr);
|
||||||
|
#endif
|
||||||
|
std::string importers = registry.getPrimeAliasesCSV();
|
||||||
|
|
||||||
// Manually fill the command line option parser
|
// Manually fill the command line option parser
|
||||||
CommandLine &cmd = CommandLine::Inst();
|
CommandLine &cmd = CommandLine::Inst();
|
||||||
for (int i = 1; i < argc; ++i)
|
for (int i = 1; i < argc; ++i)
|
||||||
@ -123,42 +146,24 @@ int main(int argc, char *argv[]) {
|
|||||||
exit(-1);
|
exit(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
Importer *importer;
|
// get the desired importer from the commandline; default to MemoryImporter
|
||||||
|
std::string imp("MemoryImporter");
|
||||||
if (cmd[IMPORTER]) {
|
if (cmd[IMPORTER]) {
|
||||||
std::string imp(cmd[IMPORTER].first()->arg);
|
imp = cmd[IMPORTER].first()->arg;
|
||||||
if (imp == "BasicImporter" || imp == "MemoryImporter" || imp == "memory" || imp == "mem") {
|
|
||||||
imp = "MemoryImporter";
|
|
||||||
importer = new MemoryImporter();
|
|
||||||
} else if (imp == "FullTraceImporter") {
|
|
||||||
importer = new FullTraceImporter();
|
|
||||||
#ifdef BUILD_LLVM_DISASSEMBLER
|
|
||||||
} else if (imp == "InstructionImporter" || imp == "code") {
|
|
||||||
imp = "InstructionImporter";
|
|
||||||
importer = new InstructionImporter();
|
|
||||||
|
|
||||||
} else if (imp == "RegisterImporter" || imp == "regs") {
|
|
||||||
imp = "RegisterImporter";
|
|
||||||
importer = new RegisterImporter();
|
|
||||||
|
|
||||||
} else if (imp == "RandomJumpImporter") {
|
|
||||||
importer = new RandomJumpImporter();
|
|
||||||
} else if (imp == "AdvancedMemoryImporter") {
|
|
||||||
importer = new AdvancedMemoryImporter();
|
|
||||||
} else if (imp == "ObjdumpImporter" || imp == "objdump" || imp == "ElfImporter") {
|
|
||||||
importer = new ElfImporter();
|
|
||||||
#endif
|
|
||||||
} else {
|
|
||||||
LOG << "Unknown import method: " << imp << endl;
|
|
||||||
exit(-1);
|
|
||||||
}
|
|
||||||
LOG << "Using " << imp << endl;
|
|
||||||
|
|
||||||
} else {
|
|
||||||
LOG << "Using MemoryImporter" << endl;
|
|
||||||
importer = new MemoryImporter();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// try and get the according importer object ; die on failure
|
||||||
|
if ((importer = (Importer *)registry.get(imp)) == 0) {
|
||||||
|
LOG << "Unknown import method: " << imp << endl;
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string prime;
|
||||||
|
if (registry.getPrimeAlias(importer, prime)) {
|
||||||
|
imp = prime;
|
||||||
|
}
|
||||||
|
LOG << "Using " << imp << endl;
|
||||||
|
|
||||||
if (importer && !(importer->cb_commandline_init())) {
|
if (importer && !(importer->cb_commandline_init())) {
|
||||||
std::cerr << "Cannot call importers command line initialization!" << std::endl;
|
std::cerr << "Cannot call importers command line initialization!" << std::endl;
|
||||||
exit(-1);
|
exit(-1);
|
||||||
|
|||||||
Reference in New Issue
Block a user