Simulator specific listener are now implemented using aspects instead of an additional inheritance level
git-svn-id: https://www4.informatik.uni-erlangen.de/i4svn/danceos/trunk/devel/fail@1706 8c4709b5-6ec9-48aa-a5cd-a96041d1645a
This commit is contained in:
@ -7,7 +7,6 @@ if(BUILD_BOCHS)
|
|||||||
SimulatorController.cc
|
SimulatorController.cc
|
||||||
perf/BreakpointBuffer.cc
|
perf/BreakpointBuffer.cc
|
||||||
bochs/BochsController.cc
|
bochs/BochsController.cc
|
||||||
bochs/BochsListener.cc
|
|
||||||
)
|
)
|
||||||
elseif(BUILD_GEM5)
|
elseif(BUILD_GEM5)
|
||||||
set(SRCS
|
set(SRCS
|
||||||
@ -17,7 +16,6 @@ elseif(BUILD_GEM5)
|
|||||||
Register.cc
|
Register.cc
|
||||||
SimulatorController.cc
|
SimulatorController.cc
|
||||||
gem5/Gem5Controller.cc
|
gem5/Gem5Controller.cc
|
||||||
gem5/Gem5Listener.cc
|
|
||||||
gem5/Gem5PCEvent.cc
|
gem5/Gem5PCEvent.cc
|
||||||
)
|
)
|
||||||
elseif(BUILD_OVP)
|
elseif(BUILD_OVP)
|
||||||
@ -39,7 +37,6 @@ elseif(BUILD_QEMU)
|
|||||||
perf/BreakpointBuffer.cc
|
perf/BreakpointBuffer.cc
|
||||||
SimulatorController.cc
|
SimulatorController.cc
|
||||||
qemu/QEMUController.cc
|
qemu/QEMUController.cc
|
||||||
qemu/QEMUListener.cc
|
|
||||||
qemu/wrappers.cc
|
qemu/wrappers.cc
|
||||||
)
|
)
|
||||||
endif(BUILD_BOCHS)
|
endif(BUILD_BOCHS)
|
||||||
|
|||||||
@ -74,7 +74,7 @@ bool BPRangeListener::isMatching(const BPEvent* pEv) const
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GenericBPSingleListener::isMatching(const BPEvent* pEv) const
|
bool BPSingleListener::isMatching(const BPEvent* pEv) const
|
||||||
{
|
{
|
||||||
if (aspaceIsMatching(pEv->getCR3())) {
|
if (aspaceIsMatching(pEv->getCR3())) {
|
||||||
if (m_WatchInstrPtr == ANY_ADDR || m_WatchInstrPtr == pEv->getTriggerInstructionPointer())
|
if (m_WatchInstrPtr == ANY_ADDR || m_WatchInstrPtr == pEv->getTriggerInstructionPointer())
|
||||||
|
|||||||
@ -173,7 +173,7 @@ public:
|
|||||||
* \class BPSingleListener
|
* \class BPSingleListener
|
||||||
* A Breakpoint listener to observe specific instruction pointers.
|
* A Breakpoint listener to observe specific instruction pointers.
|
||||||
*/
|
*/
|
||||||
class GenericBPSingleListener : public BPListener {
|
class BPSingleListener : public BPListener {
|
||||||
protected:
|
protected:
|
||||||
address_t m_WatchInstrPtr;
|
address_t m_WatchInstrPtr;
|
||||||
public:
|
public:
|
||||||
@ -189,7 +189,7 @@ public:
|
|||||||
* Here, too, ANY_ADDR is a placeholder to allow debugging
|
* Here, too, ANY_ADDR is a placeholder to allow debugging
|
||||||
* in a random address space.
|
* in a random address space.
|
||||||
*/
|
*/
|
||||||
GenericBPSingleListener(address_t ip = 0, address_t address_space = ANY_ADDR)
|
BPSingleListener(address_t ip = 0, address_t address_space = ANY_ADDR)
|
||||||
: BPListener(address_space), m_WatchInstrPtr(ip) { }
|
: BPListener(address_space), m_WatchInstrPtr(ip) { }
|
||||||
/**
|
/**
|
||||||
* Returns the instruction pointer this listener waits for.
|
* Returns the instruction pointer this listener waits for.
|
||||||
@ -353,14 +353,14 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \class GenericMemWriteListener
|
* \class MemWriteListener
|
||||||
* Observes memory write accesses.
|
* Observes memory write accesses.
|
||||||
*/
|
*/
|
||||||
class GenericMemWriteListener : public MemAccessListener {
|
class MemWriteListener : public MemAccessListener {
|
||||||
public:
|
public:
|
||||||
GenericMemWriteListener()
|
MemWriteListener()
|
||||||
: MemAccessListener(MemAccessEvent::MEM_READ) { }
|
: MemAccessListener(MemAccessEvent::MEM_READ) { }
|
||||||
GenericMemWriteListener(address_t addr)
|
MemWriteListener(address_t addr)
|
||||||
: MemAccessListener(addr, MemAccessEvent::MEM_WRITE) { }
|
: MemAccessListener(addr, MemAccessEvent::MEM_WRITE) { }
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -568,16 +568,16 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \class GenericTimerListener
|
* \class TimerListener
|
||||||
* This listener type is used to create timeouts within in an experiment.
|
* This listener type is used to create timeouts within in an experiment.
|
||||||
*
|
*
|
||||||
* Depending on your simulator backend, a concrete class needs to be derived from
|
* Depending on your simulator backend, a concrete class needs to be derived from
|
||||||
* \c GenericTimerListener. \c onAddition should be used to register and \c onDeletion
|
* \c TimerListener. \c onAddition should be used to register and \c onDeletion
|
||||||
* to unregister the timer. \c onTrigger can be used to re-register the timer if a
|
* to unregister the timer. \c onTrigger can be used to re-register the timer if a
|
||||||
* repetitive timer is requested and the back-end doesn't support such timer types
|
* repetitive timer is requested and the back-end doesn't support such timer types
|
||||||
* natively.
|
* natively.
|
||||||
*/
|
*/
|
||||||
class GenericTimerListener : public BaseListener {
|
class TimerListener : public BaseListener {
|
||||||
protected:
|
protected:
|
||||||
unsigned m_Timeout; //!< timeout interval in milliseconds
|
unsigned m_Timeout; //!< timeout interval in milliseconds
|
||||||
GenericTimerEvent m_Data;
|
GenericTimerEvent m_Data;
|
||||||
@ -589,8 +589,8 @@ public:
|
|||||||
* @param timeout the time interval in milliseconds (ms)
|
* @param timeout the time interval in milliseconds (ms)
|
||||||
* @see SimulatorController::addListener
|
* @see SimulatorController::addListener
|
||||||
*/
|
*/
|
||||||
GenericTimerListener(unsigned timeout) : m_Timeout(timeout) { }
|
TimerListener(unsigned timeout) : m_Timeout(timeout) { }
|
||||||
~GenericTimerListener() { }
|
~TimerListener() { }
|
||||||
/**
|
/**
|
||||||
* Retrieves the internal timer id. Maybe useful for debug output.
|
* Retrieves the internal timer id. Maybe useful for debug output.
|
||||||
* @return the timer id
|
* @return the timer id
|
||||||
@ -610,16 +610,4 @@ public:
|
|||||||
|
|
||||||
} // end-of-namespace: fail
|
} // end-of-namespace: fail
|
||||||
|
|
||||||
#if defined BUILD_BOCHS
|
|
||||||
#include "bochs/BochsListener.hpp"
|
|
||||||
#elif defined BUILD_GEM5
|
|
||||||
#include "gem5/Gem5Listener.hpp"
|
|
||||||
#elif defined BUILD_OVP
|
|
||||||
// #include "ovp/OVPListener.hpp"
|
|
||||||
#elif defined BUILD_QEMU
|
|
||||||
#include "qemu/QEMUListener.hpp"
|
|
||||||
#else
|
|
||||||
#error SAL Config Target not defined
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif // __LISTENER_HPP__
|
#endif // __LISTENER_HPP__
|
||||||
|
|||||||
@ -3,6 +3,8 @@
|
|||||||
#include "ListenerManager.hpp"
|
#include "ListenerManager.hpp"
|
||||||
#include "SALInst.hpp"
|
#include "SALInst.hpp"
|
||||||
|
|
||||||
|
#include "Listener.hpp"
|
||||||
|
|
||||||
namespace fail {
|
namespace fail {
|
||||||
|
|
||||||
void ListenerManager::add(BaseListener* li, ExperimentFlow* pExp)
|
void ListenerManager::add(BaseListener* li, ExperimentFlow* pExp)
|
||||||
|
|||||||
@ -6,11 +6,12 @@
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
#include "Listener.hpp"
|
#include "perf/BufferInterface.hpp"
|
||||||
|
|
||||||
namespace fail {
|
namespace fail {
|
||||||
|
|
||||||
class ExperimentFlow;
|
class ExperimentFlow;
|
||||||
|
class BaseListener;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Buffer-list for a specific experiment; acts as a simple storage container
|
* Buffer-list for a specific experiment; acts as a simple storage container
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
#include "SimulatorController.hpp"
|
#include "SimulatorController.hpp"
|
||||||
#include "SALInst.hpp"
|
#include "SALInst.hpp"
|
||||||
#include "Event.hpp"
|
#include "Event.hpp"
|
||||||
|
#include "Listener.hpp"
|
||||||
|
|
||||||
namespace fail {
|
namespace fail {
|
||||||
|
|
||||||
|
|||||||
@ -9,7 +9,6 @@
|
|||||||
#include "efw/CoroutineManager.hpp"
|
#include "efw/CoroutineManager.hpp"
|
||||||
#include "ListenerManager.hpp"
|
#include "ListenerManager.hpp"
|
||||||
#include "SALConfig.hpp"
|
#include "SALConfig.hpp"
|
||||||
#include "Listener.hpp"
|
|
||||||
|
|
||||||
namespace fail {
|
namespace fail {
|
||||||
|
|
||||||
|
|||||||
@ -5,6 +5,7 @@
|
|||||||
#include "BochsRegister.hpp"
|
#include "BochsRegister.hpp"
|
||||||
#include "../Register.hpp"
|
#include "../Register.hpp"
|
||||||
#include "../SALInst.hpp"
|
#include "../SALInst.hpp"
|
||||||
|
#include "../Listener.hpp"
|
||||||
|
|
||||||
namespace fail {
|
namespace fail {
|
||||||
|
|
||||||
|
|||||||
@ -8,10 +8,8 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include "FailBochsGlobals.hpp"
|
#include "FailBochsGlobals.hpp"
|
||||||
#include "BochsListener.hpp"
|
|
||||||
|
|
||||||
#include "../SimulatorController.hpp"
|
#include "../SimulatorController.hpp"
|
||||||
#include "../Listener.hpp"
|
|
||||||
|
|
||||||
#include "bochs.h"
|
#include "bochs.h"
|
||||||
#include "cpu/cpu.h"
|
#include "cpu/cpu.h"
|
||||||
|
|||||||
51
src/core/sal/bochs/BochsListener.ah
Normal file
51
src/core/sal/bochs/BochsListener.ah
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
#ifndef __BOCHSLISTENER_AH__
|
||||||
|
#define __BOCHSLISTENER_AH__
|
||||||
|
|
||||||
|
#include "config/VariantConfig.hpp"
|
||||||
|
#include "config/FailConfig.hpp"
|
||||||
|
|
||||||
|
#if defined(BUILD_BOCHS) && defined(CONFIG_EVENT_BREAKPOINTS)
|
||||||
|
|
||||||
|
#include "bochs.h"
|
||||||
|
#include "BochsController.hpp"
|
||||||
|
|
||||||
|
aspect BochsListener
|
||||||
|
{
|
||||||
|
advice "fail::TimerListener" : slice class
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
bool onAddition()
|
||||||
|
{
|
||||||
|
// Register the timer listener in the Bochs simulator:
|
||||||
|
setId(m_registerTimer(this));
|
||||||
|
if(getId() == -1)
|
||||||
|
return false; // unable to register the timer (error in Bochs' function call)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void onDeletion()
|
||||||
|
{
|
||||||
|
// Unregister the time listener:
|
||||||
|
m_unregisterTimer(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
timer_id_t m_registerTimer(TimerListener* pev)
|
||||||
|
{
|
||||||
|
assert(pev != NULL && "FATAL ERROR: TimerListener object ptr cannot be NULL!");
|
||||||
|
return static_cast<timer_id_t>(
|
||||||
|
bx_pc_system.register_timer(pev, BochsController::onTimerTrigger, pev->getTimeout(),
|
||||||
|
false, 1/*start immediately*/, "Fail*: BochsController"/*name*/));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool m_unregisterTimer(TimerListener* pev)
|
||||||
|
{
|
||||||
|
assert(pev != NULL && "FATAL ERROR: TimerListener object ptr cannot be NULL!");
|
||||||
|
bx_pc_system.deactivate_timer(static_cast<unsigned>(pev->getId()));
|
||||||
|
return bx_pc_system.unregisterTimer(static_cast<unsigned>(pev->getId()));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // BUILD_BOCHS && CONFIG_EVENT_BREAKPOINTS
|
||||||
|
#endif // __BOCHSLISTENER_AH__
|
||||||
@ -1,36 +0,0 @@
|
|||||||
#include "BochsListener.hpp"
|
|
||||||
#include "../SALInst.hpp"
|
|
||||||
|
|
||||||
namespace fail {
|
|
||||||
|
|
||||||
bool TimerListener::onAddition()
|
|
||||||
{
|
|
||||||
// Register the timer listener in the Bochs simulator:
|
|
||||||
setId(m_registerTimer(this));
|
|
||||||
if(getId() == -1)
|
|
||||||
return false; // unable to register the timer (error in Bochs' function call)
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void TimerListener::onDeletion()
|
|
||||||
{
|
|
||||||
// Unregister the time listener:
|
|
||||||
m_unregisterTimer(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
timer_id_t TimerListener::m_registerTimer(TimerListener* pev)
|
|
||||||
{
|
|
||||||
assert(pev != NULL && "FATAL ERROR: TimerListener object ptr cannot be NULL!");
|
|
||||||
return static_cast<timer_id_t>(
|
|
||||||
bx_pc_system.register_timer(pev, BochsController::onTimerTrigger, pev->getTimeout(),
|
|
||||||
false, 1/*start immediately*/, "Fail*: BochsController"/*name*/));
|
|
||||||
}
|
|
||||||
|
|
||||||
bool TimerListener::m_unregisterTimer(TimerListener* pev)
|
|
||||||
{
|
|
||||||
assert(pev != NULL && "FATAL ERROR: TimerListener object ptr cannot be NULL!");
|
|
||||||
bx_pc_system.deactivate_timer(static_cast<unsigned>(pev->getId()));
|
|
||||||
return bx_pc_system.unregisterTimer(static_cast<unsigned>(pev->getId()));
|
|
||||||
}
|
|
||||||
|
|
||||||
} // end-of-namespace: fail
|
|
||||||
@ -1,81 +0,0 @@
|
|||||||
#ifndef __BOCHS_LISTENER_HPP__
|
|
||||||
#define __BOCHS_LISTENER_HPP__
|
|
||||||
|
|
||||||
#include "../Listener.hpp"
|
|
||||||
|
|
||||||
namespace fail {
|
|
||||||
|
|
||||||
typedef GenericBPSingleListener BPSingleListener;
|
|
||||||
typedef GenericMemWriteListener MemWriteListener;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \class TimerListener
|
|
||||||
* Concrete TimerListener implementation of GenericTimerListener for the Bochs
|
|
||||||
* simulator backend. A (Fail)Bochs bug currently leads to the consequence that
|
|
||||||
* timers cannot be added/enabled at boot time (see BochsController.hpp for
|
|
||||||
* further details).
|
|
||||||
*/
|
|
||||||
class TimerListener : public GenericTimerListener {
|
|
||||||
private:
|
|
||||||
/**
|
|
||||||
* Registers a timer in the Bochs simulator. This timer triggers \a TimerListeners
|
|
||||||
* to inform the corresponding experiment-flow. Note that the number of timers
|
|
||||||
* (in Bochs) is limited to \c BX_MAX_TIMERS (defaults to 64 in v2.4.6).
|
|
||||||
* @param pli a pointer to the (experiment flow-) allocated TimerListener object,
|
|
||||||
* providing all required information to start the timer (e.g. the
|
|
||||||
* timeout value).
|
|
||||||
* @return The unique id of the timer recently created. This id is carried
|
|
||||||
* along with the TimerListener. On errors, -1 is returned (e.g. because
|
|
||||||
* a timer with the same id is already existing)
|
|
||||||
* @see TimerListener::getId()
|
|
||||||
*/
|
|
||||||
static timer_id_t m_registerTimer(TimerListener* pli);
|
|
||||||
/**
|
|
||||||
* Deletes a timer. No further events will be triggered by the timer.
|
|
||||||
* @param pli a pointer to the TimerListener-object to be removed
|
|
||||||
* @return \c true if the timer with \a pli->getId() has been removed
|
|
||||||
* successfully, \c false otherwise
|
|
||||||
*/
|
|
||||||
static bool m_unregisterTimer(TimerListener* pli);
|
|
||||||
public:
|
|
||||||
/**
|
|
||||||
* Creates a new timer event. This can be used to implement a timeout-
|
|
||||||
* mechanism in the experiment-flow. The timer starts automatically when
|
|
||||||
* added to FailBochs.
|
|
||||||
* @param timeout the time intervall in milliseconds (ms)
|
|
||||||
* @see SimulatorController::addListener
|
|
||||||
*/
|
|
||||||
TimerListener(unsigned timeout)
|
|
||||||
: GenericTimerListener(timeout) { }
|
|
||||||
~TimerListener() { onDeletion(); } // FIXME ~BaseListener should automatically dequeue a Listener, and then indirectly calls onDeletion. In the current implementation, no dequeueing happens at all.
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This method is called when an experiment flow adds a new event by
|
|
||||||
* calling \c simulator.addListener() or \c simulator.addListenerAndResume().
|
|
||||||
* More specifically, the event will be added to the event-list first
|
|
||||||
* (buffer-list, to be precise) and then this event handler is called.
|
|
||||||
* @return You should return \c true to continue and \c false to prevent
|
|
||||||
* the addition of the event \a pev, yielding an error in the
|
|
||||||
* experiment flow (i.e. -1 is returned).
|
|
||||||
*/
|
|
||||||
bool onAddition();
|
|
||||||
/**
|
|
||||||
* This method is called when an experiment flow removes an event from
|
|
||||||
* the event-management by calling \c removeListener(prev), \c clearListeners()
|
|
||||||
* or by deleting a complete flow (\c removeFlow). More specifically, this
|
|
||||||
* event handler will be called *before* the event is actually deleted.
|
|
||||||
*/
|
|
||||||
void onDeletion();
|
|
||||||
/**
|
|
||||||
* This method is called when an previously added event is about to be
|
|
||||||
* triggered by the simulator-backend. More specifically, this event handler
|
|
||||||
* will be called *before* the event is actually triggered, i.e. before the
|
|
||||||
* corresponding coroutine is toggled.
|
|
||||||
*/
|
|
||||||
void onTrigger() { onDeletion(); } // FIXME It should NOT be a Listener's job to call its own onDeletion. ListenerManager should call onDeletion when it deletes a Listener from a queue.
|
|
||||||
// TODO/FIXME: bei neuer impl. anpassen
|
|
||||||
};
|
|
||||||
|
|
||||||
} // end-of-namespace: fail
|
|
||||||
|
|
||||||
#endif // __BOCHS_LISTENER_HPP__
|
|
||||||
@ -35,18 +35,21 @@ void Gem5Controller::reboot()
|
|||||||
void Gem5Controller::onBreakpoint(address_t instrPtr, address_t address_space)
|
void Gem5Controller::onBreakpoint(address_t instrPtr, address_t address_space)
|
||||||
{
|
{
|
||||||
bool do_fire = false;
|
bool do_fire = false;
|
||||||
BPEvent tmp(instrPtr, address_space);
|
|
||||||
// Check for active breakpoint-events:
|
// Check for active breakpoint-events:
|
||||||
for (ListenerManager::iterator it = m_LstList.begin(); it != m_LstList.end(); it++) {
|
ListenerManager::iterator it = m_LstList.begin();
|
||||||
|
BPEvent tmp(instrPtr, address_space);
|
||||||
|
while (it != m_LstList.end()) {
|
||||||
BaseListener* pLi = *it;
|
BaseListener* pLi = *it;
|
||||||
BPListener* pBreakpt = dynamic_cast<BPListener*>(pLi);
|
BPListener* pBreakpt = dynamic_cast<BPListener*>(pLi);
|
||||||
if(pBreakpt != NULL && pBreakpt->isMatching(&tmp)) {
|
if (pBreakpt != NULL && pBreakpt->isMatching(&tmp)) {
|
||||||
pBreakpt->setTriggerInstructionPointer(instrPtr);
|
pBreakpt->setTriggerInstructionPointer(instrPtr);
|
||||||
it = m_LstList.makeActive(it);
|
it = m_LstList.makeActive(it);
|
||||||
do_fire = true;
|
do_fire = true;
|
||||||
// "it" has already been set to the next element (by calling makeActive()):
|
// "it" has already been set to the next element (by calling
|
||||||
|
// makeActive()):
|
||||||
continue; // -> skip iterator increment
|
continue; // -> skip iterator increment
|
||||||
}
|
}
|
||||||
|
it++;
|
||||||
}
|
}
|
||||||
if (do_fire)
|
if (do_fire)
|
||||||
m_LstList.triggerActiveListeners();
|
m_LstList.triggerActiveListeners();
|
||||||
|
|||||||
39
src/core/sal/gem5/Gem5Listener.ah
Normal file
39
src/core/sal/gem5/Gem5Listener.ah
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
#ifndef __GEM5LISTENER_AH__
|
||||||
|
#define __GEM5LISTENER_AH__
|
||||||
|
|
||||||
|
#include "config/VariantConfig.hpp"
|
||||||
|
#include "config/FailConfig.hpp"
|
||||||
|
|
||||||
|
#if defined(BUILD_GEM5) && defined(CONFIG_EVENT_BREAKPOINTS)
|
||||||
|
|
||||||
|
#include "Gem5PCEvent.hh"
|
||||||
|
#include "sim/system.hh"
|
||||||
|
|
||||||
|
aspect Gem5Listener
|
||||||
|
{
|
||||||
|
advice "fail::BPSingleListener" : slice class
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
Gem5PCEvent* m_Breakpoint;
|
||||||
|
public:
|
||||||
|
virtual bool onAddition()
|
||||||
|
{
|
||||||
|
System* sys = *System::systemList.begin();
|
||||||
|
m_Breakpoint = new Gem5PCEvent(&sys->pcEventQueue, this->m_WatchInstrPtr);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void onDeletion()
|
||||||
|
{
|
||||||
|
if(m_Breakpoint)
|
||||||
|
{
|
||||||
|
delete m_Breakpoint;
|
||||||
|
m_Breakpoint = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // BUILD_GEM5 && CONFIG_EVENT_BREAKPOINTS
|
||||||
|
#endif // __GEM5LISTENER_AH__
|
||||||
@ -1,33 +0,0 @@
|
|||||||
#include "Gem5Listener.hpp"
|
|
||||||
#include "../SALInst.hpp"
|
|
||||||
|
|
||||||
#include "sim/system.hh"
|
|
||||||
|
|
||||||
namespace fail {
|
|
||||||
|
|
||||||
Gem5BPSingleListener::Gem5BPSingleListener(address_t ip)
|
|
||||||
: GenericBPSingleListener(ip)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Gem5BPSingleListener::onAddition()
|
|
||||||
{
|
|
||||||
if(!m_Breakpoint)
|
|
||||||
{
|
|
||||||
System* sys = *System::systemList.begin();
|
|
||||||
m_Breakpoint = new Gem5PCEvent(&sys->pcEventQueue, this->m_WatchInstrPtr);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
Gem5BPSingleListener::~Gem5BPSingleListener()
|
|
||||||
{
|
|
||||||
if(m_Breakpoint)
|
|
||||||
{
|
|
||||||
delete m_Breakpoint;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} // end-of-namespace: fail
|
|
||||||
@ -1,25 +0,0 @@
|
|||||||
#ifndef __GEM5_LISTENER_HPP__
|
|
||||||
#define __GEM5_LISTENER_HPP__
|
|
||||||
|
|
||||||
#include "../Listener.hpp"
|
|
||||||
#include "Gem5PCEvent.hh"
|
|
||||||
|
|
||||||
namespace fail {
|
|
||||||
|
|
||||||
typedef GenericMemWriteListener MemWriteListener;
|
|
||||||
|
|
||||||
class Gem5BPSingleListener : public GenericBPSingleListener
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
Gem5BPSingleListener(address_t ip = 0);
|
|
||||||
virtual bool onAddition();
|
|
||||||
~Gem5BPSingleListener();
|
|
||||||
private:
|
|
||||||
Gem5PCEvent* m_Breakpoint;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef Gem5BPSingleListener BPSingleListener;
|
|
||||||
|
|
||||||
} // end-of-namespace: fail
|
|
||||||
|
|
||||||
#endif // __GEM5_LISTENER_HPP__
|
|
||||||
@ -8,13 +8,13 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include "../SimulatorController.hpp"
|
#include "../SimulatorController.hpp"
|
||||||
#include "../Listener.hpp"
|
|
||||||
|
|
||||||
struct CPUX86State;
|
struct CPUX86State;
|
||||||
|
|
||||||
namespace fail {
|
namespace fail {
|
||||||
|
|
||||||
class ExperimentFlow;
|
class ExperimentFlow;
|
||||||
|
class TimerListener;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \class QEMUController
|
* \class QEMUController
|
||||||
|
|||||||
60
src/core/sal/qemu/QEMUListener.ah
Normal file
60
src/core/sal/qemu/QEMUListener.ah
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
#ifndef __QEMULISTENER_AH__
|
||||||
|
#define __QEMULISTENER_AH__
|
||||||
|
|
||||||
|
#include "config/VariantConfig.hpp"
|
||||||
|
#include "config/FailConfig.hpp"
|
||||||
|
|
||||||
|
#if defined(BUILD_QEMU) && defined(CONFIG_EVENT_BREAKPOINTS)
|
||||||
|
|
||||||
|
#include "../SALInst.hpp"
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
#include "qemu/failqemu.h"
|
||||||
|
}
|
||||||
|
|
||||||
|
aspect QEMUListener
|
||||||
|
{
|
||||||
|
advice "fail::TimerListener" : slice class
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
bool onAddition()
|
||||||
|
{
|
||||||
|
//std::cout << "QEMUTimerListener::onAddition" << std::endl;
|
||||||
|
setId(failqemu_register_timer(getTimeout(), (void *)this));
|
||||||
|
//std::cout << "this = " << std::hex << (unsigned) this << std::endl;
|
||||||
|
//std::cout << "id = " << std::hex << (unsigned) getId() << std::endl;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void onDeletion()
|
||||||
|
{
|
||||||
|
//std::cout << "QEMUTimerListener::onDeletion" << std::endl;
|
||||||
|
//std::cout << "this = " << std::hex << (unsigned) this << std::endl;
|
||||||
|
//std::cout << "id = " << std::hex << (unsigned) getId() << std::endl;
|
||||||
|
failqemu_unregister_timer(getId());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
advice "fail::MemWriteListener" : slice class
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
bool onAddition()
|
||||||
|
{
|
||||||
|
//std::cout << "QEMUMemWriteListener::onAddition" << std::endl;
|
||||||
|
if (failqemu_add_watchpoint(simulator.m_cpuenv, m_WatchAddr, m_WatchWidth, 1) != 0) {
|
||||||
|
std::cout << "adding watchpoint failed!" << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void onDeletion()
|
||||||
|
{
|
||||||
|
//std::cout << "QEMUMemWriteListener::onDeletion" << std::endl;
|
||||||
|
failqemu_remove_watchpoint(simulator.m_cpuenv, m_WatchAddr, m_WatchWidth, 1);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // BUILD_QEMU && CONFIG_EVENT_BREAKPOINTS
|
||||||
|
#endif // __QEMULISTENER_AH__
|
||||||
@ -1,45 +0,0 @@
|
|||||||
#include <iostream>
|
|
||||||
|
|
||||||
#include "QEMUListener.hpp"
|
|
||||||
#include "../SALInst.hpp"
|
|
||||||
|
|
||||||
extern "C" {
|
|
||||||
#include "qemu/failqemu.h"
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace fail {
|
|
||||||
|
|
||||||
bool QEMUMemWriteListener::onAddition()
|
|
||||||
{
|
|
||||||
//std::cout << "QEMUMemWriteListener::onAddition" << std::endl;
|
|
||||||
if (failqemu_add_watchpoint(simulator.m_cpuenv, m_WatchAddr, m_WatchWidth, 1) != 0) {
|
|
||||||
std::cout << "adding watchpoint failed!" << std::endl;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void QEMUMemWriteListener::onDeletion()
|
|
||||||
{
|
|
||||||
//std::cout << "QEMUMemWriteListener::onDeletion" << std::endl;
|
|
||||||
failqemu_remove_watchpoint(simulator.m_cpuenv, m_WatchAddr, m_WatchWidth, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool QEMUTimerListener::onAddition()
|
|
||||||
{
|
|
||||||
//std::cout << "QEMUTimerListener::onAddition" << std::endl;
|
|
||||||
setId(failqemu_register_timer(getTimeout(), (void *)this));
|
|
||||||
//std::cout << "this = " << std::hex << (unsigned) this << std::endl;
|
|
||||||
//std::cout << "id = " << std::hex << (unsigned) getId() << std::endl;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void QEMUTimerListener::onDeletion()
|
|
||||||
{
|
|
||||||
//std::cout << "QEMUTimerListener::onDeletion" << std::endl;
|
|
||||||
//std::cout << "this = " << std::hex << (unsigned) this << std::endl;
|
|
||||||
//std::cout << "id = " << std::hex << (unsigned) getId() << std::endl;
|
|
||||||
failqemu_unregister_timer(getId());
|
|
||||||
}
|
|
||||||
|
|
||||||
} // end-of-namespace: fail
|
|
||||||
@ -1,40 +0,0 @@
|
|||||||
#ifndef __QEMU_LISTENER_HPP__
|
|
||||||
#define __QEMU_LISTENER_HPP__
|
|
||||||
|
|
||||||
#include "../Listener.hpp"
|
|
||||||
|
|
||||||
namespace fail {
|
|
||||||
|
|
||||||
typedef GenericBPSingleListener BPSingleListener;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \class QEMUTimerListener
|
|
||||||
* Concrete TimerListener implementation of GenericTimerListener for QEMU.
|
|
||||||
*/
|
|
||||||
class QEMUTimerListener : public GenericTimerListener {
|
|
||||||
private:
|
|
||||||
public:
|
|
||||||
QEMUTimerListener(unsigned timeout)
|
|
||||||
: GenericTimerListener(timeout) { }
|
|
||||||
~QEMUTimerListener() { onDeletion(); } // FIXME ~BaseListener should automatically dequeue a Listener, and then indirectly calls onDeletion. In the current implementation, no dequeueing happens at all.
|
|
||||||
bool onAddition();
|
|
||||||
void onDeletion();
|
|
||||||
};
|
|
||||||
typedef QEMUTimerListener TimerListener;
|
|
||||||
|
|
||||||
class QEMUMemWriteListener : public GenericMemWriteListener {
|
|
||||||
public:
|
|
||||||
QEMUMemWriteListener()
|
|
||||||
: GenericMemWriteListener() { }
|
|
||||||
QEMUMemWriteListener(address_t addr)
|
|
||||||
: GenericMemWriteListener(addr) { }
|
|
||||||
|
|
||||||
virtual bool onAddition();
|
|
||||||
virtual void onDeletion();
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef QEMUMemWriteListener MemWriteListener;
|
|
||||||
|
|
||||||
} // end-of-namespace: fail
|
|
||||||
|
|
||||||
#endif // __QEMU_LISTENER_HPP__
|
|
||||||
Reference in New Issue
Block a user