diff --git a/src/core/comm/TracePlugin.proto b/src/core/comm/TracePlugin.proto index 99222eb9..9e10bc05 100644 --- a/src/core/comm/TracePlugin.proto +++ b/src/core/comm/TracePlugin.proto @@ -25,6 +25,7 @@ message Trace_Event { // and for target backends capable of timing-accurate execution optional int64 time_delta = 6; optional uint64 memaddr = 2; + optional uint32 memtype = 7; optional uint32 width = 3; enum AccessType { READ = 1; diff --git a/src/core/sal/Event.hpp b/src/core/sal/Event.hpp index 5e9f1ae2..bf3eed4c 100644 --- a/src/core/sal/Event.hpp +++ b/src/core/sal/Event.hpp @@ -15,7 +15,7 @@ namespace fail { /** * \class BaseEvent - * This is the base class for all event types. It encapsulates the information + * This is the base class for all event types. It encapsulates the information * about an event reported by the simulator backend. */ class BaseEvent { @@ -99,15 +99,20 @@ class MemAccessEvent : public BaseEvent { address_t m_TriggerIP; //! Memory access type at m_TriggerAddr. access_type_t m_AccessType; + //! Specific memory type in which this access occured. + memory_type_t m_MemType; + //! The data that was accessed in this event. + uint64_t m_Data; public: /** * Creates a new \c MemAccessEvent using default initialization values, i.e. * \c setTriggerAddress(ANY_ADDR), \c setTriggerWidth(0), \c setTriggerAccessType(MEM_UNKNOWN), - * \c setTriggerInstructionPointer(ANY_ADDR) and setTriggerCPU(NULL). + * \c setTriggerInstructionPointer(ANY_ADDR), setMemType(MEMTYPE_RAM), and setTriggerCPU(NULL). */ MemAccessEvent() : m_TriggerAddr(ANY_ADDR), m_TriggerWidth(0), - m_TriggerIP(ANY_ADDR), m_AccessType(MEM_UNKNOWN) { } + m_TriggerIP(ANY_ADDR), m_AccessType(MEM_UNKNOWN), + m_MemType(MEMTYPE_RAM), m_Data(0){ } /** * Creates a new \c MemAccessEvent and initializes the provided values. * @param triggerAddr actual address that triggered the event @@ -117,9 +122,9 @@ class MemAccessEvent : public BaseEvent { * @param cpu the CPU that triggered the event */ MemAccessEvent(address_t triggerAddr, size_t width, address_t triggerIP, access_type_t type, - ConcreteCPU* cpu = NULL) + ConcreteCPU* cpu = NULL, memory_type_t memtype=MEMTYPE_RAM, uint64_t data=0) : BaseEvent(cpu), m_TriggerAddr(triggerAddr), m_TriggerWidth(width), - m_TriggerIP(triggerIP), m_AccessType(type) { } + m_TriggerIP(triggerIP), m_AccessType(type), m_MemType(memtype), m_Data(data){ } /** * Returns the specific memory address that actually triggered the event. * @return the triggering address @@ -131,6 +136,28 @@ class MemAccessEvent : public BaseEvent { * @param addr the new triggering address */ void setTriggerAddress(address_t addr) { m_TriggerAddr = addr; } + /** + * Returns the type of memory which actually triggered the event. + * @return A memory_type_t which corresponds to the memory which triggered the event. + */ + memory_type_t getMemoryType() const { return m_MemType; } + /** + * Set the specific memory type which triggered the event. + * Should not be used by experiment code. + * @param type the new memory type. + */ + void setMemoryType(memory_type_t type) { m_MemType = type; } + /** + * Returns the data at the memory location that was accessed if it is available. + * @return The value of the accessed memory location . + */ + uint64_t getAccessedData() const { return m_Data; } + /** + * Set the data, which was accessed during the memory event. + * Should not be used by experiment code. + * @param data The data to be saved. + */ + void setAccessedData(uint64_t data) { m_Data = data; } /** * Returns the specific number of bytes read or written at \c getTriggerAddress(). * @return the width of the memory access diff --git a/src/core/sal/Listener.cc b/src/core/sal/Listener.cc index 3c110986..e4a4e69a 100644 --- a/src/core/sal/Listener.cc +++ b/src/core/sal/Listener.cc @@ -52,8 +52,10 @@ bool MemAccessListener::isMatching(const MemAccessEvent* pEv) const if (!(m_WatchType & pEv->getTriggerAccessType())) { return false; } else if (m_WatchAddr != ANY_ADDR - && (m_WatchAddr >= pEv->getTriggerAddress() + pEv->getTriggerWidth() - || m_WatchAddr + m_WatchWidth <= pEv->getTriggerAddress())) { + && (m_WatchAddr >= pEv->getTriggerAddress() + pEv->getTriggerWidth() + || m_WatchAddr + m_WatchWidth <= pEv->getTriggerAddress())) { + return false; + } else if (m_WatchMemType != ANY_MEMORY && m_WatchMemType != pEv->getMemoryType()) { return false; } else if (m_CPU != NULL && m_CPU != pEv->getTriggerCPU()) { return false; diff --git a/src/core/sal/Listener.hpp b/src/core/sal/Listener.hpp index 4a061c15..d11b5fae 100644 --- a/src/core/sal/Listener.hpp +++ b/src/core/sal/Listener.hpp @@ -315,6 +315,8 @@ class MemAccessListener : public BaseListener { protected: //! Specific physical guest system address to watch, or ANY_ADDR. address_t m_WatchAddr; + //! Specific memory type to watch (e.g. Tag memory), or ANY_MEMORY. + memory_type_t m_WatchMemType; //! Width of the memory area being watched (# bytes). size_t m_WatchWidth; /** @@ -326,15 +328,15 @@ class MemAccessListener : public BaseListener { WP_CTOR_SCOPE: MemAccessListener(MemAccessEvent::access_type_t type = MemAccessEvent::MEM_READWRITE, ConcreteCPU* cpu = NULL) - : BaseListener(cpu), m_WatchAddr(ANY_ADDR), m_WatchWidth(1), m_WatchType(type) { } - MemAccessListener(address_t addr, - MemAccessEvent::access_type_t type = MemAccessEvent::MEM_READWRITE, + : BaseListener(cpu), m_WatchAddr(ANY_ADDR), m_WatchMemType(ANY_MEMORY), m_WatchWidth(1), m_WatchType(type), m_Data() { } + MemAccessListener(address_t addr, memory_type_t memtype = ANY_MEMORY, + MemAccessEvent::access_type_t type = MemAccessEvent::MEM_READWRITE, ConcreteCPU* cpu = NULL) - : BaseListener(cpu), m_WatchAddr(addr), m_WatchWidth(1), m_WatchType(type) { } - MemAccessListener(const ElfSymbol &symbol, - MemAccessEvent::access_type_t type = MemAccessEvent::MEM_READWRITE, + : BaseListener(cpu), m_WatchAddr(addr), m_WatchMemType(memtype), m_WatchWidth(1), m_WatchType(type), m_Data() { } + MemAccessListener(const ElfSymbol &symbol, memory_type_t memtype = ANY_MEMORY, + MemAccessEvent::access_type_t type = MemAccessEvent::MEM_READWRITE, ConcreteCPU* cpu = NULL) - : BaseListener(cpu), m_WatchAddr(symbol.getAddress()), m_WatchWidth(symbol.getSize()), m_WatchType(type) { } + : BaseListener(cpu), m_WatchAddr(symbol.getAddress()), m_WatchMemType(memtype), m_WatchWidth(symbol.getSize()), m_WatchType(type) , m_Data() { } public: /** * Returns the physical memory address to be observed. @@ -344,6 +346,14 @@ class MemAccessListener : public BaseListener { * Sets the physical memory address to be observed. (Wildcard: ANY_ADDR) */ void setWatchAddress(address_t addr) { m_WatchAddr = addr; } + /** + * Returns the memory type to be observed. + */ + memory_type_t getWatchMemoryType() const { return m_WatchMemType; } + /** + * Sets the memory type to be observed. (Wildcard: ANY_MEMORY) + */ + void setWatchMemoryType(memory_type_t type) { m_WatchMemType = type; } /** * Returns the width of the memory area being watched. */ @@ -370,6 +380,33 @@ class MemAccessListener : public BaseListener { * listener. Should not be used by experiment code. */ void setTriggerAddress(address_t addr) { m_Data.setTriggerAddress(addr); } + /** + * Returns the type of memory which actually triggered the event. + * @return A memory_type_t which corresponds to the memory which triggered the event. + */ + memory_type_t getTriggerMemoryType() const { return m_Data.getMemoryType(); } + /** + * Set the specific memory type which triggered the event. + * Should not be used by experiment code. + * @param type the new memory type. + */ + void setTriggerMemoryType(memory_type_t type) { m_Data.setMemoryType(type); } + /** + * Returns the data at the memory location that was accessed if it is available. + * @return A uint64_t which contains at most 8 bytes of the accessed data. + */ + uint64_t getAccessedData() const { return m_Data.getAccessedData(); } + /** + * Set the data, which was accessed during the memory event. + * This data is copied into this class. + * Should not be used by experiment code. + * @param type the new memory type. + */ + void setAccessedData(uint64_t data) { m_Data.setAccessedData(data); } + /** + * Returns the specific number of bytes read or written at \c getTriggerAddress(). + * @return the width of the memory access + */ /** * Returns the width (in bytes) of the memory access that triggered this * listener. @@ -425,8 +462,8 @@ class MemReadListener : public MemAccessListener { WPREAD_CTOR_SCOPE: MemReadListener(ConcreteCPU* cpu = NULL) : MemAccessListener(MemAccessEvent::MEM_READ, cpu) { } - MemReadListener(address_t addr, ConcreteCPU* cpu = NULL) - : MemAccessListener(addr, MemAccessEvent::MEM_READ, cpu) { } + MemReadListener(address_t addr, memory_type_t type = ANY_MEMORY, ConcreteCPU* cpu = NULL) + : MemAccessListener(addr, type, MemAccessEvent::MEM_READ, cpu) { } }; #ifdef CONFIG_EVENT_MEMWRITE @@ -442,8 +479,8 @@ class MemWriteListener : public MemAccessListener { WPWRITE_CTOR_SCOPE: MemWriteListener(ConcreteCPU* cpu = NULL) : MemAccessListener(MemAccessEvent::MEM_WRITE, cpu) { } - MemWriteListener(address_t addr, ConcreteCPU* cpu = NULL) - : MemAccessListener(addr, MemAccessEvent::MEM_WRITE, cpu) { } + MemWriteListener(address_t addr, memory_type_t type = ANY_MEMORY, ConcreteCPU* cpu = NULL) + : MemAccessListener(addr, type, MemAccessEvent::MEM_WRITE, cpu) { } }; #if defined CONFIG_EVENT_INTERRUPT || defined CONFIG_EVENT_TRAP diff --git a/src/core/sal/SALConfig.cc b/src/core/sal/SALConfig.cc index 5e72af34..371d4a47 100644 --- a/src/core/sal/SALConfig.cc +++ b/src/core/sal/SALConfig.cc @@ -9,6 +9,7 @@ namespace fail { defined BUILD_PANDA const address_t ADDR_INV = static_cast (0); const address_t ANY_ADDR = static_cast (-1); +const memory_type_t ANY_MEMORY = static_cast (-1); const unsigned ANY_INSTR = static_cast (-1); const unsigned ANY_TRAP = static_cast (-1); const unsigned ANY_INTERRUPT = static_cast (-1); diff --git a/src/core/sal/SALConfig.hpp b/src/core/sal/SALConfig.hpp index dced8cd8..7a6ead5d 100644 --- a/src/core/sal/SALConfig.hpp +++ b/src/core/sal/SALConfig.hpp @@ -33,12 +33,22 @@ typedef uint64_t simtime_t; //! backend-specific notion of time difference typedef int64_t simtime_diff_t; +typedef enum { + MEMTYPE_UNKNOWN = 0x0, //!< Somehow, we do not know + MEMTYPE_RAM = 0x1, //!< Access to volatile memory + MEMTYPE_FLASH = 0x2, //!< Access to flash memory + MEMTYPE_TAGS = 0x3, //!< Access to tag-bits (see SAIL) + MEMTYPE_EEPROM = 0x4 //!< Access to EEPROM (see AVR) +} memory_type_t; //! memory type (RAM, FLASH, etc...) + // Note: The following flags are defined in SALConfig.cc. //! invalid address flag (e.g. for memory address ptrs) extern const address_t ADDR_INV; //! address wildcard (e.g. for breakpoint listeners) extern const address_t ANY_ADDR; +//! memory type wildcard (e.g. for memory access listener) +extern const memory_type_t ANY_MEMORY; //! instruction wildcard (e.g. for jump listeners) extern const unsigned ANY_INSTR; //! trap wildcard diff --git a/src/core/sal/SimulatorController.cc b/src/core/sal/SimulatorController.cc index 2ea73bf4..5f193ecc 100644 --- a/src/core/sal/SimulatorController.cc +++ b/src/core/sal/SimulatorController.cc @@ -3,6 +3,7 @@ #include "Event.hpp" #include "Listener.hpp" #include "util/CommandLine.hpp" +#include "Memory.hpp" namespace fail { @@ -136,15 +137,16 @@ void SimulatorController::onBreakpoint(ConcreteCPU* cpu, address_t instrPtr, add m_LstList.triggerActiveListeners(); } -void SimulatorController::onMemoryAccess(ConcreteCPU* cpu, address_t addr, size_t len, - bool is_write, address_t instrPtr) +void SimulatorController::onMemoryAccess(ConcreteCPU* cpu, address_t addr, size_t len, + bool is_write, address_t instrPtr, memory_type_t type) { MemAccessEvent::access_type_t accesstype = is_write ? MemAccessEvent::MEM_WRITE : MemAccessEvent::MEM_READ; - MemAccessEvent tmp(addr, len, instrPtr, accesstype, cpu); + MemAccessEvent tmp(addr, len, instrPtr, accesstype, cpu, type); ListenerManager::iterator it = m_LstList.begin(); + while (it != m_LstList.end()) { // check for active listeners BaseListener* pev = *it; MemAccessListener* ev = dynamic_cast(pev); @@ -159,6 +161,18 @@ void SimulatorController::onMemoryAccess(ConcreteCPU* cpu, address_t addr, size_ ev->setTriggerAccessType(accesstype); ev->setTriggerCPU(cpu); it = m_LstList.makeActive(it); + + // Read Memory with help of Memory Manager + ev->setTriggerMemoryType(type); + if (type == MEMTYPE_RAM) { + uint64_t data = 0; + MemoryManager &mm = getMemoryManager(type); + char max_len = len > sizeof(data) ? sizeof(data) : len; + if (mm.isMapped(addr) && mm.isMapped(addr + len - 1)) { + mm.getBytes(addr, max_len, &data); + ev->setAccessedData(data); + } + } } m_LstList.triggerActiveListeners(); } @@ -276,7 +290,7 @@ BaseListener* SimulatorController::addListenerAndResume(BaseListener* li) 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; + m_log << "[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 diff --git a/src/core/sal/SimulatorController.hpp b/src/core/sal/SimulatorController.hpp index 7abb5ad7..8ed8273a 100644 --- a/src/core/sal/SimulatorController.hpp +++ b/src/core/sal/SimulatorController.hpp @@ -41,21 +41,20 @@ class SimulatorController { ListenerManager m_LstList; //!< storage where listeners are being buffered std::map m_Experiments; //!< registered experiments, one is chosen on startup CoroutineManager m_Flows; //!< managed experiment flows - MemoryManager *m_Mem; //!< access to memory pool + std::map m_Mems; //!< access to memory pool(s) std::vector m_CPUs; //!< list of CPUs in the target system friend class ListenerManager; //!< "outsources" the listener management std::string m_argv0; //!< Invocation name of simulator process public: SimulatorController() : m_log("SimulatorController", false), - m_isInitialized(false), - m_Mem(nullptr) + m_isInitialized(false) { /* blank */ } SimulatorController(MemoryManager* mem) : m_log("SimulatorController", false), - m_isInitialized(false), - m_Mem(mem) - { /* blank */ } + m_isInitialized(false) { + m_Mems[MEMTYPE_RAM] = mem; // The RAM memory manager is the default + } virtual ~SimulatorController() { } /** * @brief Initialization function each implementation needs to call on @@ -95,11 +94,14 @@ class SimulatorController { * @param len the length of the accessed memory * @param is_write \c true if memory is written, \c false if read * @param instrPtr the address of the instruction causing the memory + * @param type The type of memory that was accessed. + * @param data The data which is stored at the memory location which was accessed. At most 8 bytes are supported, passed in the form of a concatenated 64 bit integer. * access * * FIXME: should instrPtr be part of this interface? */ - void onMemoryAccess(ConcreteCPU* cpu, address_t addr, size_t len, bool is_write, address_t instrPtr); + void onMemoryAccess(ConcreteCPU* cpu, address_t addr, size_t len, bool is_write, address_t instrPtr, + memory_type_t type=MEMTYPE_RAM); /** * Interrupt handler. * @param cpu the CPU that caused the interrupt @@ -174,13 +176,19 @@ class SimulatorController { * Returns the (constant) initialized memory manager. * @return a reference to the memory manager */ - MemoryManager& getMemoryManager() { return *m_Mem; } - const MemoryManager& getMemoryManager() const { return *m_Mem; } + MemoryManager& getMemoryManager(memory_type_t type=MEMTYPE_RAM) { + return *m_Mems.at(type); + } + const MemoryManager& getMemoryManager(memory_type_t type=MEMTYPE_RAM) const { + return *m_Mems.at(type); + } /** * Sets the memory manager. * @param pMem a new concrete memory manager */ - void setMemoryManager(MemoryManager* pMem) { m_Mem = pMem; } + void setMemoryManager(MemoryManager* pMem, memory_type_t type=MEMTYPE_RAM) { + m_Mems[type] = pMem; + } /* ******************************************************************** * Experiment-Flow & Listener Management API: * ********************************************************************/ diff --git a/src/core/sal/bochs/BochsController.cc b/src/core/sal/bochs/BochsController.cc index 7b8aa140..c7c39303 100644 --- a/src/core/sal/bochs/BochsController.cc +++ b/src/core/sal/bochs/BochsController.cc @@ -27,7 +27,7 @@ BochsController::BochsController() BochsController::~BochsController() { - delete m_Mem; + delete &getMemoryManager(); std::vector::iterator it = m_CPUs.begin(); while (it != m_CPUs.end()) { delete *it; diff --git a/src/core/sal/gem5/Gem5Controller.cc b/src/core/sal/gem5/Gem5Controller.cc index dc5737ad..a3fd7362 100644 --- a/src/core/sal/gem5/Gem5Controller.cc +++ b/src/core/sal/gem5/Gem5Controller.cc @@ -36,7 +36,7 @@ Gem5Controller::~Gem5Controller() delete *it; it = m_CPUs.erase(it); } - delete m_Mem; + delete &getMemoryManager(); } bool Gem5Controller::save(const std::string &path) diff --git a/src/core/sal/panda/PandaController.cc b/src/core/sal/panda/PandaController.cc index d73cfd1a..3ced64c8 100644 --- a/src/core/sal/panda/PandaController.cc +++ b/src/core/sal/panda/PandaController.cc @@ -30,12 +30,12 @@ PandaController::PandaController() PandaController::~PandaController() { - delete m_Mem; std::vector::iterator it = m_CPUs.begin(); while (it != m_CPUs.end()) { delete *it; it = m_CPUs.erase(it); } + delete &getMemoryManager(); } void PandaController::onTimerTrigger(void* thisPtr) diff --git a/src/core/sal/perf/FastWatchpoints.ah b/src/core/sal/perf/FastWatchpoints.ah index dc7b9d98..94fede41 100644 --- a/src/core/sal/perf/FastWatchpoints.ah +++ b/src/core/sal/perf/FastWatchpoints.ah @@ -10,6 +10,8 @@ #include "../ListenerManager.hpp" #include "WatchpointBuffer.hpp" #include "../SALInst.hpp" +#include "../Memory.hpp" + // Warning: Do not import namespace using "using namespace"! // (It may yields collisions due to woven aspect code.) @@ -52,11 +54,30 @@ aspect FastWatchpoints { fail::ListenerManager& ref = tjp->target()->m_LstList; #define ARG(i) *(tjp->arg()) - fail::MemAccessEvent tmp(ARG(1), ARG(2), ARG(4), - ARG(3) ? fail::MemAccessEvent::MEM_WRITE : fail::MemAccessEvent::MEM_READ, - ARG(0)); + auto cpu = ARG(0); + auto addr = ARG(1); + auto len = ARG(2); + auto is_write = ARG(3); + auto instrPtr = ARG(4); + auto memtype = ARG(5); #undef ARG - + + fail::MemAccessEvent tmp(addr, len, instrPtr, + is_write ? fail::MemAccessEvent::MEM_WRITE : fail::MemAccessEvent::MEM_READ, + cpu, memtype); + // Read Memory with help of Memory Manager + if (memtype == fail::MEMTYPE_RAM) { + uint64_t data = 0; + fail::MemoryManager &mm = tjp->that()->getMemoryManager(memtype); + char max_len = len > sizeof(data) ? sizeof(data) : len; + if (mm.isMapped(addr) && mm.isMapped(addr + len - 1)) { + mm.getBytes(addr, max_len, &data); + tmp.setAccessedData(data); + } + } + #undef ARG + + // Check for matching MemAccessListener: fail::ResultSet& res = ref.getMemoryListeners().gather(&tmp); while (res.hasMore()) diff --git a/src/core/sal/perf/WatchpointBuffer.cc b/src/core/sal/perf/WatchpointBuffer.cc index ad2e27b4..4a8159b3 100644 --- a/src/core/sal/perf/WatchpointBuffer.cc +++ b/src/core/sal/perf/WatchpointBuffer.cc @@ -17,6 +17,8 @@ ResultSet& PerfVectorWatchpoints::gather(MemAccessEvent* pData) // Update trigger data: pmal->setTriggerInstructionPointer(pData->getTriggerInstructionPointer()); pmal->setTriggerAddress(pData->getTriggerAddress()); + pmal->setTriggerMemoryType(pData->getMemoryType()); + pmal->setAccessedData(pData->getAccessedData()); pmal->setTriggerWidth(pData->getTriggerWidth()); pmal->setTriggerAccessType(pData->getTriggerAccessType()); pmal->setTriggerCPU(pData->getTriggerCPU()); diff --git a/src/core/sal/qemu/QEMUController.cc b/src/core/sal/qemu/QEMUController.cc index e5fcac81..8e26f63d 100644 --- a/src/core/sal/qemu/QEMUController.cc +++ b/src/core/sal/qemu/QEMUController.cc @@ -18,7 +18,7 @@ QEMUController::QEMUController() QEMUController::~QEMUController() { delete m_Regs; - delete m_Mem; + delete &getMemoryManager(); } // FIXME: copied from BochsController; remove redundancy! diff --git a/src/plugins/tracing/TracingPlugin.cc b/src/plugins/tracing/TracingPlugin.cc index 225ec3f9..dc40d89e 100644 --- a/src/plugins/tracing/TracingPlugin.cc +++ b/src/plugins/tracing/TracingPlugin.cc @@ -82,12 +82,15 @@ bool TracingPlugin::run() if (m_os) *m_os << hex << "[Tracing] MEM " + << "(type=" << ev_mem.getTriggerMemoryType() << ") " << ((ev_mem.getTriggerAccessType() & MemAccessEvent::MEM_READ) ? "R " : "W ") - << addr << " width " << width << " IP " << ip << "\n"; + << addr << " width " << dec << width << " IP " << ip + << " data: " << ev_mem.getAccessedData() << "\n"; if (m_protoStreamFile) { Trace_Event e; e.set_ip(ip); + e.set_memtype(ev_mem.getTriggerMemoryType()); e.set_memaddr(addr); e.set_width(width); e.set_accesstype( @@ -106,13 +109,7 @@ bool TracingPlugin::run() the case of a memory event */ if (m_full_trace) { Trace_Event_Extended &ext = *e.mutable_trace_ext(); - // Read the accessed data - if (width > 8) { - width = 8; - } - uint64_t data = 0; - mm.getBytes(addr, width, &data); - ext.set_data(data); + ext.set_data(ev_mem.getAccessedData()); for (UniformRegisterSet::iterator it = extended_trace_regs->begin(); it != extended_trace_regs->end(); ++it) { diff --git a/tools/bochs-experiment-runner/bochs-experiment-runner.py b/tools/bochs-experiment-runner/bochs-experiment-runner.py old mode 100644 new mode 100755 diff --git a/tools/dump-trace/DumpTrace.cc b/tools/dump-trace/DumpTrace.cc index d1568f59..8af8ba54 100644 --- a/tools/dump-trace/DumpTrace.cc +++ b/tools/dump-trace/DumpTrace.cc @@ -7,6 +7,7 @@ #include "../../src/core/util/Logger.hpp" #include "../../src/core/util/gzstream/gzstream.h" #include "util/CommandLine.hpp" +#include "sal/SALConfig.hpp" using namespace fail; using std::stringstream; @@ -139,13 +140,21 @@ int main(int argc, char *argv[]) } } if (!stats_only) { - cout << "MEM " - << (ev.accesstype() == Trace_Event_AccessType_READ ? "R" : "W") << " " - << hex << ev.memaddr() - << dec << " width " << ev.width() - << hex << " IP " << ev.ip() - << dec << " t=" << acctime - << ext.str() << "\n"; + std::string memtype = ""; + if (ev.memtype() == fail::MEMTYPE_RAM) memtype = ""; + else if (ev.memtype() == fail::MEMTYPE_FLASH) memtype = "/flash"; + else if (ev.memtype() == fail::MEMTYPE_TAGS) memtype = "/tags"; + else if (ev.memtype() == fail::MEMTYPE_EEPROM) memtype = "/eeprom"; + else memtype = "/unknown"; + + + cout << "MEM" << memtype << " " + << (ev.accesstype() == Trace_Event_AccessType_READ ? "R" : "W") << " " + << hex << ev.memaddr() + << dec << " width " << ev.width() + << hex << " IP " << ev.ip() + << dec << " t=" << acctime + << ext.str() << "\n"; } else { for (uint64_t addr = ev.memaddr(); addr < ev.memaddr() + ev.width(); addr++){ stats_mem_locations.insert(addr); diff --git a/tools/import-trace/Importer.hpp b/tools/import-trace/Importer.hpp index cb3ad49c..8cb03267 100644 --- a/tools/import-trace/Importer.hpp +++ b/tools/import-trace/Importer.hpp @@ -31,6 +31,7 @@ class Importer : public fail::AliasedRegisterable { fail::Database *db; fail::Architecture m_arch; fail::UniformRegisterSet *m_extended_trace_regs; + fail::memory_type_t m_memtype; /* How many rows were inserted into the database */ unsigned m_row_count; @@ -123,8 +124,8 @@ class Importer : public fail::AliasedRegisterable { Importer() : m_variant_id(0), m_elf(NULL), m_mm(NULL), m_faultspace_rightmargin('W'), m_sanitychecks(false), m_import_write_ecs(true), m_extended_trace(false), m_cover_memorymap(false), db(NULL), - m_extended_trace_regs(NULL), m_row_count(0), m_time_trace_start(0), - m_last_ip(0), m_last_instr(0), m_last_time(0) {} + m_extended_trace_regs(NULL), m_memtype(fail::ANY_MEMORY), + m_row_count(0), m_time_trace_start(0), m_last_ip(0), m_last_instr(0), m_last_time(0) {} bool init(const std::string &variant, const std::string &benchmark, fail::Database *db); /** @@ -145,6 +146,7 @@ class Importer : public fail::AliasedRegisterable { void set_import_write_ecs(bool enabled) { m_import_write_ecs = enabled; } void set_extended_trace(bool enabled) { m_extended_trace = enabled; } void set_cover_memorymap(bool enabled) { m_cover_memorymap = enabled; } + void set_memory_type(fail::memory_type_t type) { m_memtype = type; } }; #endif diff --git a/tools/import-trace/MemoryImporter.cc b/tools/import-trace/MemoryImporter.cc index 64571529..d54d502c 100644 --- a/tools/import-trace/MemoryImporter.cc +++ b/tools/import-trace/MemoryImporter.cc @@ -11,6 +11,11 @@ bool MemoryImporter::handle_ip_event(simtime_t curtime, instruction_count_t inst bool MemoryImporter::handle_mem_event(simtime_t curtime, instruction_count_t instr, Trace_Event &ev) { + // Filter out memory events of wrong memory type + memory_type_t mtype = static_cast(ev.memtype()); + if(mtype != m_memtype && m_memtype != ANY_MEMORY) + return true; + address_t from = ev.memaddr(), to = ev.memaddr() + ev.width(); // Iterate over all accessed bytes // FIXME Keep complete trace information (access width)? diff --git a/tools/import-trace/main.cc b/tools/import-trace/main.cc index 61ec9a2d..5588e9af 100644 --- a/tools/import-trace/main.cc +++ b/tools/import-trace/main.cc @@ -132,6 +132,10 @@ int main(int argc, char *argv[]) { cmd.addOption("", "extended-trace", Arg::None, "--extended-trace \tImport extended trace information if available"); + CommandLine::option_handle MEMORY_TYPE = + cmd.addOption("", "memory-type", Arg::Required, + "--memory-type\t Only import memory access trace events with the specified type. (default: any)"); + // variant 1: care (synthetic Rs) // variant 2: don't care (synthetic Ws) CommandLine::option_handle FAULTSPACE_RIGHTMARGIN = @@ -238,6 +242,26 @@ int main(int argc, char *argv[]) { } importer->set_memorymap(memorymap); + if (cmd[MEMORY_TYPE]) { + std::string arg(cmd[MEMORY_TYPE].first()->arg); + memory_type_t type; + if (arg == "ram") + type = MEMTYPE_RAM; + else if (arg == "flash") + type = MEMTYPE_FLASH; + else if (arg == "tags") + type = MEMTYPE_TAGS; + else if (arg == "eeprom") + type = MEMTYPE_EEPROM; + else if (arg == "any") + type = ANY_MEMORY; + else { + LOG << "ERROR: unknown memory type: " << arg << std::endl; + exit(-1); + } + importer->set_memory_type(type); + } + if (cmd[FAULTSPACE_RIGHTMARGIN]) { std::string rightmargin(cmd[FAULTSPACE_RIGHTMARGIN].first()->arg); if (rightmargin == "W") {