From 9444dc0910d9335c69e02ceba577991f08ea07cf Mon Sep 17 00:00:00 2001 From: Christian Dietrich Date: Tue, 15 Dec 2020 15:12:37 +0100 Subject: [PATCH 1/2] [SAL] Introduce support for multiple memory types Many architectures have different types of memory (flash, RAM, EEPROM, etc), which is currently not well supported in the FAIL* toolchain. Therefore, this change introduces memory types. A memory type is a simple tag that is attached to memory events and memory listeners. Furthermore, the generic-tracing experiment records memory types and dump-trace displays them. Currently, they are not yet used in importing. However, with SAIL integration, we require this kind of disambiguation between different memory types. Furthermore, MemoryAccessEvents now carry the memory area that was accessed. This change should not break previous experiments and/or results. Co-authored-by: Malte Bargholz --- src/core/comm/TracePlugin.proto | 1 + src/core/sal/Event.hpp | 37 ++++++++++-- src/core/sal/Listener.cc | 6 +- src/core/sal/Listener.hpp | 59 +++++++++++++++---- src/core/sal/SALConfig.cc | 1 + src/core/sal/SALConfig.hpp | 10 ++++ src/core/sal/SimulatorController.cc | 22 +++++-- src/core/sal/SimulatorController.hpp | 28 +++++---- src/core/sal/bochs/BochsController.cc | 2 +- src/core/sal/gem5/Gem5Controller.cc | 2 +- src/core/sal/panda/PandaController.cc | 2 +- src/core/sal/perf/FastWatchpoints.ah | 29 +++++++-- src/core/sal/perf/WatchpointBuffer.cc | 2 + src/core/sal/qemu/QEMUController.cc | 2 +- src/plugins/tracing/TracingPlugin.cc | 13 ++-- .../bochs-experiment-runner.py | 0 tools/dump-trace/DumpTrace.cc | 23 +++++--- 17 files changed, 184 insertions(+), 55 deletions(-) mode change 100644 => 100755 tools/bochs-experiment-runner/bochs-experiment-runner.py 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); From 168203b6f964b40fd3279a05b962c848efbe02ba Mon Sep 17 00:00:00 2001 From: Christian Dietrich Date: Mon, 4 Jan 2021 16:11:41 +0100 Subject: [PATCH 2/2] import-trace: --memory-type filter to focus on a specific memory type --- tools/import-trace/Importer.hpp | 6 ++++-- tools/import-trace/MemoryImporter.cc | 5 +++++ tools/import-trace/main.cc | 24 ++++++++++++++++++++++++ 3 files changed, 33 insertions(+), 2 deletions(-) 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") {