fast-watchpoints: implementation finished (and tested).
git-svn-id: https://www4.informatik.uni-erlangen.de/i4svn/danceos/trunk/devel/fail@1900 8c4709b5-6ec9-48aa-a5cd-a96041d1645a
This commit is contained in:
75
src/core/sal/perf/FastWatchpoints.ah
Normal file
75
src/core/sal/perf/FastWatchpoints.ah
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
#ifndef __FAST_WATCHPOINTS_AH__
|
||||||
|
#define __FAST_WATCHPOINTS_AH__
|
||||||
|
|
||||||
|
#include "config/FailConfig.hpp"
|
||||||
|
|
||||||
|
#ifdef CONFIG_FAST_WATCHPOINTS
|
||||||
|
|
||||||
|
#if !defined(CONFIG_EVENT_MEMREAD) && !defined(CONFIG_EVENT_MEMWRITE)
|
||||||
|
#error Watchpoint events (i.e. memory read or write accesses) are required for fast watchpoints!
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "WatchpointManagerSlice.ah" // slice class "WatchpointManagerSlice"
|
||||||
|
#include "WatchpointControllerSlice.ah" // slice class "WatchpointControllerSlice"
|
||||||
|
#include "../ListenerManager.hpp"
|
||||||
|
#include "../Listener.hpp"
|
||||||
|
#include "WatchpointBuffer.hpp"
|
||||||
|
#include "../SALInst.hpp"
|
||||||
|
|
||||||
|
// Warning: Do not import namespace using "using namespace"!
|
||||||
|
// (It may yields collisions due to woven aspect code.)
|
||||||
|
|
||||||
|
aspect FastWatchpoints {
|
||||||
|
|
||||||
|
// Refer to slice classes:
|
||||||
|
advice "fail::ListenerManager" : slice WatchpointManagerSlice;
|
||||||
|
advice "fail::SimulatorController" : slice WatchpointControllerSlice;
|
||||||
|
|
||||||
|
// These around-advices handle the (special) case where an experiment
|
||||||
|
// adds a listener object casted to the base type but actually has the
|
||||||
|
// MemRead- or MemWriteListener type.
|
||||||
|
advice execution("bool fail::SimulatorController::addListener(fail::BaseListener*)") : around ()
|
||||||
|
{
|
||||||
|
// Note: The logic to update the performance buffer-list is
|
||||||
|
// placed in the addListener() methods.
|
||||||
|
fail::MemAccessListener* pma = dynamic_cast<fail::MemAccessListener*>(*(tjp->arg<0>()));
|
||||||
|
// (MemRead- and MemWriteListener are derived classes of MemAccessListener!)
|
||||||
|
if (pma != NULL)
|
||||||
|
*(tjp->result()) = tjp->that()->addListener(pma);
|
||||||
|
else
|
||||||
|
tjp->proceed();
|
||||||
|
}
|
||||||
|
advice call("BaseListener* fail::SimulatorController::addListenerAndResume(fail::BaseListener*)") : around ()
|
||||||
|
{
|
||||||
|
// Note: The logic to update the performance buffer-list is
|
||||||
|
// placed in the addListenerAndResume methods.
|
||||||
|
fail::MemAccessListener* pma = dynamic_cast<fail::MemAccessListener*>(*(tjp->arg<0>()));
|
||||||
|
if (pma != NULL)
|
||||||
|
*(tjp->result()) = tjp->that()->addListenerAndResume(pma);
|
||||||
|
else
|
||||||
|
tjp->proceed();
|
||||||
|
}
|
||||||
|
|
||||||
|
// The event handler for employing watchpoint (aka memory access) events.
|
||||||
|
advice execution("void fail::%Controller::onMemoryAccess(...)") : around ()
|
||||||
|
{
|
||||||
|
// Note: "BPListener" is an abstract class anyway.
|
||||||
|
fail::ListenerManager& ref = tjp->target()->m_LstList;
|
||||||
|
|
||||||
|
#define TJPARG(i) *(tjp->arg<i>())
|
||||||
|
fail::MemAccessEvent tmp(TJPARG(0), TJPARG(1), TJPARG(3),
|
||||||
|
TJPARG(2) ? fail::MemAccessEvent::MEM_WRITE : fail::MemAccessEvent::MEM_READ);
|
||||||
|
#undef TJPARG
|
||||||
|
|
||||||
|
// Check for matching MemAccessListener:
|
||||||
|
fail::ResultSet& res = ref.getMemoryListeners().gather(&tmp);
|
||||||
|
while (res.hasMore())
|
||||||
|
ref.makeActive(ref.dereference(res.getNext()));
|
||||||
|
|
||||||
|
ref.triggerActiveListeners();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // CONFIG_FAST_WATCHPOINTS
|
||||||
|
|
||||||
|
#endif // __FAST_WATCHPOINTS_AH__
|
||||||
28
src/core/sal/perf/WatchpointBuffer.cc
Normal file
28
src/core/sal/perf/WatchpointBuffer.cc
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
#include "WatchpointBuffer.hpp"
|
||||||
|
#include "../Listener.hpp"
|
||||||
|
#include "../Event.hpp"
|
||||||
|
#include "../SALInst.hpp"
|
||||||
|
|
||||||
|
namespace fail {
|
||||||
|
|
||||||
|
// FIXME: Can not be inlined this way!
|
||||||
|
ResultSet& PerfVectorWatchpoints::gather(MemAccessEvent* pData)
|
||||||
|
{
|
||||||
|
static ResultSet res;
|
||||||
|
res.clear(); // FIXME: This should not free the memory of the underlying std::vector.
|
||||||
|
// Search for all indices of matching listener objects:
|
||||||
|
for(std::vector<index_t>::iterator it = m_BufList.begin(); it != m_BufList.end(); ++it) {
|
||||||
|
MemAccessListener* pmal = static_cast<MemAccessListener*>(simulator.dereference(*it));
|
||||||
|
if (pmal->isMatching(pData)) {
|
||||||
|
// Update trigger data:
|
||||||
|
pmal->setTriggerInstructionPointer(pData->getTriggerInstructionPointer());
|
||||||
|
pmal->setTriggerAddress(pData->getTriggerAddress());
|
||||||
|
pmal->setTriggerWidth(pData->getTriggerWidth());
|
||||||
|
pmal->setTriggerAccessType(pData->getTriggerAccessType());
|
||||||
|
res.add(*it);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // end-of-namespace: fail
|
||||||
20
src/core/sal/perf/WatchpointBuffer.hpp
Normal file
20
src/core/sal/perf/WatchpointBuffer.hpp
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
#ifndef __WATCHPOINT_BUFFER_HPP__
|
||||||
|
#define __WATCHPOINT_BUFFER_HPP__
|
||||||
|
|
||||||
|
#include "BufferInterface.hpp"
|
||||||
|
|
||||||
|
namespace fail {
|
||||||
|
|
||||||
|
class MemAccessEvent;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Concrete implementation of the PerfVector class for \c MemAccessListener.
|
||||||
|
*/
|
||||||
|
class PerfVectorWatchpoints : public DefPerfVector<MemAccessEvent> {
|
||||||
|
public:
|
||||||
|
ResultSet& gather(MemAccessEvent* pData);
|
||||||
|
};
|
||||||
|
|
||||||
|
} // end-of-namespace: fail
|
||||||
|
|
||||||
|
#endif // __WATCHPOINT_BUFFER_HPP__
|
||||||
40
src/core/sal/perf/WatchpointControllerSlice.ah
Normal file
40
src/core/sal/perf/WatchpointControllerSlice.ah
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
#ifndef __WATCHPOINT_CONTROLLER_SLICE_AH__
|
||||||
|
#define __WATCHPOINT_CONTROLLER_SLICE_AH__
|
||||||
|
|
||||||
|
#include "config/FailConfig.hpp"
|
||||||
|
|
||||||
|
#ifdef CONFIG_FAST_WATCHPOINTS
|
||||||
|
|
||||||
|
#include <cassert>
|
||||||
|
#include "../Listener.hpp"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \class WatchpointControllerSlice
|
||||||
|
*
|
||||||
|
* The slice class definition to be used with FastWatchpoints.ah.
|
||||||
|
* The members of this class will be sliced into the \c SimulatorController class.
|
||||||
|
*/
|
||||||
|
slice class WatchpointControllerSlice {
|
||||||
|
public:
|
||||||
|
bool addListener(fail::MemAccessListener* mli)
|
||||||
|
{
|
||||||
|
assert(mli != NULL && "FATAL ERROR: Argument (ptr) cannot be NULL!");
|
||||||
|
// Check whether we were called from onTrigger (see SimulatorController.cc@addListener).
|
||||||
|
fail::ExperimentFlow* pFlow = m_Flows.getCurrent();
|
||||||
|
if (pFlow == CoroutineManager::SIM_FLOW)
|
||||||
|
pFlow = mli->getParent();
|
||||||
|
m_LstList.add(mli, pFlow); // preserve type of mli
|
||||||
|
// Call the common postprocessing function:
|
||||||
|
if (!mli->onAddition()) { // If the return value signals "false"...,
|
||||||
|
m_LstList.remove(mli); // ...skip the addition
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
fail::BaseListener* addListenerAndResume(fail::MemAccessListener* mli)
|
||||||
|
{ addListener(mli); return resume(); }
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // CONFIG_FAST_WATCHPOINTS
|
||||||
|
|
||||||
|
#endif // __WATCHPOINT_CONTROLLER_SLICE_AH__
|
||||||
42
src/core/sal/perf/WatchpointManagerSlice.ah
Normal file
42
src/core/sal/perf/WatchpointManagerSlice.ah
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
#ifndef __WATCHPOINT_MANAGER_SLICE_AH__
|
||||||
|
#define __WATCHPOINT_MANAGER_SLICE_AH__
|
||||||
|
|
||||||
|
#include "config/FailConfig.hpp"
|
||||||
|
|
||||||
|
#ifdef CONFIG_FAST_WATCHPOINTS
|
||||||
|
|
||||||
|
#include <cassert>
|
||||||
|
#include "WatchpointBuffer.hpp"
|
||||||
|
#include "../Listener.hpp"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \class WatchpointManagerSlice
|
||||||
|
*
|
||||||
|
* The slice class definition to be used with FastWatchpoints.ah.
|
||||||
|
* The members of this class will be sliced into the \c ListenerManager class.
|
||||||
|
*/
|
||||||
|
slice class WatchpointManagerSlice {
|
||||||
|
private:
|
||||||
|
fail::PerfVectorWatchpoints m_MemListeners;
|
||||||
|
public:
|
||||||
|
fail::PerfVectorWatchpoints& getMemoryListeners() { return m_MemListeners; }
|
||||||
|
|
||||||
|
void add(fail::MemAccessListener* mli, fail::ExperimentFlow* flow)
|
||||||
|
{
|
||||||
|
assert(mli != NULL && "FATAL ERROR: Argument (ptr) cannot be NULL!");
|
||||||
|
mli->setParent(flow);
|
||||||
|
// (1) Add mli to the main buffer-list, ...
|
||||||
|
m_BufferList.push_back(mli);
|
||||||
|
// (2) ... update it's location (index) / performance-buffer (ptr) and ...
|
||||||
|
fail::index_t idx = m_BufferList.size()-1;
|
||||||
|
assert(m_BufferList[idx] == mli && "FATAL ERROR: Invalid index after push_back() unexpected!");
|
||||||
|
mli->setLocation(idx);
|
||||||
|
mli->setPerformanceBuffer(&m_MemListeners);
|
||||||
|
// (3) ... add this index to the m_SingleListeners vector.
|
||||||
|
m_MemListeners.add(idx);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // CONFIG_FAST_WATCHPOINTS
|
||||||
|
|
||||||
|
#endif // __WATCHPOINT_MANAGER_SLICE_AH__
|
||||||
Reference in New Issue
Block a user