Skip to content

Commit 3d74a26

Browse files
stettbergerMalte Bargholz
andcommitted
[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 <malte@screenri.de>
1 parent a0a1970 commit 3d74a26

17 files changed

Lines changed: 184 additions & 55 deletions

src/core/comm/TracePlugin.proto

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ message Trace_Event {
2525
// and for target backends capable of timing-accurate execution
2626
optional int64 time_delta = 6;
2727
optional uint64 memaddr = 2;
28+
optional uint32 memtype = 7;
2829
optional uint32 width = 3;
2930
enum AccessType {
3031
READ = 1;

src/core/sal/Event.hpp

Lines changed: 32 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ namespace fail {
1515

1616
/**
1717
* \class BaseEvent
18-
* This is the base class for all event types. It encapsulates the information
18+
* This is the base class for all event types. It encapsulates the information
1919
* about an event reported by the simulator backend.
2020
*/
2121
class BaseEvent {
@@ -99,15 +99,20 @@ class MemAccessEvent : public BaseEvent {
9999
address_t m_TriggerIP;
100100
//! Memory access type at m_TriggerAddr.
101101
access_type_t m_AccessType;
102+
//! Specific memory type in which this access occured.
103+
memory_type_t m_MemType;
104+
//! The data that was accessed in this event.
105+
uint64_t m_Data;
102106
public:
103107
/**
104108
* Creates a new \c MemAccessEvent using default initialization values, i.e.
105109
* \c setTriggerAddress(ANY_ADDR), \c setTriggerWidth(0), \c setTriggerAccessType(MEM_UNKNOWN),
106-
* \c setTriggerInstructionPointer(ANY_ADDR) and setTriggerCPU(NULL).
110+
* \c setTriggerInstructionPointer(ANY_ADDR), setMemType(MEMTYPE_RAM), and setTriggerCPU(NULL).
107111
*/
108112
MemAccessEvent()
109113
: m_TriggerAddr(ANY_ADDR), m_TriggerWidth(0),
110-
m_TriggerIP(ANY_ADDR), m_AccessType(MEM_UNKNOWN) { }
114+
m_TriggerIP(ANY_ADDR), m_AccessType(MEM_UNKNOWN),
115+
m_MemType(MEMTYPE_RAM), m_Data(0){ }
111116
/**
112117
* Creates a new \c MemAccessEvent and initializes the provided values.
113118
* @param triggerAddr actual address that triggered the event
@@ -117,9 +122,9 @@ class MemAccessEvent : public BaseEvent {
117122
* @param cpu the CPU that triggered the event
118123
*/
119124
MemAccessEvent(address_t triggerAddr, size_t width, address_t triggerIP, access_type_t type,
120-
ConcreteCPU* cpu = NULL)
125+
ConcreteCPU* cpu = NULL, memory_type_t memtype=MEMTYPE_RAM, uint64_t data=0)
121126
: BaseEvent(cpu), m_TriggerAddr(triggerAddr), m_TriggerWidth(width),
122-
m_TriggerIP(triggerIP), m_AccessType(type) { }
127+
m_TriggerIP(triggerIP), m_AccessType(type), m_MemType(memtype), m_Data(data){ }
123128
/**
124129
* Returns the specific memory address that actually triggered the event.
125130
* @return the triggering address
@@ -131,6 +136,28 @@ class MemAccessEvent : public BaseEvent {
131136
* @param addr the new triggering address
132137
*/
133138
void setTriggerAddress(address_t addr) { m_TriggerAddr = addr; }
139+
/**
140+
* Returns the type of memory which actually triggered the event.
141+
* @return A memory_type_t which corresponds to the memory which triggered the event.
142+
*/
143+
memory_type_t getMemoryType() const { return m_MemType; }
144+
/**
145+
* Set the specific memory type which triggered the event.
146+
* Should not be used by experiment code.
147+
* @param type the new memory type.
148+
*/
149+
void setMemoryType(memory_type_t type) { m_MemType = type; }
150+
/**
151+
* Returns the data at the memory location that was accessed if it is available.
152+
* @return The value of the accessed memory location .
153+
*/
154+
uint64_t getAccessedData() const { return m_Data; }
155+
/**
156+
* Set the data, which was accessed during the memory event.
157+
* Should not be used by experiment code.
158+
* @param data The data to be saved.
159+
*/
160+
void setAccessedData(uint64_t data) { m_Data = data; }
134161
/**
135162
* Returns the specific number of bytes read or written at \c getTriggerAddress().
136163
* @return the width of the memory access

src/core/sal/Listener.cc

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,8 +52,10 @@ bool MemAccessListener::isMatching(const MemAccessEvent* pEv) const
5252
if (!(m_WatchType & pEv->getTriggerAccessType())) {
5353
return false;
5454
} else if (m_WatchAddr != ANY_ADDR
55-
&& (m_WatchAddr >= pEv->getTriggerAddress() + pEv->getTriggerWidth()
56-
|| m_WatchAddr + m_WatchWidth <= pEv->getTriggerAddress())) {
55+
&& (m_WatchAddr >= pEv->getTriggerAddress() + pEv->getTriggerWidth()
56+
|| m_WatchAddr + m_WatchWidth <= pEv->getTriggerAddress())) {
57+
return false;
58+
} else if (m_WatchMemType != ANY_MEMORY && m_WatchMemType != pEv->getMemoryType()) {
5759
return false;
5860
} else if (m_CPU != NULL && m_CPU != pEv->getTriggerCPU()) {
5961
return false;

src/core/sal/Listener.hpp

Lines changed: 48 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -315,6 +315,8 @@ class MemAccessListener : public BaseListener {
315315
protected:
316316
//! Specific physical guest system address to watch, or ANY_ADDR.
317317
address_t m_WatchAddr;
318+
//! Specific memory type to watch (e.g. Tag memory), or ANY_MEMORY.
319+
memory_type_t m_WatchMemType;
318320
//! Width of the memory area being watched (# bytes).
319321
size_t m_WatchWidth;
320322
/**
@@ -326,15 +328,15 @@ class MemAccessListener : public BaseListener {
326328
WP_CTOR_SCOPE:
327329
MemAccessListener(MemAccessEvent::access_type_t type = MemAccessEvent::MEM_READWRITE,
328330
ConcreteCPU* cpu = NULL)
329-
: BaseListener(cpu), m_WatchAddr(ANY_ADDR), m_WatchWidth(1), m_WatchType(type) { }
330-
MemAccessListener(address_t addr,
331-
MemAccessEvent::access_type_t type = MemAccessEvent::MEM_READWRITE,
331+
: BaseListener(cpu), m_WatchAddr(ANY_ADDR), m_WatchMemType(ANY_MEMORY), m_WatchWidth(1), m_WatchType(type), m_Data() { }
332+
MemAccessListener(address_t addr, memory_type_t memtype = ANY_MEMORY,
333+
MemAccessEvent::access_type_t type = MemAccessEvent::MEM_READWRITE,
332334
ConcreteCPU* cpu = NULL)
333-
: BaseListener(cpu), m_WatchAddr(addr), m_WatchWidth(1), m_WatchType(type) { }
334-
MemAccessListener(const ElfSymbol &symbol,
335-
MemAccessEvent::access_type_t type = MemAccessEvent::MEM_READWRITE,
335+
: BaseListener(cpu), m_WatchAddr(addr), m_WatchMemType(memtype), m_WatchWidth(1), m_WatchType(type), m_Data() { }
336+
MemAccessListener(const ElfSymbol &symbol, memory_type_t memtype = ANY_MEMORY,
337+
MemAccessEvent::access_type_t type = MemAccessEvent::MEM_READWRITE,
336338
ConcreteCPU* cpu = NULL)
337-
: BaseListener(cpu), m_WatchAddr(symbol.getAddress()), m_WatchWidth(symbol.getSize()), m_WatchType(type) { }
339+
: BaseListener(cpu), m_WatchAddr(symbol.getAddress()), m_WatchMemType(memtype), m_WatchWidth(symbol.getSize()), m_WatchType(type) , m_Data() { }
338340
public:
339341
/**
340342
* Returns the physical memory address to be observed.
@@ -344,6 +346,14 @@ class MemAccessListener : public BaseListener {
344346
* Sets the physical memory address to be observed. (Wildcard: ANY_ADDR)
345347
*/
346348
void setWatchAddress(address_t addr) { m_WatchAddr = addr; }
349+
/**
350+
* Returns the memory type to be observed.
351+
*/
352+
memory_type_t getWatchMemoryType() const { return m_WatchMemType; }
353+
/**
354+
* Sets the memory type to be observed. (Wildcard: ANY_MEMORY)
355+
*/
356+
void setWatchMemoryType(memory_type_t type) { m_WatchMemType = type; }
347357
/**
348358
* Returns the width of the memory area being watched.
349359
*/
@@ -370,6 +380,33 @@ class MemAccessListener : public BaseListener {
370380
* listener. Should not be used by experiment code.
371381
*/
372382
void setTriggerAddress(address_t addr) { m_Data.setTriggerAddress(addr); }
383+
/**
384+
* Returns the type of memory which actually triggered the event.
385+
* @return A memory_type_t which corresponds to the memory which triggered the event.
386+
*/
387+
memory_type_t getTriggerMemoryType() const { return m_Data.getMemoryType(); }
388+
/**
389+
* Set the specific memory type which triggered the event.
390+
* Should not be used by experiment code.
391+
* @param type the new memory type.
392+
*/
393+
void setTriggerMemoryType(memory_type_t type) { m_Data.setMemoryType(type); }
394+
/**
395+
* Returns the data at the memory location that was accessed if it is available.
396+
* @return A uint64_t which contains at most 8 bytes of the accessed data.
397+
*/
398+
uint64_t getAccessedData() const { return m_Data.getAccessedData(); }
399+
/**
400+
* Set the data, which was accessed during the memory event.
401+
* This data is copied into this class.
402+
* Should not be used by experiment code.
403+
* @param type the new memory type.
404+
*/
405+
void setAccessedData(uint64_t data) { m_Data.setAccessedData(data); }
406+
/**
407+
* Returns the specific number of bytes read or written at \c getTriggerAddress().
408+
* @return the width of the memory access
409+
*/
373410
/**
374411
* Returns the width (in bytes) of the memory access that triggered this
375412
* listener.
@@ -425,8 +462,8 @@ class MemReadListener : public MemAccessListener {
425462
WPREAD_CTOR_SCOPE:
426463
MemReadListener(ConcreteCPU* cpu = NULL)
427464
: MemAccessListener(MemAccessEvent::MEM_READ, cpu) { }
428-
MemReadListener(address_t addr, ConcreteCPU* cpu = NULL)
429-
: MemAccessListener(addr, MemAccessEvent::MEM_READ, cpu) { }
465+
MemReadListener(address_t addr, memory_type_t type = ANY_MEMORY, ConcreteCPU* cpu = NULL)
466+
: MemAccessListener(addr, type, MemAccessEvent::MEM_READ, cpu) { }
430467
};
431468

432469
#ifdef CONFIG_EVENT_MEMWRITE
@@ -442,8 +479,8 @@ class MemWriteListener : public MemAccessListener {
442479
WPWRITE_CTOR_SCOPE:
443480
MemWriteListener(ConcreteCPU* cpu = NULL)
444481
: MemAccessListener(MemAccessEvent::MEM_WRITE, cpu) { }
445-
MemWriteListener(address_t addr, ConcreteCPU* cpu = NULL)
446-
: MemAccessListener(addr, MemAccessEvent::MEM_WRITE, cpu) { }
482+
MemWriteListener(address_t addr, memory_type_t type = ANY_MEMORY, ConcreteCPU* cpu = NULL)
483+
: MemAccessListener(addr, type, MemAccessEvent::MEM_WRITE, cpu) { }
447484
};
448485

449486
#if defined CONFIG_EVENT_INTERRUPT || defined CONFIG_EVENT_TRAP

src/core/sal/SALConfig.cc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ namespace fail {
99
defined BUILD_PANDA
1010
const address_t ADDR_INV = static_cast<address_t> (0);
1111
const address_t ANY_ADDR = static_cast<address_t> (-1);
12+
const memory_type_t ANY_MEMORY = static_cast<memory_type_t> (-1);
1213
const unsigned ANY_INSTR = static_cast<unsigned> (-1);
1314
const unsigned ANY_TRAP = static_cast<unsigned> (-1);
1415
const unsigned ANY_INTERRUPT = static_cast<unsigned> (-1);

src/core/sal/SALConfig.hpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,12 +33,22 @@ typedef uint64_t simtime_t;
3333
//! backend-specific notion of time difference
3434
typedef int64_t simtime_diff_t;
3535

36+
typedef enum {
37+
MEMTYPE_UNKNOWN = 0x0, //!< Somehow, we do not know
38+
MEMTYPE_RAM = 0x1, //!< Access to volatile memory
39+
MEMTYPE_FLASH = 0x2, //!< Access to flash memory
40+
MEMTYPE_TAGS = 0x3, //!< Access to tag-bits (see SAIL)
41+
MEMTYPE_EEPROM = 0x4 //!< Access to EEPROM (see AVR)
42+
} memory_type_t; //! memory type (RAM, FLASH, etc...)
43+
3644
// Note: The following flags are defined in SALConfig.cc.
3745

3846
//! invalid address flag (e.g. for memory address ptrs)
3947
extern const address_t ADDR_INV;
4048
//! address wildcard (e.g. for breakpoint listeners)
4149
extern const address_t ANY_ADDR;
50+
//! memory type wildcard (e.g. for memory access listener)
51+
extern const memory_type_t ANY_MEMORY;
4252
//! instruction wildcard (e.g. for jump listeners)
4353
extern const unsigned ANY_INSTR;
4454
//! trap wildcard

src/core/sal/SimulatorController.cc

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
#include "Event.hpp"
44
#include "Listener.hpp"
55
#include "util/CommandLine.hpp"
6+
#include "Memory.hpp"
67

78
namespace fail {
89

@@ -136,15 +137,16 @@ void SimulatorController::onBreakpoint(ConcreteCPU* cpu, address_t instrPtr, add
136137
m_LstList.triggerActiveListeners();
137138
}
138139

139-
void SimulatorController::onMemoryAccess(ConcreteCPU* cpu, address_t addr, size_t len,
140-
bool is_write, address_t instrPtr)
140+
void SimulatorController::onMemoryAccess(ConcreteCPU* cpu, address_t addr, size_t len,
141+
bool is_write, address_t instrPtr, memory_type_t type)
141142
{
142143
MemAccessEvent::access_type_t accesstype =
143144
is_write ? MemAccessEvent::MEM_WRITE
144145
: MemAccessEvent::MEM_READ;
145146

146-
MemAccessEvent tmp(addr, len, instrPtr, accesstype, cpu);
147+
MemAccessEvent tmp(addr, len, instrPtr, accesstype, cpu, type);
147148
ListenerManager::iterator it = m_LstList.begin();
149+
148150
while (it != m_LstList.end()) { // check for active listeners
149151
BaseListener* pev = *it;
150152
MemAccessListener* ev = dynamic_cast<MemAccessListener*>(pev);
@@ -159,6 +161,18 @@ void SimulatorController::onMemoryAccess(ConcreteCPU* cpu, address_t addr, size_
159161
ev->setTriggerAccessType(accesstype);
160162
ev->setTriggerCPU(cpu);
161163
it = m_LstList.makeActive(it);
164+
165+
// Read Memory with help of Memory Manager
166+
ev->setTriggerMemoryType(type);
167+
if (type == MEMTYPE_RAM) {
168+
uint64_t data = 0;
169+
MemoryManager &mm = getMemoryManager(type);
170+
char max_len = len > sizeof(data) ? sizeof(data) : len;
171+
if (mm.isMapped(addr) && mm.isMapped(addr + len - 1)) {
172+
mm.getBytes(addr, max_len, &data);
173+
ev->setAccessedData(data);
174+
}
175+
}
162176
}
163177
m_LstList.triggerActiveListeners();
164178
}
@@ -276,7 +290,7 @@ BaseListener* SimulatorController::addListenerAndResume(BaseListener* li)
276290
void SimulatorController::terminate(int exCode)
277291
{
278292
// Attention: This could cause problems, e.g., because of non-closed sockets
279-
std::cout << "[FAIL] Exit called by experiment with exit code: " << exCode << std::endl;
293+
m_log << "[FAIL] Exit called by experiment with exit code: " << exCode << std::endl;
280294
// TODO: (Non-)Verbose-Mode? Log-Level?
281295

282296
m_Flows.setTerminated(); // we are about to terminate

src/core/sal/SimulatorController.hpp

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -41,21 +41,20 @@ class SimulatorController {
4141
ListenerManager m_LstList; //!< storage where listeners are being buffered
4242
std::map<std::string, ExperimentFlow *> m_Experiments; //!< registered experiments, one is chosen on startup
4343
CoroutineManager m_Flows; //!< managed experiment flows
44-
MemoryManager *m_Mem; //!< access to memory pool
44+
std::map<memory_type_t, MemoryManager *> m_Mems; //!< access to memory pool(s)
4545
std::vector<ConcreteCPU*> m_CPUs; //!< list of CPUs in the target system
4646
friend class ListenerManager; //!< "outsources" the listener management
4747
std::string m_argv0; //!< Invocation name of simulator process
4848
public:
4949
SimulatorController()
5050
: m_log("SimulatorController", false),
51-
m_isInitialized(false),
52-
m_Mem(nullptr)
51+
m_isInitialized(false)
5352
{ /* blank */ }
5453
SimulatorController(MemoryManager* mem)
5554
: m_log("SimulatorController", false),
56-
m_isInitialized(false),
57-
m_Mem(mem)
58-
{ /* blank */ }
55+
m_isInitialized(false) {
56+
m_Mems[MEMTYPE_RAM] = mem; // The RAM memory manager is the default
57+
}
5958
virtual ~SimulatorController() { }
6059
/**
6160
* @brief Initialization function each implementation needs to call on
@@ -95,11 +94,14 @@ class SimulatorController {
9594
* @param len the length of the accessed memory
9695
* @param is_write \c true if memory is written, \c false if read
9796
* @param instrPtr the address of the instruction causing the memory
97+
* @param type The type of memory that was accessed.
98+
* @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.
9899
* access
99100
*
100101
* FIXME: should instrPtr be part of this interface?
101102
*/
102-
void onMemoryAccess(ConcreteCPU* cpu, address_t addr, size_t len, bool is_write, address_t instrPtr);
103+
void onMemoryAccess(ConcreteCPU* cpu, address_t addr, size_t len, bool is_write, address_t instrPtr,
104+
memory_type_t type=MEMTYPE_RAM);
103105
/**
104106
* Interrupt handler.
105107
* @param cpu the CPU that caused the interrupt
@@ -174,13 +176,19 @@ class SimulatorController {
174176
* Returns the (constant) initialized memory manager.
175177
* @return a reference to the memory manager
176178
*/
177-
MemoryManager& getMemoryManager() { return *m_Mem; }
178-
const MemoryManager& getMemoryManager() const { return *m_Mem; }
179+
MemoryManager& getMemoryManager(memory_type_t type=MEMTYPE_RAM) {
180+
return *m_Mems.at(type);
181+
}
182+
const MemoryManager& getMemoryManager(memory_type_t type=MEMTYPE_RAM) const {
183+
return *m_Mems.at(type);
184+
}
179185
/**
180186
* Sets the memory manager.
181187
* @param pMem a new concrete memory manager
182188
*/
183-
void setMemoryManager(MemoryManager* pMem) { m_Mem = pMem; }
189+
void setMemoryManager(MemoryManager* pMem, memory_type_t type=MEMTYPE_RAM) {
190+
m_Mems[type] = pMem;
191+
}
184192
/* ********************************************************************
185193
* Experiment-Flow & Listener Management API:
186194
* ********************************************************************/

src/core/sal/bochs/BochsController.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ BochsController::BochsController()
2727

2828
BochsController::~BochsController()
2929
{
30-
delete m_Mem;
30+
delete &getMemoryManager();
3131
std::vector<ConcreteCPU*>::iterator it = m_CPUs.begin();
3232
while (it != m_CPUs.end()) {
3333
delete *it;

src/core/sal/gem5/Gem5Controller.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ Gem5Controller::~Gem5Controller()
3636
delete *it;
3737
it = m_CPUs.erase(it);
3838
}
39-
delete m_Mem;
39+
delete &getMemoryManager();
4040
}
4141

4242
bool Gem5Controller::save(const std::string &path)

0 commit comments

Comments
 (0)