Aspect-based implementation of fast breakpoints added (optional).

git-svn-id: https://www4.informatik.uni-erlangen.de/i4svn/danceos/trunk/devel/fail@1685 8c4709b5-6ec9-48aa-a5cd-a96041d1645a
This commit is contained in:
adrian
2012-09-25 10:10:02 +00:00
parent 0783931bf6
commit 0cb6b39490
17 changed files with 725 additions and 107 deletions

View File

@ -0,0 +1,157 @@
#ifndef __BREAKPOINT_BUFFER_HPP__
#define __BREAKPOINT_BUFFER_HPP__
#include "BufferInterface.hpp"
#include "../Listener.hpp"
#include <cassert>
#include <vector>
// TODOs:
// - Make these implementations even faster (see below: continue PerfVecSortedSingleBP).
// - The implementation of gather() (see below) in BreakpointBuffer.cc (not inlined in
// .hpp) avoids an include cycle. Unfortunately, this may cause a bad performance
// because gather() won't be inlined anymore! (The method is called quite often.)
namespace fail {
class BPEvent;
/**
* \class ResultSet
*
* Results (= indices of matching listeners) returned by the "gather"-method,
* see below. (This class can be seen as a "temporary fire-list".)
*/
class ResultSet {
std::vector<index_t> m_Res;
public:
ResultSet() { }
bool hasMore() const { return !m_Res.empty(); }
index_t getNext() { index_t idx = m_Res.back(); m_Res.pop_back(); return idx; }
void add(index_t idx) { m_Res.push_back(idx); }
size_t size() const { return m_Res.size(); }
void clear() { m_Res.clear(); }
};
/**
* Concrete implementation of the PerfBufferBase class for \c std::vector
* and \c BPSingleListener.
*/
class PerfVectorBreakpoints : public PerfBufferBase {
protected:
std::vector<index_t> m_BufList;
public:
void add(index_t idx) { m_BufList.push_back(idx); }
void remove(index_t idx)
{
for (std::vector<index_t>::iterator it = m_BufList.begin();
it != m_BufList.end(); ++it) {
if (*it == idx) {
m_BufList.erase(it);
break;
}
}
}
void clear() { m_BufList.clear(); }
size_t size() const { return m_BufList.size(); }
ResultSet& gather(BPEvent* pData);
};
/**
* \class PerfVecSortedSingleBP
*
* This class implements a faster mechanism to store BPSingleListener
* based on binary search on their corresponding instruction pointer.
*/
/*
class PerfVecSortedSingleBP : public PerfVectorBreakpoints {
private:
SimulatorController* m_Sim;
public:
PerfVecSortedSingleBP(SimulatorController* pSim) : m_Sim(pSim) { }
**
* TODO.
* @warning The method expects that \c idx is a valid index within the main
* buffer-list. Therefore we are allowed to call \c SimulatorController::dereference().
* Additionally, the indexed listener is epected to be of type \c BPListener*.
*
void add(index_t idx)
{
address_t watchIP = static_cast<BPSingleListener*>(m_Sim->dereference(idx))->getWatchInstructionPointer();
// Keep the indices sorted in ascending order regarding their instr. ptr.
// Search for the slot to insert the element (skip lower IPs):
int pos = binarySearch(m_BufList, 0, m_BufList.size()-1, idx);
assert(pos < 0 && "FATAL ERROR: Element already inserted!");
m_BufList.insert(it + (pos * (-1) + 1), idx);
// for (std::vector<index_t>::iterator it = m_BufList.begin(); it != m_BufList.end(); ++it) {
// if (static_cast<BPSingleListener*>(
// m_Sim->dereference(*it))->getWatchInstructionPointer() > watchIP) {
// m_BufList.insert(it, idx); // Insert the element before "it"
// break;
// }
}
}
static bool CompareInstrPtr(index_t arg1, index_t arg2, void* pStuff)
{
SimulatorController* pSim = static_cast<SimulatorController*>(pStuff);
#define VAL(idx) \
static_cast<BPSingleListener*>(pSim->dereference(idx))->getWatchInstructionPointer()
return (VAL(arg1) > VAL(arg2);
}
**
* Searches vec[first]...vec[last] for \c key. Returns the index of the matching
* element if it finds key, otherwise -(index where it could be inserted)-1.
* @param vec array of sorted (ascending) values.
* @param first lower subscript bound
* @param last upper subscript bound
* @param key value to search for
* @param pfnCmp a function pointer to a comparison function, returning \c true
* if the first argument is greater than the second, otherwise \c false.
* The last parameter equals the last parameter provided by calling this
* method. It can be used to pass additional data.
* @return index of key, or -insertion_position -1 if key is not in the array.
* This value can easily be transformed into the position to insert it.
*
int binarySearch(const std::vector<index_t>& vec, index_t first, index_t last, index_t key, bool (*pfnCmp)(index_t, index_t, void*), void* pStuff = NULL)
{
while (first <= last) {
int mid = (first + last) / 2; // compute mid point.
if (VAL(key) > VAL(vec[mid]))
first = mid + 1; // repeat search in top half.
else if (VAL(key) < VAL(vec[mid]))
last = mid - 1; // repeat search in bottom half.
else
return mid; // found it. return position
}
return -(first + 1); // failed to find key
}
void remove(index_t idx)
{
int pos = binarySearch(m_BufList, 0, m_BufList.size()-1, idx, CompareInstrPtr, m_Sim);
if (pos >= 0)
m_BufList.erase(m_BufList.begin() + pos);
}
ResultSet& gather(BPEvent* pData)
{
// TODO: Improve this by using binary search, too!
ResultSet res;
// Search for all indices of matching listener objects:
for(std::vector<index_t>::iterator it = m_BufList.begin(); it != m_BufList.end(); ++it) {
BPListener* pLi = static_cast<BPListener*>(simulator.dereference(*it));
if (pLi->isMatching(pData)) {
// Update trigger IPtr:
pLi->setTriggerInstructionPointer(pData->getTriggerInstructionPointer());
res.add(*it);
}
}
return res;
}
};
*/
} // end-of-namespace: fail
#endif // __BREAKPOINT_BUFFER_HPP__