ruby: get rid of PrioHeap and use STL

One big difference is that PrioHeap puts the smallest element at the
top of the heap, whereas stl puts the largest element on top, so I
changed all comparisons so they did the right thing.

Some usage of PrioHeap was simply changed to a std::vector, using sort
at the right time, other usage had me just use the various heap functions
in the stl.
This commit is contained in:
Nathan Binkert 2010-06-10 23:17:07 -07:00
parent 3df84fd8a0
commit dd133c7b24
23 changed files with 120 additions and 370 deletions

View file

@ -1,251 +0,0 @@
/*
* Copyright (c) 1999-2005 Mark D. Hill and David A. Wood
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer;
* redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution;
* neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef PRIOHEAP_H
#define PRIOHEAP_H
#include <cassert>
#include <iostream>
#include <vector>
typedef unsigned int HeapIndex;
template <class TYPE>
class PrioHeap {
public:
// Constructors
PrioHeap() { init(); }
// Destructor
//~PrioHeap();
// Public Methods
void init() { m_current_size = 0; }
int size() const { return m_current_size; }
void insert(const TYPE& key);
const TYPE& peekMin() const;
const TYPE& peekElement(int index) const;
TYPE extractMin();
void print(std::ostream& out) const;
private:
// Private Methods
bool verifyHeap() const;
bool verifyHeap(HeapIndex index) const;
void heapify();
// Private copy constructor and assignment operator
PrioHeap(const PrioHeap& obj);
PrioHeap<TYPE>& operator=(const PrioHeap& obj);
// Data Members (m_ prefix)
std::vector<TYPE> m_heap;
HeapIndex m_current_size;
};
// Output operator declaration
template <class TYPE>
std::ostream& operator<<(std::ostream& out, const PrioHeap<TYPE>& obj);
// ******************* Helper Functions *******************
inline
HeapIndex get_parent(HeapIndex i)
{
// return (i/2);
return (i>>1);
}
inline
HeapIndex get_right(HeapIndex i)
{
// return (2*i) + 1;
return (i<<1) | 1;
}
inline
HeapIndex get_left(HeapIndex i)
{
// return (2*i);
return (i<<1);
}
template <class TYPE>
void prio_heap_swap(TYPE& n1, TYPE& n2)
{
TYPE temp = n1;
n1 = n2;
n2 = temp;
}
// ******************* Definitions *******************
template <class TYPE>
void PrioHeap<TYPE>::insert(const TYPE& key)
{
int i;
// grow the vector size
m_current_size++;
m_heap.resize(m_current_size+1);
if(m_current_size == 1){ // HACK: need to initialize index 0 to avoid purify UMCs
m_heap[0] = key;
}
i = m_current_size;
while ((i > 1) && (node_less_then_eq(key, m_heap[get_parent(i)]))) {
m_heap[i] = m_heap[get_parent(i)];
i = get_parent(i);
}
m_heap[i] = key;
// assert(verifyHeap());
}
template <class TYPE>
const TYPE& PrioHeap<TYPE>::peekMin() const
{
assert(size() > 0);
return m_heap[1]; // 1, not 0, is the first element
}
template <class TYPE>
const TYPE& PrioHeap<TYPE>::peekElement(int index) const
{
assert(size() > 0);
return m_heap[index];
}
template <class TYPE>
TYPE PrioHeap<TYPE>::extractMin()
{
// TYPE temp;
assert(size() > 0);
TYPE temp = m_heap[1]; // 1, not 0, is the first element
m_heap[1] = m_heap[m_current_size];
m_current_size--;
heapify();
return temp;
}
template <class TYPE>
bool PrioHeap<TYPE>::verifyHeap() const
{
return verifyHeap(1);
}
template <class TYPE>
bool PrioHeap<TYPE>::verifyHeap(HeapIndex index) const
{
// Recursively verify that each node is <= its parent
if(index > m_current_size) {
return true;
} else if (index == 1) {
return
verifyHeap(get_right(index)) &&
verifyHeap(get_left(index));
} else if (node_less_then_eq(m_heap[get_parent(index)], m_heap[index])) {
return
verifyHeap(get_right(index)) &&
verifyHeap(get_left(index));
} else {
// Heap property violation
return false;
}
}
template <class TYPE>
void PrioHeap<TYPE>::heapify()
{
HeapIndex current_node = 1;
HeapIndex left, right, smallest;
// HeapIndex size = m_current_size;
while(true) {
left = get_left(current_node);
right = get_right(current_node);
// Find the smallest of the current node and children
if (left <= m_current_size && node_less_then_eq(m_heap[left], m_heap[current_node])) {
smallest = left;
} else {
smallest = current_node;
}
if (right <= m_current_size && node_less_then_eq(m_heap[right], m_heap[smallest])) {
smallest = right;
}
// Check to see if we are done
if (smallest == current_node) {
// We are done
break;
} else {
// Not done, heapify on the smallest child
prio_heap_swap(m_heap[current_node], m_heap[smallest]);
current_node = smallest;
}
}
// assert(verifyHeap());
}
template <class TYPE>
void PrioHeap<TYPE>::print(std::ostream& out) const
{
std::vector<TYPE> copyHeap(m_heap);
// sort copyHeap (inefficient, but will not be done often)
for(HeapIndex i=0;i<m_current_size; i++){
for(HeapIndex j=0; j< m_current_size; j++){
if(copyHeap[i].m_time < copyHeap[j].m_time){
prio_heap_swap(copyHeap[i], copyHeap[j]);
}
}
}
out << "[PrioHeap: ";
for(HeapIndex i=1; i<= m_current_size; i++){
out << copyHeap[i];
if(i != m_current_size-1){
out << ",";
}
out << " ";
}
out << "]";
}
// Output operator definition
template <class TYPE>
std::ostream& operator<<(std::ostream& out, const PrioHeap<TYPE>& obj)
{
obj.print(out);
out << std::flush;
return out;
}
#endif //PRIOHEAP_H

View file

@ -27,10 +27,12 @@
*/ */
#include "base/cprintf.hh" #include "base/cprintf.hh"
#include "base/stl_helpers.hh"
#include "mem/ruby/buffers/MessageBuffer.hh" #include "mem/ruby/buffers/MessageBuffer.hh"
#include "mem/ruby/system/System.hh" #include "mem/ruby/system/System.hh"
using namespace std; using namespace std;
using m5::stl_helpers::operator<<;
MessageBuffer::MessageBuffer(const string &name) MessageBuffer::MessageBuffer(const string &name)
{ {
@ -111,7 +113,7 @@ MessageBuffer::getMsgPtrCopy() const
{ {
assert(isReady()); assert(isReady());
return m_prio_heap.peekMin().m_msgptr->clone(); return m_prio_heap.front().m_msgptr->clone();
} }
const Message* const Message*
@ -124,7 +126,7 @@ MessageBuffer::peekAtHeadOfQueue() const
m_name, g_eventQueue_ptr->getTime())); m_name, g_eventQueue_ptr->getTime()));
assert(isReady()); assert(isReady());
const Message* msg_ptr = m_prio_heap.peekMin().m_msgptr.get(); const Message* msg_ptr = m_prio_heap.front().m_msgptr.get();
assert(msg_ptr); assert(msg_ptr);
DEBUG_EXPR(QUEUE_COMP, MedPrio, *msg_ptr); DEBUG_EXPR(QUEUE_COMP, MedPrio, *msg_ptr);
@ -223,7 +225,9 @@ MessageBuffer::enqueue(MsgPtr message, Time delta)
// Insert the message into the priority heap // Insert the message into the priority heap
MessageBufferNode thisNode(arrival_time, m_msg_counter, message); MessageBufferNode thisNode(arrival_time, m_msg_counter, message);
m_prio_heap.insert(thisNode); m_prio_heap.push_back(thisNode);
push_heap(m_prio_heap.begin(), m_prio_heap.end(),
greater<MessageBufferNode>());
DEBUG_NEWLINE(QUEUE_COMP, HighPrio); DEBUG_NEWLINE(QUEUE_COMP, HighPrio);
DEBUG_MSG(QUEUE_COMP, HighPrio, DEBUG_MSG(QUEUE_COMP, HighPrio,
@ -260,7 +264,7 @@ void
MessageBuffer::dequeue(MsgPtr& message) MessageBuffer::dequeue(MsgPtr& message)
{ {
DEBUG_MSG(QUEUE_COMP, MedPrio, "dequeue from " + m_name); DEBUG_MSG(QUEUE_COMP, MedPrio, "dequeue from " + m_name);
message = m_prio_heap.peekMin().m_msgptr; message = m_prio_heap.front().m_msgptr;
pop(); pop();
DEBUG_EXPR(QUEUE_COMP, MedPrio, message); DEBUG_EXPR(QUEUE_COMP, MedPrio, message);
@ -272,7 +276,7 @@ MessageBuffer::dequeue_getDelayCycles()
int delay_cycles = -1; // null value int delay_cycles = -1; // null value
// get MsgPtr of the message about to be dequeued // get MsgPtr of the message about to be dequeued
MsgPtr message = m_prio_heap.peekMin().m_msgptr; MsgPtr message = m_prio_heap.front().m_msgptr;
// get the delay cycles // get the delay cycles
delay_cycles = setAndReturnDelayCycles(message); delay_cycles = setAndReturnDelayCycles(message);
@ -288,7 +292,10 @@ MessageBuffer::pop()
{ {
DEBUG_MSG(QUEUE_COMP, MedPrio, "pop from " + m_name); DEBUG_MSG(QUEUE_COMP, MedPrio, "pop from " + m_name);
assert(isReady()); assert(isReady());
m_prio_heap.extractMin(); pop_heap(m_prio_heap.begin(), m_prio_heap.end(),
greater<MessageBufferNode>());
m_prio_heap.pop_back();
// record previous size and time so the current buffer size isn't // record previous size and time so the current buffer size isn't
// adjusted until next cycle // adjusted until next cycle
if (m_time_last_time_pop < g_eventQueue_ptr->getTime()) { if (m_time_last_time_pop < g_eventQueue_ptr->getTime()) {
@ -301,11 +308,7 @@ MessageBuffer::pop()
void void
MessageBuffer::clear() MessageBuffer::clear()
{ {
while(m_prio_heap.size() > 0){ m_prio_heap.clear();
m_prio_heap.extractMin();
}
ASSERT(m_prio_heap.size() == 0);
m_msg_counter = 0; m_msg_counter = 0;
m_size = 0; m_size = 0;
@ -320,9 +323,13 @@ MessageBuffer::recycle()
{ {
DEBUG_MSG(QUEUE_COMP, MedPrio, "recycling " + m_name); DEBUG_MSG(QUEUE_COMP, MedPrio, "recycling " + m_name);
assert(isReady()); assert(isReady());
MessageBufferNode node = m_prio_heap.extractMin(); MessageBufferNode node = m_prio_heap.front();
pop_heap(m_prio_heap.begin(), m_prio_heap.end(),
greater<MessageBufferNode>());
node.m_time = g_eventQueue_ptr->getTime() + m_recycle_latency; node.m_time = g_eventQueue_ptr->getTime() + m_recycle_latency;
m_prio_heap.insert(node); m_prio_heap.back() = node;
push_heap(m_prio_heap.begin(), m_prio_heap.end(),
greater<MessageBufferNode>());
g_eventQueue_ptr->scheduleEventAbsolute(m_consumer_ptr, g_eventQueue_ptr->scheduleEventAbsolute(m_consumer_ptr,
g_eventQueue_ptr->getTime() + m_recycle_latency); g_eventQueue_ptr->getTime() + m_recycle_latency);
} }
@ -353,7 +360,10 @@ MessageBuffer::print(ostream& out) const
if (m_consumer_ptr != NULL) { if (m_consumer_ptr != NULL) {
out << " consumer-yes "; out << " consumer-yes ";
} }
out << m_prio_heap << "] " << m_name << endl;
vector<MessageBufferNode> copy(m_prio_heap);
sort_heap(copy.begin(), copy.end(), greater<MessageBufferNode>());
out << copy << "] " << m_name << endl;
} }
void void

View file

@ -34,10 +34,12 @@
#ifndef __MEM_RUBY_BUFFERS_MESSAGEBUFFER_HH__ #ifndef __MEM_RUBY_BUFFERS_MESSAGEBUFFER_HH__
#define __MEM_RUBY_BUFFERS_MESSAGEBUFFER_HH__ #define __MEM_RUBY_BUFFERS_MESSAGEBUFFER_HH__
#include <algorithm>
#include <functional>
#include <iostream> #include <iostream>
#include <vector>
#include <string> #include <string>
#include "mem/gems_common/PrioHeap.hh"
#include "mem/ruby/buffers/MessageBufferNode.hh" #include "mem/ruby/buffers/MessageBufferNode.hh"
#include "mem/ruby/common/Consumer.hh" #include "mem/ruby/common/Consumer.hh"
#include "mem/ruby/common/Global.hh" #include "mem/ruby/common/Global.hh"
@ -61,13 +63,16 @@ class MessageBuffer
isReady() const isReady() const
{ {
return ((m_prio_heap.size() > 0) && return ((m_prio_heap.size() > 0) &&
(m_prio_heap.peekMin().m_time <= g_eventQueue_ptr->getTime())); (m_prio_heap.front().m_time <= g_eventQueue_ptr->getTime()));
} }
void void
delayHead() delayHead()
{ {
MessageBufferNode node = m_prio_heap.extractMin(); MessageBufferNode node = m_prio_heap.front();
std::pop_heap(m_prio_heap.begin(), m_prio_heap.end(),
std::greater<MessageBufferNode>());
m_prio_heap.pop_back();
enqueue(node.m_msgptr, 1); enqueue(node.m_msgptr, 1);
} }
@ -93,13 +98,13 @@ class MessageBuffer
peekMsgPtr() const peekMsgPtr() const
{ {
assert(isReady()); assert(isReady());
return m_prio_heap.peekMin().m_msgptr; return m_prio_heap.front().m_msgptr;
} }
const MsgPtr& const MsgPtr&
peekMsgPtrEvenIfNotReady() const peekMsgPtrEvenIfNotReady() const
{ {
return m_prio_heap.peekMin().m_msgptr; return m_prio_heap.front().m_msgptr;
} }
void enqueue(MsgPtr message) { enqueue(message, 1); } void enqueue(MsgPtr message) { enqueue(message, 1); }
@ -144,7 +149,7 @@ class MessageBuffer
// Data Members (m_ prefix) // Data Members (m_ prefix)
Consumer* m_consumer_ptr; // Consumer to signal a wakeup(), can be NULL Consumer* m_consumer_ptr; // Consumer to signal a wakeup(), can be NULL
PrioHeap<MessageBufferNode> m_prio_heap; std::vector<MessageBufferNode> m_prio_heap;
std::string m_name; std::string m_name;
int m_max_size; int m_max_size;

View file

@ -59,13 +59,13 @@ class MessageBufferNode
}; };
inline bool inline bool
node_less_then_eq(const MessageBufferNode& n1, const MessageBufferNode& n2) operator>(const MessageBufferNode& n1, const MessageBufferNode& n2)
{ {
if (n1.m_time == n2.m_time) { if (n1.m_time == n2.m_time) {
assert(n1.m_msg_counter != n2.m_msg_counter); assert(n1.m_msg_counter != n2.m_msg_counter);
return (n1.m_msg_counter <= n2.m_msg_counter); return n1.m_msg_counter > n2.m_msg_counter;
} else { } else {
return (n1.m_time <= n2.m_time); return n1.m_time > n2.m_time;
} }
} }

View file

@ -63,7 +63,6 @@
#include "sim/eventq.hh" #include "sim/eventq.hh"
class Consumer; class Consumer;
template <class TYPE> class PrioHeap;
class RubyEventQueueNode; class RubyEventQueueNode;
class RubyEventQueue : public EventManager class RubyEventQueue : public EventManager

View file

@ -37,7 +37,6 @@
#include "mem/ruby/network/garnet/NetworkHeader.hh" #include "mem/ruby/network/garnet/NetworkHeader.hh"
#include "mem/ruby/common/Consumer.hh" #include "mem/ruby/common/Consumer.hh"
#include "mem/ruby/network/garnet/fixed-pipeline/flitBuffer_d.hh" #include "mem/ruby/network/garnet/fixed-pipeline/flitBuffer_d.hh"
#include "mem/gems_common/PrioHeap.hh"
#include "mem/ruby/network/orion/power_bus.hh" #include "mem/ruby/network/orion/power_bus.hh"
class GarnetNetwork_d; class GarnetNetwork_d;

View file

@ -49,7 +49,7 @@ bool flitBuffer_d::isReady()
{ {
if(m_buffer.size() != 0 ) if(m_buffer.size() != 0 )
{ {
flit_d *t_flit = m_buffer.peekMin(); flit_d *t_flit = peekTopFlit();
if(t_flit->get_time() <= g_eventQueue_ptr->getTime()) if(t_flit->get_time() <= g_eventQueue_ptr->getTime())
return true; return true;
} }
@ -60,7 +60,7 @@ bool flitBuffer_d::isReadyForNext()
{ {
if(m_buffer.size() != 0 ) if(m_buffer.size() != 0 )
{ {
flit_d *t_flit = m_buffer.peekMin(); flit_d *t_flit = peekTopFlit();
if(t_flit->get_time() <= (g_eventQueue_ptr->getTime() + 1)) if(t_flit->get_time() <= (g_eventQueue_ptr->getTime() + 1))
return true; return true;
} }

View file

@ -31,10 +31,11 @@
#ifndef FLIT_BUFFER_D_H #ifndef FLIT_BUFFER_D_H
#define FLIT_BUFFER_D_H #define FLIT_BUFFER_D_H
#include <algorithm>
#include <iostream> #include <iostream>
#include <vector>
#include "mem/ruby/network/garnet/NetworkHeader.hh" #include "mem/ruby/network/garnet/NetworkHeader.hh"
#include "mem/gems_common/PrioHeap.hh"
#include "mem/ruby/network/garnet/fixed-pipeline/flit_d.hh" #include "mem/ruby/network/garnet/fixed-pipeline/flit_d.hh"
class flitBuffer_d { class flitBuffer_d {
@ -51,19 +52,23 @@ public:
inline flit_d* getTopFlit() inline flit_d* getTopFlit()
{ {
return m_buffer.extractMin(); flit_d *f = m_buffer.front();
std::pop_heap(m_buffer.begin(), m_buffer.end(), flit_d::greater);
m_buffer.pop_back();
return f;
} }
inline flit_d* peekTopFlit() inline flit_d* peekTopFlit()
{ {
return m_buffer.peekMin(); return m_buffer.front();
} }
inline void insert(flit_d *flt) inline void insert(flit_d *flt)
{ {
m_buffer.insert(flt); m_buffer.push_back(flt);
std::push_heap(m_buffer.begin(), m_buffer.end(), flit_d::greater);
} }
/**********Data Members*********/ /**********Data Members*********/
private: private:
PrioHeap <flit_d *> m_buffer; std::vector<flit_d *> m_buffer;
int size, max_size; int size, max_size;
}; };

View file

@ -115,6 +115,16 @@ public:
return src_delay; return src_delay;
} }
static bool
greater(flit_d* n1, flit_d* n2)
{
if (n1->get_time() == n2->get_time()) {
//ASSERT(n1->flit_id != n2->flit_id);
return (n1->get_id() > n2->get_id());
} else {
return (n1->get_time() > n2->get_time());
}
}
private: private:
/************Data Members*************/ /************Data Members*************/
@ -132,19 +142,6 @@ private:
}; };
inline extern bool node_less_then_eq(flit_d* n1, flit_d* n2);
inline extern
bool node_less_then_eq(flit_d* n1, flit_d* n2)
{
if (n1->get_time() == n2->get_time()) {
// ASSERT(n1->flit_id != n2->flit_id);
return (n1->get_id() <= n2->get_id());
} else {
return (n1->get_time() <= n2->get_time());
}
}
inline std::ostream& inline std::ostream&
operator<<(std::ostream& out, const flit_d& obj) operator<<(std::ostream& out, const flit_d& obj)
{ {

View file

@ -37,7 +37,6 @@
#include "mem/ruby/network/garnet/NetworkHeader.hh" #include "mem/ruby/network/garnet/NetworkHeader.hh"
#include "mem/ruby/network/garnet/flexible-pipeline/FlexibleConsumer.hh" #include "mem/ruby/network/garnet/flexible-pipeline/FlexibleConsumer.hh"
#include "mem/ruby/network/garnet/flexible-pipeline/flitBuffer.hh" #include "mem/ruby/network/garnet/flexible-pipeline/flitBuffer.hh"
#include "mem/gems_common/PrioHeap.hh"
#include "mem/ruby/common/NetDest.hh" #include "mem/ruby/common/NetDest.hh"
class GarnetNetwork; class GarnetNetwork;

View file

@ -37,7 +37,6 @@
#include "mem/ruby/network/garnet/NetworkHeader.hh" #include "mem/ruby/network/garnet/NetworkHeader.hh"
#include "mem/ruby/network/garnet/flexible-pipeline/GarnetNetwork.hh" #include "mem/ruby/network/garnet/flexible-pipeline/GarnetNetwork.hh"
#include "mem/ruby/network/garnet/flexible-pipeline/FlexibleConsumer.hh" #include "mem/ruby/network/garnet/flexible-pipeline/FlexibleConsumer.hh"
#include "mem/gems_common/PrioHeap.hh"
#include "mem/ruby/network/garnet/flexible-pipeline/NetworkLink.hh" #include "mem/ruby/network/garnet/flexible-pipeline/NetworkLink.hh"
#include "mem/ruby/common/NetDest.hh" #include "mem/ruby/common/NetDest.hh"
#include "mem/ruby/network/garnet/flexible-pipeline/flitBuffer.hh" #include "mem/ruby/network/garnet/flexible-pipeline/flitBuffer.hh"

View file

@ -52,6 +52,16 @@ public:
flit_type get_type(); flit_type get_type();
void print(std::ostream& out) const; void print(std::ostream& out) const;
static bool
greater(flit* n1, flit* n2)
{
if (n1->get_time() == n2->get_time())
//ASSERT(n1->flit_id != n2->flit_id);
return (n1->get_id() > n2->get_id());
else
return (n1->get_time() > n2->get_time());
}
private: private:
/************Data Members*************/ /************Data Members*************/
int m_id; int m_id;
@ -64,19 +74,6 @@ private:
}; };
inline extern bool node_less_then_eq(flit* n1, flit* n2);
inline extern
bool node_less_then_eq(flit* n1, flit* n2)
{
if (n1->get_time() == n2->get_time()) {
// ASSERT(n1->flit_id != n2->flit_id);
return (n1->get_id() <= n2->get_id());
} else {
return (n1->get_time() <= n2->get_time());
}
}
inline std::ostream& inline std::ostream&
operator<<(std::ostream& out, const flit& obj) operator<<(std::ostream& out, const flit& obj)
{ {

View file

@ -28,8 +28,12 @@
* Authors: Niket Agarwal * Authors: Niket Agarwal
*/ */
#include <algorithm>
#include "mem/ruby/network/garnet/flexible-pipeline/flitBuffer.hh" #include "mem/ruby/network/garnet/flexible-pipeline/flitBuffer.hh"
using namespace std;
flitBuffer::flitBuffer() flitBuffer::flitBuffer()
{ {
max_size = INFINITE_; max_size = INFINITE_;
@ -49,7 +53,7 @@ bool flitBuffer::isReady()
{ {
if(m_buffer.size() != 0 ) if(m_buffer.size() != 0 )
{ {
flit *t_flit = m_buffer.peekMin(); flit *t_flit = m_buffer.front();
if(t_flit->get_time() <= g_eventQueue_ptr->getTime()) if(t_flit->get_time() <= g_eventQueue_ptr->getTime())
return true; return true;
} }
@ -60,7 +64,7 @@ bool flitBuffer::isReadyForNext()
{ {
if(m_buffer.size() != 0 ) if(m_buffer.size() != 0 )
{ {
flit *t_flit = m_buffer.peekMin(); flit *t_flit = m_buffer.front();
if(t_flit->get_time() <= (g_eventQueue_ptr->getTime() + 1)) if(t_flit->get_time() <= (g_eventQueue_ptr->getTime() + 1))
return true; return true;
} }
@ -79,17 +83,21 @@ void flitBuffer::setMaxSize(int maximum)
flit* flitBuffer:: getTopFlit() flit* flitBuffer:: getTopFlit()
{ {
return m_buffer.extractMin(); flit *f = m_buffer.front();
pop_heap(m_buffer.begin(), m_buffer.end(), flit::greater);
m_buffer.pop_back();
return f;
} }
flit* flitBuffer::peekTopFlit() flit* flitBuffer::peekTopFlit()
{ {
return m_buffer.peekMin(); return m_buffer.front();
} }
void flitBuffer::insert(flit *flt) void flitBuffer::insert(flit *flt)
{ {
m_buffer.insert(flt); m_buffer.push_back(flt);
push_heap(m_buffer.begin(), m_buffer.end(), flit::greater);
} }
void flitBuffer::print(std::ostream& out) const void flitBuffer::print(std::ostream& out) const

View file

@ -32,9 +32,9 @@
#define FLIT_BUFFER_H #define FLIT_BUFFER_H
#include <iostream> #include <iostream>
#include <vector>
#include "mem/ruby/network/garnet/NetworkHeader.hh" #include "mem/ruby/network/garnet/NetworkHeader.hh"
#include "mem/gems_common/PrioHeap.hh"
#include "mem/ruby/network/garnet/flexible-pipeline/flit.hh" #include "mem/ruby/network/garnet/flexible-pipeline/flit.hh"
class flitBuffer { class flitBuffer {
@ -54,7 +54,7 @@ public:
/**********Data Members*********/ /**********Data Members*********/
private: private:
PrioHeap <flit *> m_buffer; std::vector<flit *> m_buffer;
int size, max_size; int size, max_size;
}; };

View file

@ -60,6 +60,13 @@ class AccessTraceForAddress
void print(std::ostream& out) const; void print(std::ostream& out) const;
static inline bool
less_equal(const AccessTraceForAddress* n1,
const AccessTraceForAddress* n2)
{
return n1->getTotal() <= n2->getTotal();
}
private: private:
Address m_addr; Address m_addr;
uint64 m_loads; uint64 m_loads;
@ -72,13 +79,6 @@ class AccessTraceForAddress
Histogram* m_histogram_ptr; Histogram* m_histogram_ptr;
}; };
inline bool
node_less_then_eq(const AccessTraceForAddress* n1,
const AccessTraceForAddress* n2)
{
return n1->getTotal() > n2->getTotal();
}
inline std::ostream& inline std::ostream&
operator<<(std::ostream& out, const AccessTraceForAddress& obj) operator<<(std::ostream& out, const AccessTraceForAddress& obj)
{ {

View file

@ -29,7 +29,6 @@
#include <vector> #include <vector>
#include "base/stl_helpers.hh" #include "base/stl_helpers.hh"
#include "mem/gems_common/PrioHeap.hh"
#include "mem/protocol/CacheMsg.hh" #include "mem/protocol/CacheMsg.hh"
#include "mem/ruby/profiler/AddressProfiler.hh" #include "mem/ruby/profiler/AddressProfiler.hh"
#include "mem/ruby/profiler/Profiler.hh" #include "mem/ruby/profiler/Profiler.hh"
@ -70,15 +69,16 @@ printSorted(ostream& out, int num_of_sequencers, const AddressMap &record_map,
const int records_printed = 100; const int records_printed = 100;
uint64 misses = 0; uint64 misses = 0;
PrioHeap<const AccessTraceForAddress*> heap; std::vector<const AccessTraceForAddress *> sorted;
AddressMap::const_iterator i = record_map.begin(); AddressMap::const_iterator i = record_map.begin();
AddressMap::const_iterator end = record_map.end(); AddressMap::const_iterator end = record_map.end();
for (; i != end; ++i) { for (; i != end; ++i) {
const AccessTraceForAddress* record = &i->second; const AccessTraceForAddress* record = &i->second;
misses += record->getTotal(); misses += record->getTotal();
heap.insert(record); sorted.push_back(record);
} }
sort(sorted.begin(), sorted.end(), AccessTraceForAddress::less_equal);
out << "Total_entries_" << description << ": " << record_map.size() out << "Total_entries_" << description << ": " << record_map.size()
<< endl; << endl;
@ -106,8 +106,9 @@ printSorted(ostream& out, int num_of_sequencers, const AddressMap &record_map,
} }
int counter = 0; int counter = 0;
while (heap.size() > 0 && counter < records_printed) { int max = sorted.size();
const AccessTraceForAddress* record = heap.extractMin(); while (counter < max && counter < records_printed) {
const AccessTraceForAddress* record = sorted[counter];
double percent = 100.0 * (record->getTotal() / double(misses)); double percent = 100.0 * (record->getTotal() / double(misses));
out << description << " | " << percent << " % " << *record << endl; out << description << " | " << percent << " % " << *record << endl;
all_records.add(record->getTotal()); all_records.add(record->getTotal());
@ -117,8 +118,8 @@ printSorted(ostream& out, int num_of_sequencers, const AddressMap &record_map,
m_touched_weighted_vec[record->getTouchedBy()] += record->getTotal(); m_touched_weighted_vec[record->getTouchedBy()] += record->getTotal();
} }
while (heap.size() > 0) { while (counter < max) {
const AccessTraceForAddress* record = heap.extractMin(); const AccessTraceForAddress* record = sorted[counter];
all_records.add(record->getTotal()); all_records.add(record->getTotal());
remaining_records.add(record->getTotal()); remaining_records.add(record->getTotal());
all_records_log.add(record->getTotal()); all_records_log.add(record->getTotal());

View file

@ -26,7 +26,6 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#include "mem/gems_common/PrioHeap.hh"
#include "mem/ruby/profiler/CacheProfiler.hh" #include "mem/ruby/profiler/CacheProfiler.hh"
#include "mem/ruby/profiler/Profiler.hh" #include "mem/ruby/profiler/Profiler.hh"
#include "mem/ruby/system/System.hh" #include "mem/ruby/system/System.hh"

View file

@ -50,7 +50,6 @@
#include "base/stl_helpers.hh" #include "base/stl_helpers.hh"
#include "base/str.hh" #include "base/str.hh"
#include "mem/gems_common/PrioHeap.hh"
#include "mem/protocol/CacheMsg.hh" #include "mem/protocol/CacheMsg.hh"
#include "mem/protocol/MachineType.hh" #include "mem/protocol/MachineType.hh"
#include "mem/protocol/Protocol.hh" #include "mem/protocol/Protocol.hh"

View file

@ -26,31 +26,21 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#include <algorithm>
#include "gzstream.hh" #include "gzstream.hh"
#include "mem/gems_common/PrioHeap.hh"
#include "mem/ruby/eventqueue/RubyEventQueue.hh" #include "mem/ruby/eventqueue/RubyEventQueue.hh"
#include "mem/ruby/recorder/CacheRecorder.hh" #include "mem/ruby/recorder/CacheRecorder.hh"
#include "mem/ruby/recorder/TraceRecord.hh"
using namespace std; using namespace std;
CacheRecorder::CacheRecorder()
{
m_records_ptr = new PrioHeap<TraceRecord>;
}
CacheRecorder::~CacheRecorder()
{
delete m_records_ptr;
}
void void
CacheRecorder::addRecord(Sequencer* sequencer, const Address& data_addr, CacheRecorder::addRecord(Sequencer* sequencer, const Address& data_addr,
const Address& pc_addr, RubyRequestType type, Time time) const Address& pc_addr, RubyRequestType type, Time time)
{ {
m_records_ptr-> TraceRecord rec(sequencer, data_addr, pc_addr, type, time);
insert(TraceRecord(sequencer, data_addr, pc_addr, type, time)); m_records.push_back(rec);
} }
int int
@ -62,13 +52,15 @@ CacheRecorder::dumpRecords(string filename)
return 0; return 0;
} }
int counter = 0; std::sort(m_records.begin(), m_records.end(), greater<TraceRecord>());
while (m_records_ptr->size() != 0) {
TraceRecord record = m_records_ptr->extractMin(); int size = m_records.size();
record.output(out); for (int i = 0; i < size; ++i)
counter++; m_records[i].output(out);
}
return counter; m_records.clear();
return size;
} }
void void

View file

@ -36,13 +36,14 @@
#include <iostream> #include <iostream>
#include <string> #include <string>
#include <vector>
#include "mem/protocol/CacheRequestType.hh" #include "mem/protocol/CacheRequestType.hh"
#include "mem/ruby/common/Global.hh" #include "mem/ruby/common/Global.hh"
#include "mem/ruby/libruby_internal.hh" #include "mem/ruby/libruby_internal.hh"
#include "mem/ruby/system/NodeID.hh" #include "mem/ruby/system/NodeID.hh"
#include "mem/ruby/recorder/TraceRecord.hh"
template <class TYPE> class PrioHeap;
class Address; class Address;
class TraceRecord; class TraceRecord;
class Sequencer; class Sequencer;
@ -50,9 +51,6 @@ class Sequencer;
class CacheRecorder class CacheRecorder
{ {
public: public:
CacheRecorder();
~CacheRecorder();
void addRecord(Sequencer* sequencer, const Address& data_addr, void addRecord(Sequencer* sequencer, const Address& data_addr,
const Address& pc_addr, RubyRequestType type, Time time); const Address& pc_addr, RubyRequestType type, Time time);
int dumpRecords(std::string filename); int dumpRecords(std::string filename);
@ -64,7 +62,7 @@ class CacheRecorder
CacheRecorder(const CacheRecorder& obj); CacheRecorder(const CacheRecorder& obj);
CacheRecorder& operator=(const CacheRecorder& obj); CacheRecorder& operator=(const CacheRecorder& obj);
PrioHeap<TraceRecord>* m_records_ptr; std::vector<TraceRecord> m_records;
}; };
inline std::ostream& inline std::ostream&

View file

@ -60,12 +60,6 @@ class TraceRecord
TraceRecord(const TraceRecord& obj); TraceRecord(const TraceRecord& obj);
TraceRecord& operator=(const TraceRecord& obj); TraceRecord& operator=(const TraceRecord& obj);
bool
node_less_then_eq(const TraceRecord& rec) const
{
return this->m_time <= rec.m_time;
}
void issueRequest() const; void issueRequest() const;
void print(std::ostream& out) const; void print(std::ostream& out) const;
@ -73,6 +67,8 @@ class TraceRecord
bool input(std::istream& in); bool input(std::istream& in);
private: private:
friend bool operator>(const TraceRecord& n1, const TraceRecord& n2);
Sequencer* m_sequencer_ptr; Sequencer* m_sequencer_ptr;
Time m_time; Time m_time;
Address m_data_address; Address m_data_address;
@ -81,9 +77,9 @@ class TraceRecord
}; };
inline bool inline bool
node_less_then_eq(const TraceRecord& n1, const TraceRecord& n2) operator>(const TraceRecord& n1, const TraceRecord& n2)
{ {
return n1.node_less_then_eq(n2); return n1.m_time > n2.m_time;
} }
inline std::ostream& inline std::ostream&

View file

@ -27,7 +27,6 @@
*/ */
#include "base/cprintf.hh" #include "base/cprintf.hh"
#include "mem/gems_common/PrioHeap.hh"
#include "mem/ruby/eventqueue/RubyEventQueue.hh" #include "mem/ruby/eventqueue/RubyEventQueue.hh"
#include "mem/ruby/recorder/TraceRecord.hh" #include "mem/ruby/recorder/TraceRecord.hh"
#include "mem/ruby/recorder/Tracer.hh" #include "mem/ruby/recorder/Tracer.hh"

View file

@ -46,7 +46,6 @@
#include "params/RubyTracer.hh" #include "params/RubyTracer.hh"
#include "sim/sim_object.hh" #include "sim/sim_object.hh"
template <class TYPE> class PrioHeap;
class Address; class Address;
class TraceRecord; class TraceRecord;
class Sequencer; class Sequencer;