ruby: style pass

This commit is contained in:
Nathan Binkert
2010-03-22 18:43:53 -07:00
parent 2620e08722
commit 5ab13e2deb
92 changed files with 7043 additions and 8245 deletions

View File

@@ -1,4 +1,3 @@
/* /*
* Copyright (c) 1999-2008 Mark D. Hill and David A. Wood * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
* All rights reserved. * All rights reserved.
@@ -27,10 +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.
*/ */
/*
* $Id$
*/
#include "mem/ruby/buffers/MessageBuffer.hh" #include "mem/ruby/buffers/MessageBuffer.hh"
#include "mem/ruby/system/System.hh" #include "mem/ruby/system/System.hh"
@@ -55,7 +50,8 @@ MessageBuffer::MessageBuffer(const string &name)
m_name = name; m_name = name;
} }
int MessageBuffer::getSize() int
MessageBuffer::getSize()
{ {
if (m_time_last_time_size_checked == g_eventQueue_ptr->getTime()) { if (m_time_last_time_size_checked == g_eventQueue_ptr->getTime()) {
return m_size_last_time_size_checked; return m_size_last_time_size_checked;
@@ -66,7 +62,8 @@ int MessageBuffer::getSize()
} }
} }
bool MessageBuffer::areNSlotsAvailable(int n) bool
MessageBuffer::areNSlotsAvailable(int n)
{ {
// fast path when message buffers have infinite size // fast path when message buffers have infinite size
@@ -75,15 +72,20 @@ bool MessageBuffer::areNSlotsAvailable(int n)
} }
// determine my correct size for the current cycle // determine my correct size for the current cycle
// pop operations shouldn't effect the network's visible size until next cycle, // pop operations shouldn't effect the network's visible size
// but enqueue operations effect the visible size immediately // until next cycle, but enqueue operations effect the visible
// size immediately
int current_size = max(m_size_at_cycle_start, m_size); int current_size = max(m_size_at_cycle_start, m_size);
if (m_time_last_time_pop < g_eventQueue_ptr->getTime()) { // no pops this cycle - m_size is correct if (m_time_last_time_pop < g_eventQueue_ptr->getTime()) {
// no pops this cycle - m_size is correct
current_size = m_size; current_size = m_size;
} else { } else {
if (m_time_last_time_enqueue < g_eventQueue_ptr->getTime()) { // no enqueues this cycle - m_size_at_cycle_start is correct if (m_time_last_time_enqueue < g_eventQueue_ptr->getTime()) {
// no enqueues this cycle - m_size_at_cycle_start is correct
current_size = m_size_at_cycle_start; current_size = m_size_at_cycle_start;
} else { // both pops and enqueues occured this cycle - add new enqueued msgs to m_size_at_cycle_start } else {
// both pops and enqueues occured this cycle - add new
// enqueued msgs to m_size_at_cycle_start
current_size = m_size_at_cycle_start+m_msgs_this_cycle; current_size = m_size_at_cycle_start+m_msgs_this_cycle;
} }
} }
@@ -101,7 +103,8 @@ bool MessageBuffer::areNSlotsAvailable(int n)
} }
} }
const MsgPtr MessageBuffer::getMsgPtrCopy() const const MsgPtr
MessageBuffer::getMsgPtrCopy() const
{ {
assert(isReady()); assert(isReady());
@@ -111,12 +114,14 @@ const MsgPtr MessageBuffer::getMsgPtrCopy() const
return temp_msg; return temp_msg;
} }
const Message* MessageBuffer::peekAtHeadOfQueue() const const Message*
MessageBuffer::peekAtHeadOfQueue() const
{ {
const Message* msg_ptr; const Message* msg_ptr;
DEBUG_NEWLINE(QUEUE_COMP, MedPrio); DEBUG_NEWLINE(QUEUE_COMP, MedPrio);
DEBUG_MSG(QUEUE_COMP,MedPrio,"Peeking at head of queue " + m_name + " time: " DEBUG_MSG(QUEUE_COMP, MedPrio,
"Peeking at head of queue " + m_name + " time: "
+ int_to_string(g_eventQueue_ptr->getTime()) + "."); + int_to_string(g_eventQueue_ptr->getTime()) + ".");
assert(isReady()); assert(isReady());
@@ -129,7 +134,8 @@ const Message* MessageBuffer::peekAtHeadOfQueue() const
} }
// FIXME - move me somewhere else // FIXME - move me somewhere else
int random_time() int
random_time()
{ {
int time = 1; int time = 1;
time += random() & 0x3; // [0...3] time += random() & 0x3; // [0...3]
@@ -139,7 +145,8 @@ int random_time()
return time; return time;
} }
void MessageBuffer::enqueue(const MsgPtr& message, Time delta) void
MessageBuffer::enqueue(const MsgPtr& message, Time delta)
{ {
DEBUG_NEWLINE(QUEUE_COMP, HighPrio); DEBUG_NEWLINE(QUEUE_COMP, HighPrio);
DEBUG_MSG(QUEUE_COMP, HighPrio, "enqueue " + m_name + " time: " DEBUG_MSG(QUEUE_COMP, HighPrio, "enqueue " + m_name + " time: "
@@ -175,7 +182,6 @@ void MessageBuffer::enqueue(const MsgPtr& message, Time delta)
if (!RubySystem::getRandomization() || (m_randomization == false)) { if (!RubySystem::getRandomization() || (m_randomization == false)) {
// No randomization // No randomization
arrival_time = current_time + delta; arrival_time = current_time + delta;
} else { } else {
// Randomization - ignore delta // Randomization - ignore delta
if (m_strict_fifo) { if (m_strict_fifo) {
@@ -191,9 +197,7 @@ void MessageBuffer::enqueue(const MsgPtr& message, Time delta)
// Check the arrival time // Check the arrival time
assert(arrival_time > current_time); assert(arrival_time > current_time);
if (m_strict_fifo) { if (m_strict_fifo) {
if (arrival_time >= m_last_arrival_time) { if (arrival_time < m_last_arrival_time) {
} else {
WARN_EXPR(*this); WARN_EXPR(*this);
WARN_EXPR(m_name); WARN_EXPR(m_name);
WARN_EXPR(current_time); WARN_EXPR(current_time);
@@ -206,11 +210,15 @@ void MessageBuffer::enqueue(const MsgPtr& message, Time delta)
m_last_arrival_time = arrival_time; m_last_arrival_time = arrival_time;
// compute the delay cycles and set enqueue time // compute the delay cycles and set enqueue time
Message* msg_ptr = NULL; Message* msg_ptr = message.mod_ref();
msg_ptr = message.mod_ref();
assert(msg_ptr != NULL); assert(msg_ptr != NULL);
assert(g_eventQueue_ptr->getTime() >= msg_ptr->getLastEnqueueTime()); // ensure we aren't dequeued early
msg_ptr->setDelayedCycles((g_eventQueue_ptr->getTime() - msg_ptr->getLastEnqueueTime())+msg_ptr->getDelayedCycles()); assert(g_eventQueue_ptr->getTime() >= msg_ptr->getLastEnqueueTime() &&
"ensure we aren't dequeued early");
msg_ptr->setDelayedCycles(g_eventQueue_ptr->getTime() -
msg_ptr->getLastEnqueueTime() +
msg_ptr->getDelayedCycles());
msg_ptr->setLastEnqueueTime(arrival_time); msg_ptr->setLastEnqueueTime(arrival_time);
// Insert the message into the priority heap // Insert the message into the priority heap
@@ -220,7 +228,8 @@ void MessageBuffer::enqueue(const MsgPtr& message, Time delta)
DEBUG_NEWLINE(QUEUE_COMP, HighPrio); DEBUG_NEWLINE(QUEUE_COMP, HighPrio);
DEBUG_MSG(QUEUE_COMP, HighPrio, "enqueue " + m_name DEBUG_MSG(QUEUE_COMP, HighPrio, "enqueue " + m_name
+ " with arrival_time " + int_to_string(arrival_time) + " with arrival_time " + int_to_string(arrival_time)
+ " cur_time: " + int_to_string(g_eventQueue_ptr->getTime()) + "."); + " cur_time: " + int_to_string(g_eventQueue_ptr->getTime())
+ ".");
DEBUG_EXPR(QUEUE_COMP, MedPrio, message); DEBUG_EXPR(QUEUE_COMP, MedPrio, message);
DEBUG_NEWLINE(QUEUE_COMP, HighPrio); DEBUG_NEWLINE(QUEUE_COMP, HighPrio);
@@ -234,7 +243,8 @@ void MessageBuffer::enqueue(const MsgPtr& message, Time delta)
} }
} }
int MessageBuffer::dequeue_getDelayCycles(MsgPtr& message) int
MessageBuffer::dequeue_getDelayCycles(MsgPtr& message)
{ {
int delay_cycles = -1; // null value int delay_cycles = -1; // null value
@@ -247,7 +257,8 @@ int MessageBuffer::dequeue_getDelayCycles(MsgPtr& message)
return delay_cycles; return delay_cycles;
} }
void MessageBuffer::dequeue(MsgPtr& message) void
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.peekMin().m_msgptr;
@@ -256,7 +267,8 @@ void MessageBuffer::dequeue(MsgPtr& message)
DEBUG_EXPR(QUEUE_COMP, MedPrio, message); DEBUG_EXPR(QUEUE_COMP, MedPrio, message);
} }
int MessageBuffer::dequeue_getDelayCycles() int
MessageBuffer::dequeue_getDelayCycles()
{ {
int delay_cycles = -1; // null value int delay_cycles = -1; // null value
@@ -272,12 +284,14 @@ int MessageBuffer::dequeue_getDelayCycles()
return delay_cycles; return delay_cycles;
} }
void MessageBuffer::pop() void
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(); m_prio_heap.extractMin();
// record previous size and time so the current buffer size isn't adjusted until next cycle // record previous size and time so the current buffer size isn't
// adjusted until next cycle
if (m_time_last_time_pop < g_eventQueue_ptr->getTime()) { if (m_time_last_time_pop < g_eventQueue_ptr->getTime()) {
m_size_at_cycle_start = m_size; m_size_at_cycle_start = m_size;
m_time_last_time_pop = g_eventQueue_ptr->getTime(); m_time_last_time_pop = g_eventQueue_ptr->getTime();
@@ -285,7 +299,8 @@ void MessageBuffer::pop()
m_size--; m_size--;
} }
void MessageBuffer::clear() void
MessageBuffer::clear()
{ {
while(m_prio_heap.size() > 0){ while(m_prio_heap.size() > 0){
m_prio_heap.extractMin(); m_prio_heap.extractMin();
@@ -301,17 +316,20 @@ void MessageBuffer::clear()
m_msgs_this_cycle = 0; m_msgs_this_cycle = 0;
} }
void MessageBuffer::recycle() void
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.extractMin();
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.insert(node);
g_eventQueue_ptr->scheduleEventAbsolute(m_consumer_ptr, g_eventQueue_ptr->getTime() + m_recycle_latency); g_eventQueue_ptr->scheduleEventAbsolute(m_consumer_ptr,
g_eventQueue_ptr->getTime() + m_recycle_latency);
} }
int MessageBuffer::setAndReturnDelayCycles(MsgPtr& message) int
MessageBuffer::setAndReturnDelayCycles(MsgPtr& message)
{ {
int delay_cycles = -1; // null value int delay_cycles = -1; // null value
@@ -321,14 +339,17 @@ int MessageBuffer::setAndReturnDelayCycles(MsgPtr& message)
// this function should only be called on dequeue // this function should only be called on dequeue
// ensure the msg hasn't been enqueued // ensure the msg hasn't been enqueued
assert(msg_ptr->getLastEnqueueTime() <= g_eventQueue_ptr->getTime()); assert(msg_ptr->getLastEnqueueTime() <= g_eventQueue_ptr->getTime());
msg_ptr->setDelayedCycles((g_eventQueue_ptr->getTime() - msg_ptr->getLastEnqueueTime())+msg_ptr->getDelayedCycles()); msg_ptr->setDelayedCycles(g_eventQueue_ptr->getTime() -
msg_ptr->getLastEnqueueTime() +
msg_ptr->getDelayedCycles());
delay_cycles = msg_ptr->getDelayedCycles(); delay_cycles = msg_ptr->getDelayedCycles();
assert(delay_cycles >= 0); assert(delay_cycles >= 0);
return delay_cycles; return delay_cycles;
} }
void MessageBuffer::print(ostream& out) const void
MessageBuffer::print(ostream& out) const
{ {
out << "[MessageBuffer: "; out << "[MessageBuffer: ";
if (m_consumer_ptr != NULL) { if (m_consumer_ptr != NULL) {
@@ -337,8 +358,9 @@ void MessageBuffer::print(ostream& out) const
out << m_prio_heap << "] " << m_name << endl; out << m_prio_heap << "] " << m_name << endl;
} }
void MessageBuffer::printStats(ostream& out) void
MessageBuffer::printStats(ostream& out)
{ {
out << "MessageBuffer: " << m_name << " stats - msgs:" << m_msg_counter << " full:" << m_not_avail_count << endl; out << "MessageBuffer: " << m_name << " stats - msgs:" << m_msg_counter
<< " full:" << m_not_avail_count << endl;
} }

View File

@@ -1,4 +1,3 @@
/* /*
* Copyright (c) 1999-2008 Mark D. Hill and David A. Wood * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
* All rights reserved. * All rights reserved.
@@ -28,46 +27,47 @@
*/ */
/* /*
* $Id$ * Unordered buffer of messages that can be inserted such
*
* Description: Unordered buffer of messages that can be inserted such
* that they can be dequeued after a given delta time has expired. * that they can be dequeued after a given delta time has expired.
*
*/ */
#ifndef MESSAGEBUFFER_H #ifndef __MEM_RUBY_BUFFERS_MESSAGEBUFFER_HH__
#define MESSAGEBUFFER_H #define __MEM_RUBY_BUFFERS_MESSAGEBUFFER_HH__
#include <iostream> #include <iostream>
#include <string> #include <string>
#include "mem/ruby/common/Global.hh"
#include "mem/ruby/buffers/MessageBufferNode.hh"
#include "mem/ruby/common/Consumer.hh"
#include "mem/ruby/eventqueue/RubyEventQueue.hh"
#include "mem/ruby/slicc_interface/Message.hh"
#include "mem/gems_common/PrioHeap.hh" #include "mem/gems_common/PrioHeap.hh"
#include "mem/gems_common/util.hh" #include "mem/gems_common/util.hh"
#include "mem/ruby/buffers/MessageBufferNode.hh"
#include "mem/ruby/common/Consumer.hh"
#include "mem/ruby/common/Global.hh"
#include "mem/ruby/eventqueue/RubyEventQueue.hh"
#include "mem/ruby/slicc_interface/Message.hh"
class MessageBuffer { class MessageBuffer
{
public: public:
// Constructors
MessageBuffer(const std::string &name = ""); MessageBuffer(const std::string &name = "");
// ~MessageBuffer()
// Public Methods
static void printConfig(std::ostream& out) {} static void printConfig(std::ostream& out) {}
void setRecycleLatency(int recycle_latency) { m_recycle_latency = recycle_latency; } void
setRecycleLatency(int recycle_latency)
{
m_recycle_latency = recycle_latency;
}
// TRUE if head of queue timestamp <= SystemTime // TRUE if head of queue timestamp <= SystemTime
bool isReady() const { bool
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.peekMin().m_time <= g_eventQueue_ptr->getTime()));
} }
void delayHead() { void
delayHead()
{
MessageBufferNode node = m_prio_heap.extractMin(); MessageBufferNode node = m_prio_heap.extractMin();
enqueue(node.m_msgptr, 1); enqueue(node.m_msgptr, 1);
} }
@@ -75,7 +75,12 @@ public:
bool areNSlotsAvailable(int n); bool areNSlotsAvailable(int n);
int getPriority() { return m_priority_rank; } int getPriority() { return m_priority_rank; }
void setPriority(int rank) { m_priority_rank = rank; } void setPriority(int rank) { m_priority_rank = rank; }
void setConsumer(Consumer* consumer_ptr) { ASSERT(m_consumer_ptr==NULL); m_consumer_ptr = consumer_ptr; } void setConsumer(Consumer* consumer_ptr)
{
ASSERT(m_consumer_ptr == NULL);
m_consumer_ptr = consumer_ptr;
}
void setDescription(const std::string& name) { m_name = name; } void setDescription(const std::string& name) { m_name = name; }
std::string getDescription() { return m_name;} std::string getDescription() { return m_name;}
@@ -84,13 +89,26 @@ public:
const Message* peekAtHeadOfQueue() const; const Message* peekAtHeadOfQueue() const;
const Message* peek() const { return peekAtHeadOfQueue(); } const Message* peek() const { return peekAtHeadOfQueue(); }
const MsgPtr getMsgPtrCopy() const; const MsgPtr getMsgPtrCopy() const;
const MsgPtr& peekMsgPtr() const { assert(isReady()); return m_prio_heap.peekMin().m_msgptr; }
const MsgPtr& peekMsgPtrEvenIfNotReady() const {return m_prio_heap.peekMin().m_msgptr; } const MsgPtr&
peekMsgPtr() const
{
assert(isReady());
return m_prio_heap.peekMin().m_msgptr;
}
const MsgPtr&
peekMsgPtrEvenIfNotReady() const
{
return m_prio_heap.peekMin().m_msgptr;
}
void enqueue(const MsgPtr& message) { enqueue(message, 1); } void enqueue(const MsgPtr& message) { enqueue(message, 1); }
void enqueue(const MsgPtr& message, Time delta); void enqueue(const MsgPtr& message, Time delta);
// void enqueueAbsolute(const MsgPtr& message, Time absolute_time); // void enqueueAbsolute(const MsgPtr& message, Time absolute_time);
int dequeue_getDelayCycles(MsgPtr& message); // returns delay cycles of the message int dequeue_getDelayCycles(MsgPtr& message); // returns delay
// cycles of the
// message
void dequeue(MsgPtr& message); void dequeue(MsgPtr& message);
int dequeue_getDelayCycles(); // returns delay cycles of the message int dequeue_getDelayCycles(); // returns delay cycles of the message
void dequeue() { pop(); } void dequeue() { pop(); }
@@ -98,7 +116,12 @@ public:
void recycle(); void recycle();
bool isEmpty() const { return m_prio_heap.size() == 0; } bool isEmpty() const { return m_prio_heap.size() == 0; }
void setOrdering(bool order) { m_strict_fifo = order; m_ordering_set = true; } void
setOrdering(bool order)
{
m_strict_fifo = order;
m_ordering_set = true;
}
void setSize(int size) { m_max_size = size; } void setSize(int size) { m_max_size = size; }
int getSize(); int getSize();
void setRandomization(bool random_flag) { m_randomization = random_flag; } void setRandomization(bool random_flag) { m_randomization = random_flag; }
@@ -131,13 +154,15 @@ private:
Time m_time_last_time_size_checked; Time m_time_last_time_size_checked;
int m_size_last_time_size_checked; int m_size_last_time_size_checked;
// variables used so enqueues appear to happen imediately, while pop happen the next cycle // variables used so enqueues appear to happen imediately, while
// pop happen the next cycle
Time m_time_last_time_enqueue; Time m_time_last_time_enqueue;
Time m_time_last_time_pop; Time m_time_last_time_pop;
int m_size_at_cycle_start; int m_size_at_cycle_start;
int m_msgs_this_cycle; int m_msgs_this_cycle;
int m_not_avail_count; // count the # of times I didn't have N slots available int m_not_avail_count; // count the # of times I didn't have N
// slots available
int m_msg_counter; int m_msg_counter;
int m_priority_rank; int m_priority_rank;
bool m_strict_fifo; bool m_strict_fifo;
@@ -146,19 +171,12 @@ private:
Time m_last_arrival_time; Time m_last_arrival_time;
}; };
// Output operator declaration inline std::ostream&
//template <class TYPE> operator<<(std::ostream& out, const MessageBuffer& obj)
std::ostream& operator<<(std::ostream& out, const MessageBuffer& obj);
// ******************* Definitions *******************
// Output operator definition
extern inline
std::ostream& operator<<(std::ostream& out, const MessageBuffer& obj)
{ {
obj.print(out); obj.print(out);
out << std::flush; out << std::flush;
return out; return out;
} }
#endif //MESSAGEBUFFER_H #endif // __MEM_RUBY_BUFFERS_MESSAGEBUFFER_HH__

View File

@@ -1,4 +1,3 @@
/* /*
* Copyright (c) 1999-2008 Mark D. Hill and David A. Wood * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
* All rights reserved. * All rights reserved.

View File

@@ -1,4 +1,3 @@
/* /*
* Copyright (c) 1999-2008 Mark D. Hill and David A. Wood * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
* All rights reserved. * All rights reserved.
@@ -27,48 +26,40 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#ifndef MESSAGEBUFFERNODE_H #ifndef __MEM_RUBY_BUFFERS_MESSAGEBUFFERNODE_HH__
#define MESSAGEBUFFERNODE_H #define __MEM_RUBY_BUFFERS_MESSAGEBUFFERNODE_HH__
#include <iostream> #include <iostream>
#include "mem/ruby/common/Global.hh" #include "mem/ruby/common/Global.hh"
#include "mem/ruby/slicc_interface/Message.hh" #include "mem/ruby/slicc_interface/Message.hh"
class MessageBufferNode { class MessageBufferNode
{
public: public:
// Constructors MessageBufferNode()
MessageBufferNode() { m_time = 0; m_msg_counter = 0; } {
m_time = 0;
m_msg_counter = 0;
}
MessageBufferNode(const Time& time, int counter, const MsgPtr& msgptr) MessageBufferNode(const Time& time, int counter, const MsgPtr& msgptr)
{ m_time = time; m_msgptr = msgptr; m_msg_counter = counter; } {
// Destructor m_time = time;
//~MessageBufferNode(); m_msgptr = msgptr;
m_msg_counter = counter;
}
// Public Methods
void print(std::ostream& out) const; void print(std::ostream& out) const;
private:
// Private Methods
// Default copy constructor and assignment operator
// MessageBufferNode(const MessageBufferNode& obj);
// MessageBufferNode& operator=(const MessageBufferNode& obj);
// Data Members (m_ prefix)
public: public:
Time m_time; Time m_time;
int m_msg_counter; // FIXME, should this be a 64-bit value? int m_msg_counter; // FIXME, should this be a 64-bit value?
MsgPtr m_msgptr; MsgPtr m_msgptr;
}; };
// Output operator declaration inline bool
std::ostream& operator<<(std::ostream& out, const MessageBufferNode& obj); node_less_then_eq(const MessageBufferNode& n1, const MessageBufferNode& n2)
// ******************* Definitions *******************
inline extern bool node_less_then_eq(const MessageBufferNode& n1, const MessageBufferNode& n2);
inline extern
bool node_less_then_eq(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);
@@ -78,13 +69,12 @@ bool node_less_then_eq(const MessageBufferNode& n1, const MessageBufferNode& n2)
} }
} }
// Output operator definition inline std::ostream&
extern inline operator<<(std::ostream& out, const MessageBufferNode& obj)
std::ostream& operator<<(std::ostream& out, const MessageBufferNode& obj)
{ {
obj.print(out); obj.print(out);
out << std::flush; out << std::flush;
return out; return out;
} }
#endif //MESSAGEBUFFERNODE_H #endif // __MEM_RUBY_BUFFERS_MESSAGEBUFFERNODE_HH__

View File

@@ -1,4 +1,3 @@
/* /*
* Copyright (c) 1999-2008 Mark D. Hill and David A. Wood * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
* All rights reserved. * All rights reserved.
@@ -27,13 +26,10 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
/*
* $Id$
*/
#include "mem/ruby/common/Address.hh" #include "mem/ruby/common/Address.hh"
void Address::output(ostream& out) const void
Address::output(ostream& out) const
{ {
// Note: this outputs addresses in the form "ffff", not "0xffff". // Note: this outputs addresses in the form "ffff", not "0xffff".
// This code should always be able to write out addresses in a // This code should always be able to write out addresses in a
@@ -42,7 +38,8 @@ void Address::output(ostream& out) const
out << hex << m_address << dec; out << hex << m_address << dec;
} }
void Address::input(istream& in) void
Address::input(istream& in)
{ {
// Note: this only works with addresses in the form "ffff", not // Note: this only works with addresses in the form "ffff", not
// "0xffff". This code should always be able to read in addresses // "0xffff". This code should always be able to read in addresses
@@ -56,7 +53,8 @@ Address::Address(const Address& obj)
m_address = obj.m_address; m_address = obj.m_address;
} }
Address& Address::operator=(const Address& obj) Address&
Address::operator=(const Address& obj)
{ {
if (this == &obj) { if (this == &obj) {
// assert(false); // assert(false);

View File

@@ -1,4 +1,3 @@
/* /*
* Copyright (c) 1999 Mark D. Hill and David A. Wood * Copyright (c) 1999 Mark D. Hill and David A. Wood
* All rights reserved. * All rights reserved.
@@ -27,20 +26,16 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
/* #ifndef __MEM_RUBY_COMMON_ADDRESS_HH__
* $Id$ #define __MEM_RUBY_COMMON_ADDRESS_HH__
*/
#ifndef ADDRESS_H
#define ADDRESS_H
#include <iomanip> #include <iomanip>
#include "base/hashmap.hh" #include "base/hashmap.hh"
#include "mem/ruby/common/Global.hh" #include "mem/ruby/common/Global.hh"
#include "mem/ruby/system/System.hh"
#include "mem/ruby/system/NodeID.hh"
#include "mem/ruby/system/MachineID.hh" #include "mem/ruby/system/MachineID.hh"
#include "mem/ruby/system/NodeID.hh"
#include "mem/ruby/system/System.hh"
const int ADDRESS_WIDTH = 64; // address width in bytes const int ADDRESS_WIDTH = 64; // address width in bytes
@@ -48,20 +43,21 @@ class Address;
typedef Address PhysAddress; typedef Address PhysAddress;
typedef Address VirtAddress; typedef Address VirtAddress;
class Address { class Address
{
public: public:
// Constructors Address()
Address() { m_address = 0; } : m_address(0)
explicit Address(physical_address_t address) { m_address = address; } { }
explicit
Address(physical_address_t address)
: m_address(address)
{ }
Address(const Address& obj); Address(const Address& obj);
Address& operator=(const Address& obj); Address& operator=(const Address& obj);
// Destructor
// ~Address();
// Public Methods
void setAddress(physical_address_t address) { m_address = address; } void setAddress(physical_address_t address) { m_address = address; }
physical_address_t getAddress() const {return m_address;} physical_address_t getAddress() const {return m_address;}
// selects bits inclusive // selects bits inclusive
@@ -70,17 +66,33 @@ public:
physical_address_t maskLowOrderBits(int number) const; physical_address_t maskLowOrderBits(int number) const;
physical_address_t maskHighOrderBits(int number) const; physical_address_t maskHighOrderBits(int number) const;
physical_address_t shiftLowOrderBits(int number) const; physical_address_t shiftLowOrderBits(int number) const;
physical_address_t getLineAddress() const
{ return bitSelect(RubySystem::getBlockSizeBits(), ADDRESS_WIDTH); }
physical_address_t getOffset() const
{ return bitSelect(0, RubySystem::getBlockSizeBits()-1); }
void makeLineAddress() { m_address = maskLowOrderBits(RubySystem::getBlockSizeBits()); } physical_address_t
getLineAddress() const
{
return bitSelect(RubySystem::getBlockSizeBits(), ADDRESS_WIDTH);
}
physical_address_t
getOffset() const
{
return bitSelect(0, RubySystem::getBlockSizeBits() - 1);
}
void
makeLineAddress()
{
m_address = maskLowOrderBits(RubySystem::getBlockSizeBits());
}
// returns the next stride address based on line address // returns the next stride address based on line address
void makeNextStrideAddress( int stride) { void
makeNextStrideAddress(int stride)
{
m_address = maskLowOrderBits(RubySystem::getBlockSizeBits()) m_address = maskLowOrderBits(RubySystem::getBlockSizeBits())
+ RubySystem::getBlockSizeBytes()*stride; + RubySystem::getBlockSizeBytes()*stride;
} }
int getBankSetNum() const; int getBankSetNum() const;
int getBankSetDist() const; int getBankSetDist() const;
@@ -90,65 +102,55 @@ public:
void output(ostream& out) const; void output(ostream& out) const;
void input(istream& in); void input(istream& in);
void setOffset( int offset ){ void
setOffset(int offset)
{
// first, zero out the offset bits // first, zero out the offset bits
makeLineAddress(); makeLineAddress();
m_address |= (physical_address_t) offset; m_address |= (physical_address_t) offset;
} }
private: private:
// Private Methods
// Private copy constructor and assignment operator
// Address(const Address& obj);
// Address& operator=(const Address& obj);
// Data Members (m_ prefix)
physical_address_t m_address; physical_address_t m_address;
}; };
inline inline Address
Address line_address(const Address& addr) { Address temp(addr); temp.makeLineAddress(); return temp; } line_address(const Address& addr)
{
Address temp(addr);
temp.makeLineAddress();
return temp;
}
// Output operator declaration inline bool
ostream& operator<<(ostream& out, const Address& obj); operator<(const Address& obj1, const Address& obj2)
// comparison operator declaration
bool operator==(const Address& obj1, const Address& obj2);
bool operator!=(const Address& obj1, const Address& obj2);
bool operator<(const Address& obj1, const Address& obj2);
/* Address& operator=(const physical_address_t address); */
inline
bool operator<(const Address& obj1, const Address& obj2)
{ {
return obj1.getAddress() < obj2.getAddress(); return obj1.getAddress() < obj2.getAddress();
} }
// ******************* Definitions ******************* inline ostream&
operator<<(ostream& out, const Address& obj)
// Output operator definition
inline
ostream& operator<<(ostream& out, const Address& obj)
{ {
obj.print(out); obj.print(out);
out << flush; out << flush;
return out; return out;
} }
inline inline bool
bool operator==(const Address& obj1, const Address& obj2) operator==(const Address& obj1, const Address& obj2)
{ {
return (obj1.getAddress() == obj2.getAddress()); return (obj1.getAddress() == obj2.getAddress());
} }
inline inline bool
bool operator!=(const Address& obj1, const Address& obj2) operator!=(const Address& obj1, const Address& obj2)
{ {
return (obj1.getAddress() != obj2.getAddress()); return (obj1.getAddress() != obj2.getAddress());
} }
inline // rips bits inclusive
physical_address_t Address::bitSelect(int small, int big) const // rips bits inclusive inline physical_address_t
Address::bitSelect(int small, int big) const
{ {
physical_address_t mask; physical_address_t mask;
assert((unsigned)big >= (unsigned)small); assert((unsigned)big >= (unsigned)small);
@@ -164,8 +166,8 @@ physical_address_t Address::bitSelect(int small, int big) const // rips bits inc
} }
// removes bits inclusive // removes bits inclusive
inline inline physical_address_t
physical_address_t Address::bitRemove(int small, int big) const Address::bitRemove(int small, int big) const
{ {
physical_address_t mask; physical_address_t mask;
assert((unsigned)big >= (unsigned)small); assert((unsigned)big >= (unsigned)small);
@@ -184,16 +186,14 @@ physical_address_t Address::bitRemove(int small, int big) const
mask = (physical_address_t)~0 << (big + 1); mask = (physical_address_t)~0 << (big + 1);
physical_address_t higher_bits = m_address & mask; physical_address_t higher_bits = m_address & mask;
//
// Shift the valid high bits over the removed section // Shift the valid high bits over the removed section
//
higher_bits = higher_bits >> (big - small); higher_bits = higher_bits >> (big - small);
return (higher_bits | lower_bits); return (higher_bits | lower_bits);
} }
} }
inline inline physical_address_t
physical_address_t Address::maskLowOrderBits(int number) const Address::maskLowOrderBits(int number) const
{ {
physical_address_t mask; physical_address_t mask;
@@ -205,8 +205,8 @@ physical_address_t Address::maskLowOrderBits(int number) const
return (m_address & mask); return (m_address & mask);
} }
inline inline physical_address_t
physical_address_t Address::maskHighOrderBits(int number) const Address::maskHighOrderBits(int number) const
{ {
physical_address_t mask; physical_address_t mask;
@@ -218,23 +218,29 @@ physical_address_t Address::maskHighOrderBits(int number) const
return (m_address & mask); return (m_address & mask);
} }
inline inline physical_address_t
physical_address_t Address::shiftLowOrderBits(int number) const Address::shiftLowOrderBits(int number) const
{ {
return (m_address >> number); return (m_address >> number);
} }
inline inline integer_t
integer_t Address::memoryModuleIndex() const Address::memoryModuleIndex() const
{ {
integer_t index = bitSelect(RubySystem::getBlockSizeBits()+RubySystem::getMemorySizeBits(), ADDRESS_WIDTH); integer_t index =
bitSelect(RubySystem::getBlockSizeBits() +
RubySystem::getMemorySizeBits(), ADDRESS_WIDTH);
assert (index >= 0); assert (index >= 0);
return index; return index;
// Index indexHighPortion = address.bitSelect(MEMORY_SIZE_BITS-1, PAGE_SIZE_BITS+NUMBER_OF_MEMORY_MODULE_BITS); // Index indexHighPortion =
// Index indexLowPortion = address.bitSelect(DATA_BLOCK_BITS, PAGE_SIZE_BITS-1); // address.bitSelect(MEMORY_SIZE_BITS - 1,
// PAGE_SIZE_BITS + NUMBER_OF_MEMORY_MODULE_BITS);
//Index index = indexLowPortion | (indexHighPortion << (PAGE_SIZE_BITS - DATA_BLOCK_BITS)); // Index indexLowPortion =
// address.bitSelect(DATA_BLOCK_BITS, PAGE_SIZE_BITS - 1);
//
// Index index = indexLowPortion |
// (indexHighPortion << (PAGE_SIZE_BITS - DATA_BLOCK_BITS));
/* /*
Round-robin mapping of addresses, at page size granularity Round-robin mapping of addresses, at page size granularity
@@ -252,26 +258,36 @@ ADDRESS_WIDTH MEMORY_SIZE_BITS PAGE_SIZE_BITS DATA_BLOCK_BITS
*/ */
} }
inline inline void
void Address::print(ostream& out) const Address::print(ostream& out) const
{ {
using namespace std; using namespace std;
out << "[" << hex << "0x" << m_address << "," << " line 0x" << maskLowOrderBits(RubySystem::getBlockSizeBits()) << dec << "]" << flush; out << "[" << hex << "0x" << m_address << "," << " line 0x"
<< maskLowOrderBits(RubySystem::getBlockSizeBits()) << dec << "]"
<< flush;
} }
class Address; class Address;
namespace __hash_namespace { namespace __hash_namespace {
template <> struct hash<Address> template <> struct hash<Address>
{ {
size_t operator()(const Address &s) const { return (size_t) s.getAddress(); } size_t
}; operator()(const Address &s) const
{
return (size_t)s.getAddress();
} }
};
/* namespace __hash_namespace */ }
namespace std { namespace std {
template <> struct equal_to<Address> template <> struct equal_to<Address>
{ {
bool operator()(const Address& s1, const Address& s2) const { return s1 == s2; } bool
}; operator()(const Address& s1, const Address& s2) const
{
return s1 == s2;
} }
};
/* namespace std */ }
#endif //ADDRESS_H #endif // __MEM_RUBY_COMMON_ADDRESS_HH__

View File

@@ -1,4 +1,3 @@
/* /*
* Copyright (c) 1999-2008 Mark D. Hill and David A. Wood * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
* All rights reserved. * All rights reserved.
@@ -28,16 +27,13 @@
*/ */
/* /*
* $Id$ * This is the virtual base class of all classes that can be the
* * targets of wakeup events. There is only two methods, wakeup() and
* Description: This is the virtual base class of all classes that can * print() and no data members.
* be the targets of wakeup events. There is only two methods,
* wakeup() and print() and no data members.
*
*/ */
#ifndef CONSUMER_H #ifndef __MEM_RUBY_COMMON_CONSUMER_HH__
#define CONSUMER_H #define __MEM_RUBY_COMMON_CONSUMER_HH__
#include <iostream> #include <iostream>
#include <set> #include <set>
@@ -47,68 +43,74 @@
class MessageBuffer; class MessageBuffer;
class Consumer { class Consumer
{
public: public:
// Constructors Consumer()
Consumer() { m_last_scheduled_wakeup = 0; m_last_wakeup = 0; } : m_last_scheduled_wakeup(0), m_last_wakeup(0)
{
}
// Destructor virtual
virtual ~Consumer() { } ~Consumer()
{ }
// Public Methods - pure virtual methods void
void triggerWakeup(RubyEventQueue * eventQueue) triggerWakeup(RubyEventQueue *eventQueue)
{ {
Time time = eventQueue->getTime(); Time time = eventQueue->getTime();
if (m_last_wakeup != time) { if (m_last_wakeup != time) {
wakeup(); m_last_wakeup = time; wakeup();
m_last_wakeup = time;
} }
} }
virtual void wakeup() = 0; virtual void wakeup() = 0;
virtual void print(std::ostream& out) const = 0; virtual void print(std::ostream& out) const = 0;
const Time& getLastScheduledWakeup() const
const Time&
getLastScheduledWakeup() const
{ {
return m_last_scheduled_wakeup; return m_last_scheduled_wakeup;
} }
void setLastScheduledWakeup(const Time& time)
void
setLastScheduledWakeup(const Time& time)
{ {
m_last_scheduled_wakeup = time; m_last_scheduled_wakeup = time;
} }
bool alreadyScheduled(Time time)
bool
alreadyScheduled(Time time)
{ {
return (m_scheduled_wakeups.find(time) != m_scheduled_wakeups.end()); return m_scheduled_wakeups.find(time) != m_scheduled_wakeups.end();
} }
void insertScheduledWakeupTime(Time time)
void
insertScheduledWakeupTime(Time time)
{ {
m_scheduled_wakeups.insert(time); m_scheduled_wakeups.insert(time);
} }
void removeScheduledWakeupTime(Time time)
void
removeScheduledWakeupTime(Time time)
{ {
assert(alreadyScheduled(time)); assert(alreadyScheduled(time));
m_scheduled_wakeups.erase(time); m_scheduled_wakeups.erase(time);
} }
private: private:
// Private Methods
// Data Members (m_ prefix)
Time m_last_scheduled_wakeup; Time m_last_scheduled_wakeup;
std::set<Time> m_scheduled_wakeups; std::set<Time> m_scheduled_wakeups;
Time m_last_wakeup; Time m_last_wakeup;
}; };
// Output operator declaration inline std::ostream&
inline extern operator<<(std::ostream& out, const Consumer& obj)
std::ostream& operator<<(std::ostream& out, const Consumer& obj);
// ******************* Definitions *******************
// Output operator definition
inline extern
std::ostream& operator<<(std::ostream& out, const Consumer& obj)
{ {
obj.print(out); obj.print(out);
out << std::flush; out << std::flush;
return out; return out;
} }
#endif //CONSUMER_H #endif // __MEM_RUBY_COMMON_CONSUMER_HH__

View File

@@ -1,4 +1,3 @@
/* /*
* Copyright (c) 1999-2008 Mark D. Hill and David A. Wood * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
* All rights reserved. * All rights reserved.
@@ -40,5 +39,6 @@ DataBlock::operator=(const DataBlock & obj)
memcpy(m_data, obj.m_data, RubySystem::getBlockSizeBytes()); memcpy(m_data, obj.m_data, RubySystem::getBlockSizeBytes());
m_alloc = true; m_alloc = true;
} }
return *this; return *this;
} }

View File

@@ -1,4 +1,3 @@
/* /*
* Copyright (c) 1999-2008 Mark D. Hill and David A. Wood * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
* All rights reserved. * All rights reserved.
@@ -27,36 +26,39 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#ifndef DATABLOCK_H #ifndef __MEM_RUBY_COMMON_DATABLOCK_HH__
#define DATABLOCK_H #define __MEM_RUBY_COMMON_DATABLOCK_HH__
#include <iomanip> #include <iomanip>
#include <iostream> #include <iostream>
#include "mem/gems_common/Vector.hh"
#include "mem/ruby/common/Global.hh" #include "mem/ruby/common/Global.hh"
#include "mem/ruby/system/System.hh" #include "mem/ruby/system/System.hh"
#include "mem/gems_common/Vector.hh"
class DataBlock { class DataBlock
{
public: public:
// Constructors DataBlock()
DataBlock() {alloc();} {
DataBlock(const DataBlock & cp) { alloc();
}
DataBlock(const DataBlock &cp)
{
m_data = new uint8[RubySystem::getBlockSizeBytes()]; m_data = new uint8[RubySystem::getBlockSizeBytes()];
memcpy(m_data, cp.m_data, RubySystem::getBlockSizeBytes()); memcpy(m_data, cp.m_data, RubySystem::getBlockSizeBytes());
m_alloc = true; m_alloc = true;
} }
// Destructor ~DataBlock()
~DataBlock() { {
if(m_alloc) { if (m_alloc)
delete [] m_data; delete [] m_data;
} }
}
DataBlock& operator=(const DataBlock& obj); DataBlock& operator=(const DataBlock& obj);
// Public Methods
void assign(uint8* data); void assign(uint8* data);
void clear(); void clear();
@@ -70,20 +72,12 @@ class DataBlock {
private: private:
void alloc(); void alloc();
// Data Members (m_ prefix)
uint8* m_data; uint8* m_data;
bool m_alloc; bool m_alloc;
}; };
// Output operator declaration inline void
std::ostream& operator<<(std::ostream& out, const DataBlock& obj); DataBlock::assign(uint8* data)
bool operator==(const DataBlock& obj1, const DataBlock& obj2);
// inline functions for speed
inline
void DataBlock::assign(uint8* data)
{ {
if (m_alloc) { if (m_alloc) {
delete [] m_data; delete [] m_data;
@@ -92,28 +86,28 @@ void DataBlock::assign(uint8* data)
m_alloc = false; m_alloc = false;
} }
inline inline void
void DataBlock::alloc() DataBlock::alloc()
{ {
m_data = new uint8[RubySystem::getBlockSizeBytes()]; m_data = new uint8[RubySystem::getBlockSizeBytes()];
m_alloc = true; m_alloc = true;
clear(); clear();
} }
inline inline void
void DataBlock::clear() DataBlock::clear()
{ {
memset(m_data, 0, RubySystem::getBlockSizeBytes()); memset(m_data, 0, RubySystem::getBlockSizeBytes());
} }
inline inline bool
bool DataBlock::equal(const DataBlock& obj) const DataBlock::equal(const DataBlock& obj) const
{ {
return !memcmp(m_data, obj.m_data, RubySystem::getBlockSizeBytes()); return !memcmp(m_data, obj.m_data, RubySystem::getBlockSizeBytes());
} }
inline inline void
void DataBlock::print(std::ostream& out) const DataBlock::print(std::ostream& out) const
{ {
using namespace std; using namespace std;
@@ -126,53 +120,50 @@ void DataBlock::print(std::ostream& out) const
out << dec << "]" << flush; out << dec << "]" << flush;
} }
inline inline uint8
uint8 DataBlock::getByte(int whichByte) const DataBlock::getByte(int whichByte) const
{ {
return m_data[whichByte]; return m_data[whichByte];
} }
inline inline const uint8*
const uint8* DataBlock::getData(int offset, int len) const DataBlock::getData(int offset, int len) const
{ {
assert(offset + len <= RubySystem::getBlockSizeBytes()); assert(offset + len <= RubySystem::getBlockSizeBytes());
return &m_data[offset]; return &m_data[offset];
} }
inline inline void
void DataBlock::setByte(int whichByte, uint8 data) DataBlock::setByte(int whichByte, uint8 data)
{ {
m_data[whichByte] = data; m_data[whichByte] = data;
} }
inline inline void
void DataBlock::setData(uint8* data, int offset, int len) DataBlock::setData(uint8* data, int offset, int len)
{ {
assert(offset + len <= RubySystem::getBlockSizeBytes()); assert(offset + len <= RubySystem::getBlockSizeBytes());
memcpy(&m_data[offset], data, len); memcpy(&m_data[offset], data, len);
} }
inline inline void
void DataBlock::copyPartial(const DataBlock & dblk, int offset, int len) DataBlock::copyPartial(const DataBlock & dblk, int offset, int len)
{ {
setData(&dblk.m_data[offset], offset, len); setData(&dblk.m_data[offset], offset, len);
} }
// ******************* Definitions ******************* inline std::ostream&
operator<<(std::ostream& out, const DataBlock& obj)
// Output operator definition
extern inline
std::ostream& operator<<(std::ostream& out, const DataBlock& obj)
{ {
obj.print(out); obj.print(out);
out << std::flush; out << std::flush;
return out; return out;
} }
extern inline inline bool
bool operator==(const DataBlock& obj1,const DataBlock& obj2) operator==(const DataBlock& obj1,const DataBlock& obj2)
{ {
return (obj1.equal(obj2)); return obj1.equal(obj2);
} }
#endif //DATABLOCK_H #endif // __MEM_RUBY_COMMON_DATABLOCK_HH__

View File

@@ -1,4 +1,3 @@
/* /*
* Copyright (c) 1999-2008 Mark D. Hill and David A. Wood * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
* All rights reserved. * All rights reserved.
@@ -27,19 +26,14 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
/*
* $Id$
*
*/
#include <fstream> #include <fstream>
#include <stdarg.h> #include <stdarg.h>
#include "mem/ruby/common/Global.hh"
#include "mem/ruby/common/Debug.hh"
#include "mem/ruby/eventqueue/RubyEventQueue.hh"
#include "mem/gems_common/util.hh"
#include "base/misc.hh" #include "base/misc.hh"
#include "mem/gems_common/util.hh"
#include "mem/ruby/common/Debug.hh"
#include "mem/ruby/common/Global.hh"
#include "mem/ruby/eventqueue/RubyEventQueue.hh"
using namespace std; using namespace std;
@@ -79,12 +73,14 @@ DebugComponentData debugComponents[] =
extern "C" void changeDebugVerbosity(VerbosityLevel vb); extern "C" void changeDebugVerbosity(VerbosityLevel vb);
extern "C" void changeDebugFilter(int filter); extern "C" void changeDebugFilter(int filter);
void changeDebugVerbosity(VerbosityLevel vb) void
changeDebugVerbosity(VerbosityLevel vb)
{ {
g_debug_ptr->setVerbosity(vb); g_debug_ptr->setVerbosity(vb);
} }
void changeDebugFilter(int filter) void
changeDebugFilter(int filter)
{ {
g_debug_ptr->setFilter(filter); g_debug_ptr->setFilter(filter);
} }
@@ -103,12 +99,12 @@ Debug::Debug(const Params *p)
g_debug_ptr = this; g_debug_ptr = this;
} }
Debug::~Debug() Debug::~Debug()
{ {
} }
void Debug::printVerbosity(ostream& out) const void
Debug::printVerbosity(ostream& out) const
{ {
switch (getVerbosity()) { switch (getVerbosity()) {
case No_Verb: case No_Verb:
@@ -128,7 +124,8 @@ void Debug::printVerbosity(ostream& out) const
} }
} }
bool Debug::validDebug(int module, PriorityLevel priority) bool
Debug::validDebug(int module, PriorityLevel priority)
{ {
int local_module = (1 << module); int local_module = (1 << module);
if (m_filter & local_module) { if (m_filter & local_module) {
@@ -137,82 +134,58 @@ bool Debug::validDebug(int module, PriorityLevel priority)
switch (m_verbosityLevel) { switch (m_verbosityLevel) {
case No_Verb: case No_Verb:
return false; return false;
break;
case Low_Verb: case Low_Verb:
if(priority == HighPrio) { return (priority == HighPrio);
return true;
}else{
return false;
}
break;
case Med_Verb: case Med_Verb:
if(priority == HighPrio || priority == MedPrio ) { return (priority == HighPrio || priority == MedPrio);
return true;
}else{
return false;
}
break;
case High_Verb: case High_Verb:
return true; return true;
break;
} }
} }
} }
return false; return false;
} }
void Debug::setDebugTime(Time t) void
Debug::setDebugTime(Time t)
{ {
m_starting_cycle = t; m_starting_cycle = t;
} }
void Debug::setVerbosity(VerbosityLevel vb) void
Debug::setVerbosity(VerbosityLevel vb)
{ {
m_verbosityLevel = vb; m_verbosityLevel = vb;
} }
void Debug::setFilter(int filter) void
Debug::setFilter(int filter)
{ {
m_filter = filter; m_filter = filter;
} }
bool Debug::checkVerbosityString(const char *verb_str) bool
Debug::setVerbosityString(const char *verb_str)
{ {
if (verb_str == NULL) { string verb = verb_str ? verb_str : "";
cerr << "Error: unrecognized verbosity (use none, low, med, high): NULL" << endl; if (verb == "none") {
return true; // error
} else if ( (string(verb_str) == "none") ||
(string(verb_str) == "low") ||
(string(verb_str) == "med") ||
(string(verb_str) == "high") ) {
return false;
}
cerr << "Error: unrecognized verbosity (use none, low, med, high): NULL" << endl;
return true; // error
}
bool Debug::setVerbosityString(const char *verb_str)
{
bool check_fails = checkVerbosityString(verb_str);
if (check_fails) {
return true; // error
}
if (string(verb_str) == "none") {
setVerbosity(No_Verb); setVerbosity(No_Verb);
} else if (string(verb_str) == "low") { } else if (verb == "low") {
setVerbosity(Low_Verb); setVerbosity(Low_Verb);
} else if (string(verb_str) == "med") { } else if (verb == "med") {
setVerbosity(Med_Verb); setVerbosity(Med_Verb);
} else if (string(verb_str) == "high") { } else if (verb == "high") {
setVerbosity(High_Verb); setVerbosity(High_Verb);
} else { } else {
cerr << "Error: unrecognized verbosity (use none, low, med, high): " << verb_str << endl; cerr << "Error: unrecognized verbosity (use none, low, med, high): "
<< verb << endl;
return true; // error return true; // error
} }
return false; // no error return false; // no error
} }
bool Debug::checkFilter(char ch) bool
Debug::checkFilter(char ch)
{ {
for (int i = 0; i < NUMBER_OF_COMPS; i++) { for (int i = 0; i < NUMBER_OF_COMPS; i++) {
// Look at all components to find a character match // Look at all components to find a character match
@@ -224,7 +197,8 @@ bool Debug::checkFilter(char ch)
return true; // error return true; // error
} }
bool Debug::checkFilterString(const char *filter_str) bool
Debug::checkFilterString(const char *filter_str)
{ {
if (filter_str == NULL) { if (filter_str == NULL) {
cerr << "Error: unrecognized component filter: NULL" << endl; cerr << "Error: unrecognized component filter: NULL" << endl;
@@ -232,17 +206,18 @@ bool Debug::checkFilterString(const char *filter_str)
} }
// check for default filter ("none") before reporting RUBY_DEBUG error // check for default filter ("none") before reporting RUBY_DEBUG error
if ( (string(filter_str) == "none") ) { if (string(filter_str) == "none") {
return false; // no error return false; // no error
} }
if (RUBY_DEBUG == false) { if (RUBY_DEBUG == false) {
cerr << "Error: User specified set of debug components, but the RUBY_DEBUG compile-time flag is false." << endl; cerr << "Error: User specified set of debug components, but the "
cerr << "Solution: Re-compile with RUBY_DEBUG set to true." << endl; << "RUBY_DEBUG compile-time flag is false." << endl
<< "Solution: Re-compile with RUBY_DEBUG set to true." << endl;
return true; // error return true; // error
} }
if ( (string(filter_str) == "all") ) { if (string(filter_str) == "all") {
return false; // no error return false; // no error
} }
@@ -256,7 +231,8 @@ bool Debug::checkFilterString(const char *filter_str)
return false; // no error return false; // no error
} }
bool Debug::setFilterString(const char *filter_str) bool
Debug::setFilterString(const char *filter_str)
{ {
if (checkFilterString(filter_str)) { if (checkFilterString(filter_str)) {
return true; // error return true; // error
@@ -278,13 +254,15 @@ bool Debug::setFilterString(const char *filter_str)
return false; // no error return false; // no error
} }
bool Debug::addFilter(char ch) bool
Debug::addFilter(char ch)
{ {
for (int i = 0; i < NUMBER_OF_COMPS; i++) { for (int i = 0; i < NUMBER_OF_COMPS; i++) {
// Look at all components to find a character match // Look at all components to find a character match
if (debugComponents[i].ch == ch) { if (debugComponents[i].ch == ch) {
// We found a match - update the filter bit mask // We found a match - update the filter bit mask
cout << " Debug: Adding to filter: '" << ch << "' (" << debugComponents[i].desc << ")" << endl; cout << " Debug: Adding to filter: '" << ch << "' ("
<< debugComponents[i].desc << ")" << endl;
m_filter |= (1 << i); m_filter |= (1 << i);
return false; // no error return false; // no error
} }
@@ -296,7 +274,8 @@ bool Debug::addFilter(char ch)
return true; // error return true; // error
} }
void Debug::clearFilter() void
Debug::clearFilter()
{ {
m_filter = 0; m_filter = 0;
} }
@@ -306,23 +285,26 @@ void Debug::allFilter()
m_filter = ~0; m_filter = ~0;
} }
void Debug::usageInstructions(void) void
Debug::usageInstructions(void)
{ {
cerr << "Debug components: " << endl; cerr << "Debug components: " << endl;
for (int i = 0; i < NUMBER_OF_COMPS; i++) { for (int i = 0; i < NUMBER_OF_COMPS; i++) {
cerr << " " << debugComponents[i].ch << ": " << debugComponents[i].desc << endl; cerr << " " << debugComponents[i].ch << ": "
<< debugComponents[i].desc << endl;
} }
} }
void Debug::print(ostream& out) const void
Debug::print(ostream& out) const
{ {
out << "[Debug]" << endl; out << "[Debug]" << endl;
} }
void Debug::setDebugOutputFile (const char * filename) void
Debug::setDebugOutputFile (const char *filename)
{ {
if ( (filename == NULL) || if (filename == NULL || !strcmp(filename, "none")) {
(!strcmp(filename, "none")) ) {
debug_cout_ptr = &cout; debug_cout_ptr = &cout;
return; return;
} }
@@ -333,13 +315,13 @@ void Debug::setDebugOutputFile (const char * filename)
m_fout.open(filename, ios::out); m_fout.open(filename, ios::out);
if (!m_fout.is_open()) { if (!m_fout.is_open()) {
cerr << "setDebugOutputFile: can't open file " << filename << endl; cerr << "setDebugOutputFile: can't open file " << filename << endl;
} } else {
else {
debug_cout_ptr = &m_fout; debug_cout_ptr = &m_fout;
} }
} }
void Debug::closeDebugOutputFile () void
Debug::closeDebugOutputFile ()
{ {
if (m_fout.is_open()) { if (m_fout.is_open()) {
m_fout.close (); m_fout.close ();
@@ -347,7 +329,8 @@ void Debug::closeDebugOutputFile ()
} }
} }
void Debug::debugMsg( const char *fmt, ... ) void
Debug::debugMsg( const char *fmt, ...)
{ {
va_list args; va_list args;
@@ -357,36 +340,6 @@ void Debug::debugMsg( const char *fmt, ... )
va_end(args); va_end(args);
} }
/*
void DEBUG_OUT( const char* fmt, ...) {
if (RUBY_DEBUG) {
cout << "Debug: in fn "
<< __PRETTY_FUNCTION__
<< " in " << __FILE__ << ":"
<< __LINE__ << ": ";
va_list args;
va_start(args, fmt);
vfprintf(stdout, fmt, args);
va_end(args);
}
}
void ERROR_OUT( const char* fmt, ... ) {
if (ERROR_MESSAGE_FLAG) {
cout << "error: in fn "
<< __PRETTY_FUNCTION__ << " in "
<< __FILE__ << ":"
<< __LINE__ << ": ";
va_list args;
va_start(args, fmt);
vfprintf(stdout, fmt, args);
va_end(args);
}
assert(0);
}
*/
Debug * Debug *
RubyDebugParams::create() RubyDebugParams::create()
{ {

View File

@@ -1,4 +1,3 @@
/* /*
* Copyright (c) 1999-2008 Mark D. Hill and David A. Wood * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
* All rights reserved. * All rights reserved.
@@ -27,12 +26,8 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
/* #ifndef __MEM_RUBY_COMMON_DEBUG_HH__
* $Id$ #define __MEM_RUBY_COMMON_DEBUG_HH__
*/
#ifndef __MEM_RUBY_DEBUG_HH__
#define __MEM_RUBY_DEBUG_HH__
#include <unistd.h> #include <unistd.h>
@@ -75,21 +70,17 @@ enum DebugComponents
enum PriorityLevel {HighPrio, MedPrio, LowPrio}; enum PriorityLevel {HighPrio, MedPrio, LowPrio};
enum VerbosityLevel {No_Verb, Low_Verb, Med_Verb, High_Verb}; enum VerbosityLevel {No_Verb, Low_Verb, Med_Verb, High_Verb};
class Debug : public SimObject { class Debug : public SimObject
{
public: public:
// Constructors
typedef RubyDebugParams Params; typedef RubyDebugParams Params;
Debug(const Params *p); Debug(const Params *p);
// Destructor
~Debug(); ~Debug();
// Public Methods
static bool getProtocolTrace() { return m_protocol_trace; } static bool getProtocolTrace() { return m_protocol_trace; }
bool validDebug(int module, PriorityLevel priority); bool validDebug(int module, PriorityLevel priority);
void printVerbosity(std::ostream& out) const; void printVerbosity(std::ostream& out) const;
void setVerbosity(VerbosityLevel vb); void setVerbosity(VerbosityLevel vb);
static bool checkVerbosityString(const char *verb_str);
bool setVerbosityString(const char *); bool setVerbosityString(const char *);
VerbosityLevel getVerbosity() const { return m_verbosityLevel; } VerbosityLevel getVerbosity() const { return m_verbosityLevel; }
void setFilter(int); void setFilter(int);
@@ -110,13 +101,10 @@ public:
static void usageInstructions(void); static void usageInstructions(void);
private: private:
// Private Methods
// Private copy constructor and assignment operator // Private copy constructor and assignment operator
Debug(const Debug& obj); Debug(const Debug& obj);
Debug& operator=(const Debug& obj); Debug& operator=(const Debug& obj);
// Data Members (m_ prefix)
static bool m_protocol_trace; static bool m_protocol_trace;
VerbosityLevel m_verbosityLevel; VerbosityLevel m_verbosityLevel;
int m_filter; int m_filter;
@@ -125,14 +113,8 @@ private:
std::fstream m_fout; std::fstream m_fout;
}; };
// Output operator declaration inline std::ostream&
std::ostream& operator<<(std::ostream& out, const Debug& obj); operator<<(std::ostream& out, const Debug& obj)
// ******************* Definitions *******************
// Output operator definition
extern inline
std::ostream& operator<<(std::ostream& out, const Debug& obj)
{ {
obj.print(out); obj.print(out);
out << std::flush; out << std::flush;
@@ -151,8 +133,7 @@ const bool ASSERT_FLAG = true;
#undef assert #undef assert
#define assert(EXPR) ASSERT(EXPR) #define assert(EXPR) ASSERT(EXPR)
#undef ASSERT #undef ASSERT
#define ASSERT(EXPR)\ #define ASSERT(EXPR) do { \
{\
using namespace std; \ using namespace std; \
if (ASSERT_FLAG) { \ if (ASSERT_FLAG) { \
if (!(EXPR)) { \ if (!(EXPR)) { \
@@ -167,21 +148,21 @@ const bool ASSERT_FLAG = true;
<< __FILE__ << ":" \ << __FILE__ << ":" \
<< __LINE__ << endl << flush; \ << __LINE__ << endl << flush; \
if (isatty(STDIN_FILENO)) { \ if (isatty(STDIN_FILENO)) { \
cerr << "At this point you might want to attach a debug to ";\ cerr << "At this point you might want to attach a debug to " \
cerr << "the running and get to the" << endl;\ << "the running and get to the" << endl \
cerr << "crash site; otherwise press enter to continue" << endl;\ << "crash site; otherwise press enter to continue" \
cerr << "PID: " << getpid();\ << endl \
cerr << endl << flush; \ << "PID: " << getpid() \
<< endl << flush; \
char c; \ char c; \
cin.get(c); \ cin.get(c); \
} \ } \
abort(); \ abort(); \
} \ } \
} \ } \
} } while (0)
#define BREAK(X)\ #define BREAK(X) do { \
{\
using namespace std; \ using namespace std; \
cerr << "breakpoint '" \ cerr << "breakpoint '" \
<< #X << "' reached at fn " \ << #X << "' reached at fn " \
@@ -195,10 +176,9 @@ const bool ASSERT_FLAG = true;
char c; \ char c; \
cin.get(c); \ cin.get(c); \
} \ } \
} } while (0)
#define ERROR_MSG(MESSAGE)\ #define ERROR_MSG(MESSAGE) do { \
{\
using namespace std; \ using namespace std; \
if (ERROR_MESSAGE_FLAG) { \ if (ERROR_MESSAGE_FLAG) { \
cerr << "Fatal Error: in fn " \ cerr << "Fatal Error: in fn " \
@@ -213,10 +193,9 @@ const bool ASSERT_FLAG = true;
<< (MESSAGE) << endl << flush; \ << (MESSAGE) << endl << flush; \
abort(); \ abort(); \
} \ } \
} } while(0)
#define WARN_MSG(MESSAGE)\ #define WARN_MSG(MESSAGE) do { \
{\
using namespace std; \ using namespace std; \
if (WARNING_MESSAGE_FLAG) { \ if (WARNING_MESSAGE_FLAG) { \
cerr << "Warning: in fn " \ cerr << "Warning: in fn " \
@@ -230,10 +209,9 @@ const bool ASSERT_FLAG = true;
<< __LINE__ << ": " \ << __LINE__ << ": " \
<< (MESSAGE) << endl << flush; \ << (MESSAGE) << endl << flush; \
} \ } \
} } while (0)
#define WARN_EXPR(EXPR)\ #define WARN_EXPR(EXPR) do { \
{\
using namespace std; \ using namespace std; \
if (WARNING_MESSAGE_FLAG) { \ if (WARNING_MESSAGE_FLAG) { \
cerr << "Warning: in fn " \ cerr << "Warning: in fn " \
@@ -249,10 +227,9 @@ const bool ASSERT_FLAG = true;
<< #EXPR << " is " \ << #EXPR << " is " \
<< (EXPR) << endl << flush; \ << (EXPR) << endl << flush; \
} \ } \
} } while (0)
#define DEBUG_MSG(module, priority, MESSAGE)\ #define DEBUG_MSG(module, priority, MESSAGE) do { \
{\
using namespace std; \ using namespace std; \
if (RUBY_DEBUG) { \ if (RUBY_DEBUG) { \
if (g_debug_ptr->validDebug(module, priority)) { \ if (g_debug_ptr->validDebug(module, priority)) { \
@@ -263,10 +240,9 @@ const bool ASSERT_FLAG = true;
<< (MESSAGE) << endl << flush; \ << (MESSAGE) << endl << flush; \
} \ } \
} \ } \
} } while (0)
#define DEBUG_EXPR(module, priority, EXPR)\ #define DEBUG_EXPR(module, priority, EXPR) do { \
{\
using namespace std; \ using namespace std; \
if (RUBY_DEBUG) { \ if (RUBY_DEBUG) { \
if (g_debug_ptr->validDebug(module, priority)) { \ if (g_debug_ptr->validDebug(module, priority)) { \
@@ -278,30 +254,27 @@ const bool ASSERT_FLAG = true;
<< (EXPR) << endl << flush; \ << (EXPR) << endl << flush; \
} \ } \
} \ } \
} } while (0)
#define DEBUG_NEWLINE(module, priority)\ #define DEBUG_NEWLINE(module, priority) do { \
{\
using namespace std; \ using namespace std; \
if (RUBY_DEBUG) { \ if (RUBY_DEBUG) { \
if (g_debug_ptr->validDebug(module, priority)) { \ if (g_debug_ptr->validDebug(module, priority)) { \
(* debug_cout_ptr) << endl << flush; \ (* debug_cout_ptr) << endl << flush; \
} \ } \
} \ } \
} } while (0)
#define DEBUG_SLICC(priority, LINE, MESSAGE)\ #define DEBUG_SLICC(priority, LINE, MESSAGE) do { \
{\
using namespace std; \ using namespace std; \
if (RUBY_DEBUG) { \ if (RUBY_DEBUG) { \
if (g_debug_ptr->validDebug(SLICC_COMP, priority)) { \ if (g_debug_ptr->validDebug(SLICC_COMP, priority)) { \
(* debug_cout_ptr) << (LINE) << (MESSAGE) << endl << flush; \ (* debug_cout_ptr) << (LINE) << (MESSAGE) << endl << flush; \
} \ } \
} \ } \
} } while (0)
#define DEBUG_OUT( rest... ) \ #define DEBUG_OUT(rest... ) do { \
{\
using namespace std; \ using namespace std; \
if (RUBY_DEBUG) { \ if (RUBY_DEBUG) { \
cout << "Debug: in fn " \ cout << "Debug: in fn " \
@@ -310,10 +283,9 @@ const bool ASSERT_FLAG = true;
<< __LINE__ << ": "; \ << __LINE__ << ": "; \
g_debug_ptr->debugMsg(rest); \ g_debug_ptr->debugMsg(rest); \
} \ } \
} } while (0)
#define ERROR_OUT( rest... ) \ #define ERROR_OUT( rest... ) do { \
{\
using namespace std; \ using namespace std; \
if (ERROR_MESSAGE_FLAG) { \ if (ERROR_MESSAGE_FLAG) { \
cout << "error: in fn " \ cout << "error: in fn " \
@@ -322,7 +294,7 @@ const bool ASSERT_FLAG = true;
<< __LINE__ << ": "; \ << __LINE__ << ": "; \
g_debug_ptr->debugMsg(rest); \ g_debug_ptr->debugMsg(rest); \
} \ } \
} } while (0)
#endif //DEBUG_H #endif // __MEM_RUBY_COMMON_DEBUG_HH__

View File

@@ -1,4 +1,3 @@
/* /*
* Copyright (c) 1999-2008 Mark D. Hill and David A. Wood * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
* All rights reserved. * All rights reserved.
@@ -27,6 +26,8 @@
* 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 <cassert>
#include "mem/ruby/common/Driver.hh" #include "mem/ruby/common/Driver.hh"
Driver::Driver() Driver::Driver()
@@ -37,3 +38,40 @@ Driver::Driver()
Driver::~Driver() Driver::~Driver()
{ {
} }
integer_t
Driver::getInstructionCount(int procID) const
{
return 1;
}
integer_t
Driver::getCycleCount(int procID) const
{
return 1;
}
void
Driver::addThreadDependency(int procID, int requestor_thread,
int conflict_thread) const
{
assert(0);
}
void
Driver::printDebug()
{}
integer_t
Driver::readPhysicalMemory(int procID, physical_address_t address, int len)
{
assert(0);
return 0;
}
void
Driver::writePhysicalMemory(int procID, physical_address_t address,
integer_t value, int len)
{
assert(0);
}

View File

@@ -1,4 +1,3 @@
/* /*
* Copyright (c) 1999-2008 Mark D. Hill and David A. Wood * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
* All rights reserved. * All rights reserved.
@@ -27,28 +26,18 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
/* #ifndef __MEM_RUBY_COMMON_DRIVER_HH__
* $Id$ #define __MEM_RUBY_COMMON_DRIVER_HH__
*
* Description:
*
*/
#ifndef DRIVER_H
#define DRIVER_H
#include "mem/ruby/common/Global.hh"
#include "mem/ruby/common/Consumer.hh"
#include "mem/ruby/system/NodeID.hh"
#include "mem/ruby/common/Address.hh" #include "mem/ruby/common/Address.hh"
#include "mem/ruby/common/Consumer.hh"
#include "mem/ruby/common/Global.hh"
#include "mem/ruby/system/NodeID.hh"
class Driver
class Driver { {
public: public:
// Constructors
Driver(); Driver();
// Destructor
virtual ~Driver() = 0; virtual ~Driver() = 0;
// Public Methods // Public Methods
@@ -56,29 +45,21 @@ public:
virtual void dmaHitCallback() {}; virtual void dmaHitCallback() {};
virtual void hitCallback(int64_t id) = 0; // Called by sequencer virtual void hitCallback(int64_t id) = 0; // Called by sequencer
virtual void go() = 0; virtual void go() = 0;
virtual integer_t getInstructionCount(int procID) const { return 1; } virtual integer_t getInstructionCount(int procID) const;
virtual integer_t getCycleCount(int procID) const { return 1; } virtual integer_t getCycleCount(int procID) const;
virtual void addThreadDependency(int procID, int requestor_thread, int conflict_thread) const { assert(0);} virtual void addThreadDependency(int procID, int requestor_thread,
virtual void printDebug(){} //called by Sequencer int conflict_thread) const;
virtual void printDebug(); //called by Sequencer
virtual void printStats(ostream& out) const = 0; virtual void printStats(ostream& out) const = 0;
virtual void clearStats() = 0; virtual void clearStats() = 0;
virtual void printConfig(ostream& out) const = 0; virtual void printConfig(ostream& out) const = 0;
virtual integer_t readPhysicalMemory(int procID, physical_address_t addr,
virtual integer_t readPhysicalMemory(int procID, physical_address_t address, int len);
int len ){ ASSERT(0); return 0; } virtual void writePhysicalMemory(int procID, physical_address_t addr,
integer_t value, int len);
virtual void writePhysicalMemory( int procID, physical_address_t address,
integer_t value, int len ){ ASSERT(0); }
protected:
// accessible by subclasses
private:
// inaccessible by subclasses
}; };
#endif //DRIVER_H #endif //__MEM_RUBY_COMMON_DRIVER_HH__

View File

@@ -1,4 +1,3 @@
/* /*
* Copyright (c) 1999-2008 Mark D. Hill and David A. Wood * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
* All rights reserved. * All rights reserved.

View File

@@ -1,4 +1,3 @@
/* /*
* Copyright (c) 1999-2008 Mark D. Hill and David A. Wood * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
* All rights reserved. * All rights reserved.
@@ -27,42 +26,8 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
/* #ifndef __MEM_RUBY_COMMON_GLOBAL_HH__
* $Id$ #define __MEM_RUBY_COMMON_GLOBAL_HH__
*
* */
#ifndef GLOBAL_H
#define GLOBAL_H
/*
#ifdef SINGLE_LEVEL_CACHE
const bool TWO_LEVEL_CACHE = false;
#define L1I_CACHE_MEMBER_VARIABLE m_L1Cache_cacheMemory_vec[m_version] // currently all protocols require L1s == nodes
#define L1D_CACHE_MEMBER_VARIABLE m_L1Cache_cacheMemory_vec[m_version] // "
#define L2_CACHE_MEMBER_VARIABLE m_L1Cache_cacheMemory_vec[m_version] // "
#define L2_CACHE_VARIABLE m_L1Cache_cacheMemory_vec
#else
const bool TWO_LEVEL_CACHE = true;
#ifdef IS_CMP
#define L1I_CACHE_MEMBER_VARIABLE m_L1Cache_L1IcacheMemory_vec[m_version]
#define L1D_CACHE_MEMBER_VARIABLE m_L1Cache_L1DcacheMemory_vec[m_version]
#define L2_CACHE_MEMBER_VARIABLE m_L2Cache_L2cacheMemory_vec[m_version]
#define L2_CACHE_VARIABLE m_L2Cache_L2cacheMemory_vec
#else // not IS_CMP
#define L1I_CACHE_MEMBER_VARIABLE m_L1Cache_L1IcacheMemory_vec[m_version] // currently all protocols require L1s == nodes
#define L1D_CACHE_MEMBER_VARIABLE m_L1Cache_L1DcacheMemory_vec[m_version] // "
// #define L2_CACHE_MEMBER_VARIABLE m_L1Cache_L2cacheMemory_vec[m_version] // old exclusive caches don't support L2s != nodes
#define L2_CACHE_MEMBER_VARIABLE m_L1Cache_cacheMemory_vec[m_version] // old exclusive caches don't support L2s != nodes
#define L2_CACHE_VARIABLE m_L1Cache_L2cacheMemory_vec
#endif // IS_CMP
#endif //SINGLE_LEVEL_CACHE
#define DIRECTORY_MEMBER_VARIABLE m_Directory_directory_vec[m_version]
#define TBE_TABLE_MEMBER_VARIABLE m_L1Cache_TBEs_vec[m_version]
*/
// external includes for all classes // external includes for all classes
#include "mem/ruby/common/TypeDefines.hh" #include "mem/ruby/common/TypeDefines.hh"
@@ -85,13 +50,12 @@ extern RubySystem* g_system_ptr;
class Debug; class Debug;
extern Debug* g_debug_ptr; extern Debug* g_debug_ptr;
// FIXME: this is required by the contructor of Directory_Entry.hh. It can't go // FIXME: this is required by the contructor of Directory_Entry.hh.
// into slicc_util.hh because it opens a can of ugly worms // It can't go into slicc_util.hh because it opens a can of ugly worms
extern inline int max_tokens() extern inline int max_tokens()
{ {
return 1024; return 1024;
} }
#endif // __MEM_RUBY_COMMON_GLOBAL_HH__
#endif //GLOBAL_H

View File

@@ -1,4 +1,3 @@
/* /*
* Copyright (c) 1999-2008 Mark D. Hill and David A. Wood * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
* All rights reserved. * All rights reserved.
@@ -27,14 +26,10 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
/*
* $Id$
*
*/
#include <cmath> #include <cmath>
#include <iomanip> #include <iomanip>
#include "base/intmath.hh"
#include "mem/ruby/common/Histogram.hh" #include "mem/ruby/common/Histogram.hh"
using namespace std; using namespace std;
@@ -50,13 +45,15 @@ Histogram::~Histogram()
{ {
} }
void Histogram::clear(int binsize, int bins) void
Histogram::clear(int binsize, int bins)
{ {
m_binsize = binsize; m_binsize = binsize;
clear(bins); clear(bins);
} }
void Histogram::clear(int bins) void
Histogram::clear(int bins)
{ {
m_bins = bins; m_bins = bins;
m_largest_bin = 0; m_largest_bin = 0;
@@ -73,7 +70,8 @@ void Histogram::clear(int bins)
} }
void Histogram::add(int64 value) void
Histogram::add(int64 value)
{ {
assert(value >= 0); assert(value >= 0);
m_max = max(m_max, value); m_max = max(m_max, value);
@@ -88,7 +86,7 @@ void Histogram::add(int64 value)
if (value == 0) { if (value == 0) {
index = 0; index = 0;
} else { } else {
index = int(log(double(value))/log(2.0))+1; index = floorLog2(value) + 1;
if (index >= m_data.size()) { if (index >= m_data.size()) {
index = m_data.size() - 1; index = m_data.size() - 1;
} }
@@ -111,7 +109,8 @@ void Histogram::add(int64 value)
m_largest_bin = max(m_largest_bin, index); m_largest_bin = max(m_largest_bin, index);
} }
void Histogram::add(const Histogram& hist) void
Histogram::add(const Histogram& hist)
{ {
assert(hist.getBins() == m_bins); assert(hist.getBins() == m_bins);
assert(hist.getBinSize() == -1); // assume log histogram assert(hist.getBinSize() == -1); // assume log histogram
@@ -126,29 +125,31 @@ void Histogram::add(const Histogram& hist)
add(1<<(i-1)); // account for the + 1 index add(1<<(i-1)); // account for the + 1 index
} }
} }
} }
// Computation of standard deviation of samples a1, a2, ... aN // Computation of standard deviation of samples a1, a2, ... aN
// variance = [SUM {ai^2} - (SUM {ai})^2/N]/(N-1) // variance = [SUM {ai^2} - (SUM {ai})^2/N]/(N-1)
// std deviation equals square root of variance // std deviation equals square root of variance
double Histogram::getStandardDeviation() const double
Histogram::getStandardDeviation() const
{ {
double variance; if (m_count <= 1)
if(m_count > 1){ return 0.0;
variance = (double)(m_sumSquaredSamples - m_sumSamples*m_sumSamples/m_count)/(m_count - 1);
} else { double variance =
return 0; (double)(m_sumSquaredSamples - m_sumSamples * m_sumSamples / m_count)
} / (m_count - 1);
return sqrt(variance); return sqrt(variance);
} }
void Histogram::print(ostream& out) const void
Histogram::print(ostream& out) const
{ {
printWithMultiplier(out, 1.0); printWithMultiplier(out, 1.0);
} }
void Histogram::printPercent(ostream& out) const void
Histogram::printPercent(ostream& out) const
{ {
if (m_count == 0) { if (m_count == 0) {
printWithMultiplier(out, 0.0); printWithMultiplier(out, 0.0);
@@ -157,7 +158,8 @@ void Histogram::printPercent(ostream& out) const
} }
} }
void Histogram::printWithMultiplier(ostream& out, double multiplier) const void
Histogram::printWithMultiplier(ostream& out, double multiplier) const
{ {
if (m_binsize == -1) { if (m_binsize == -1) {
out << "[binsize: log2 "; out << "[binsize: log2 ";
@@ -171,7 +173,8 @@ void Histogram::printWithMultiplier(ostream& out, double multiplier) const
out << "average: NaN |"; out << "average: NaN |";
out << "standard deviation: NaN |"; out << "standard deviation: NaN |";
} else { } else {
out << "average: " << setw(5) << ((double) m_sumSamples)/m_count << " | "; out << "average: " << setw(5) << ((double) m_sumSamples)/m_count
<< " | ";
out << "standard deviation: " << getStandardDeviation() << " |"; out << "standard deviation: " << getStandardDeviation() << " |";
} }
for (int i = 0; i < m_bins && i <= m_largest_bin; i++) { for (int i = 0; i < m_bins && i <= m_largest_bin; i++) {
@@ -184,7 +187,8 @@ void Histogram::printWithMultiplier(ostream& out, double multiplier) const
out << " ]"; out << " ]";
} }
bool node_less_then_eq(const Histogram* n1, const Histogram* n2) bool
node_less_then_eq(const Histogram* n1, const Histogram* n2)
{ {
return (n1->size() > n2->size()); return (n1->size() > n2->size());
} }

View File

@@ -1,4 +1,3 @@
/* /*
* Copyright (c) 1999-2008 Mark D. Hill and David A. Wood * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
* All rights reserved. * All rights reserved.
@@ -27,31 +26,20 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
/* #ifndef __MEM_RUBY_COMMON_HISTOGRAM_HH__
* $Id$ #define __MEM_RUBY_COMMON_HISTOGRAM_HH__
*
* Description: The histogram class implements a simple histogram
*
*/
#ifndef HISTOGRAM_H
#define HISTOGRAM_H
#include <iostream> #include <iostream>
#include "mem/ruby/common/Global.hh" #include "mem/ruby/common/Global.hh"
#include "mem/gems_common/Vector.hh" #include "mem/gems_common/Vector.hh"
class Histogram { class Histogram
{
public: public:
// Constructors
Histogram(int binsize = 1, int bins = 50); Histogram(int binsize = 1, int bins = 50);
// Destructor
~Histogram(); ~Histogram();
// Public Methods
void add(int64 value); void add(int64 value);
void add(const Histogram& hist); void add(const Histogram& hist);
void clear() { clear(m_bins); } void clear() { clear(m_bins); }
@@ -66,14 +54,8 @@ public:
void printWithMultiplier(std::ostream& out, double multiplier) const; void printWithMultiplier(std::ostream& out, double multiplier) const;
void printPercent(std::ostream& out) const; void printPercent(std::ostream& out) const;
void print(std::ostream& out) const; void print(std::ostream& out) const;
private: private:
// Private Methods
// Private copy constructor and assignment operator
// Histogram(const Histogram& obj);
// Histogram& operator=(const Histogram& obj);
// Data Members (m_ prefix)
Vector<int64> m_data; Vector<int64> m_data;
int64 m_max; // the maximum value seen so far int64 m_max; // the maximum value seen so far
int64 m_count; // the number of elements added int64 m_count; // the number of elements added
@@ -89,18 +71,12 @@ private:
bool node_less_then_eq(const Histogram* n1, const Histogram* n2); bool node_less_then_eq(const Histogram* n1, const Histogram* n2);
// Output operator declaration inline std::ostream&
std::ostream& operator<<(std::ostream& out, const Histogram& obj); operator<<(std::ostream& out, const Histogram& obj)
// ******************* Definitions *******************
// Output operator definition
extern inline
std::ostream& operator<<(std::ostream& out, const Histogram& obj)
{ {
obj.print(out); obj.print(out);
out << std::flush; out << std::flush;
return out; return out;
} }
#endif //HISTOGRAM_H #endif // __MEM_RUBY_COMMON_HISTOGRAM_HH__

View File

@@ -1,34 +0,0 @@
/*
* Copyright (c) 1999-2008 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.
*/
/*
* $Id$
*/
#include "mem/ruby/slicc_interface/Message.hh"

View File

@@ -1,4 +1,3 @@
/* /*
* Copyright (c) 1999-2008 Mark D. Hill and David A. Wood * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
* All rights reserved. * All rights reserved.
@@ -27,15 +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.
*/ */
/*
* NetDest.C
*
* Description: See NetDest.hh
*
* $Id$
*
*/
#include "mem/ruby/common/NetDest.hh" #include "mem/ruby/common/NetDest.hh"
#include "mem/protocol/Protocol.hh" #include "mem/protocol/Protocol.hh"
@@ -44,12 +34,14 @@ NetDest::NetDest()
setSize(); setSize();
} }
void NetDest::add(MachineID newElement) void
NetDest::add(MachineID newElement)
{ {
m_bits[vecIndex(newElement)].add(bitIndex(newElement.num)); m_bits[vecIndex(newElement)].add(bitIndex(newElement.num));
} }
void NetDest::addNetDest(const NetDest& netDest) void
NetDest::addNetDest(const NetDest& netDest)
{ {
assert(m_bits.size() == netDest.getSize()); assert(m_bits.size() == netDest.getSize());
for (int i = 0; i < m_bits.size(); i++) { for (int i = 0; i < m_bits.size(); i++) {
@@ -57,49 +49,57 @@ void NetDest::addNetDest(const NetDest& netDest)
} }
} }
void NetDest::addRandom() void
NetDest::addRandom()
{ {
int i = random()%m_bits.size(); int i = random()%m_bits.size();
m_bits[i].addRandom(); m_bits[i].addRandom();
} }
void NetDest::setNetDest(MachineType machine, const Set& set) void
NetDest::setNetDest(MachineType machine, const Set& set)
{ {
// assure that there is only one set of destinations for this machine // assure that there is only one set of destinations for this machine
assert(MachineType_base_level((MachineType)(machine+1)) - MachineType_base_level(machine) == 1); assert(MachineType_base_level((MachineType)(machine + 1)) -
MachineType_base_level(machine) == 1);
m_bits[MachineType_base_level(machine)] = set; m_bits[MachineType_base_level(machine)] = set;
} }
void NetDest::remove(MachineID oldElement) void
NetDest::remove(MachineID oldElement)
{ {
m_bits[vecIndex(oldElement)].remove(bitIndex(oldElement.num)); m_bits[vecIndex(oldElement)].remove(bitIndex(oldElement.num));
} }
void NetDest::removeNetDest(const NetDest& netDest) void
NetDest::removeNetDest(const NetDest& netDest)
{ {
assert(m_bits.size() == netDest.getSize()); assert(m_bits.size() == netDest.getSize());
for (int i = 0; i < m_bits.size(); i++) { for (int i = 0; i < m_bits.size(); i++) {
m_bits[i].removeSet(netDest.m_bits[i]); m_bits[i].removeSet(netDest.m_bits[i]);
} }
} }
void NetDest::clear() void
NetDest::clear()
{ {
for (int i = 0; i < m_bits.size(); i++) { for (int i = 0; i < m_bits.size(); i++) {
m_bits[i].clear(); m_bits[i].clear();
} }
} }
void NetDest::broadcast() void
NetDest::broadcast()
{ {
for (MachineType machine = MachineType_FIRST; machine < MachineType_NUM; ++machine) { for (MachineType machine = MachineType_FIRST;
machine < MachineType_NUM; ++machine) {
broadcast(machine); broadcast(machine);
} }
} }
void NetDest::broadcast(MachineType machineType) { void
NetDest::broadcast(MachineType machineType)
{
for (int i = 0; i < MachineType_base_count(machineType); i++) { for (int i = 0; i < MachineType_base_count(machineType); i++) {
MachineID mach = {machineType, i}; MachineID mach = {machineType, i};
add(mach); add(mach);
@@ -107,20 +107,24 @@ void NetDest::broadcast(MachineType machineType) {
} }
//For Princeton Network //For Princeton Network
Vector<NodeID> NetDest::getAllDest() { Vector<NodeID>
NetDest::getAllDest()
{
Vector<NodeID> dest; Vector<NodeID> dest;
dest.clear(); dest.clear();
for (int i = 0; i < m_bits.size(); i++) { for (int i = 0; i < m_bits.size(); i++) {
for (int j = 0; j < m_bits[i].getSize(); j++) { for (int j = 0; j < m_bits[i].getSize(); j++) {
if (m_bits[i].isElement(j)) { if (m_bits[i].isElement(j)) {
dest.insertAtBottom((NodeID) (MachineType_base_number((MachineType) i) + j)); int id = MachineType_base_number((MachineType)i) + j;
dest.insertAtBottom((NodeID)id);
} }
} }
} }
return dest; return dest;
} }
int NetDest::count() const int
NetDest::count() const
{ {
int counter = 0; int counter = 0;
for (int i = 0; i < m_bits.size(); i++) { for (int i = 0; i < m_bits.size(); i++) {
@@ -129,11 +133,14 @@ int NetDest::count() const
return counter; return counter;
} }
NodeID NetDest::elementAt(MachineID index) { NodeID
NetDest::elementAt(MachineID index)
{
return m_bits[vecIndex(index)].elementAt(bitIndex(index.num)); return m_bits[vecIndex(index)].elementAt(bitIndex(index.num));
} }
MachineID NetDest::smallestElement() const MachineID
NetDest::smallestElement() const
{ {
assert(count() > 0); assert(count() > 0);
for (int i = 0; i < m_bits.size(); i++) { for (int i = 0; i < m_bits.size(); i++) {
@@ -147,9 +154,11 @@ MachineID NetDest::smallestElement() const
ERROR_MSG("No smallest element of an empty set."); ERROR_MSG("No smallest element of an empty set.");
} }
MachineID NetDest::smallestElement(MachineType machine) const MachineID
NetDest::smallestElement(MachineType machine) const
{ {
for (int j = 0; j < m_bits[MachineType_base_level(machine)].getSize(); j++) { int size = m_bits[MachineType_base_level(machine)].getSize();
for (int j = 0; j < size; j++) {
if (m_bits[MachineType_base_level(machine)].isElement(j)) { if (m_bits[MachineType_base_level(machine)].isElement(j)) {
MachineID mach = {machine, j}; MachineID mach = {machine, j};
return mach; return mach;
@@ -159,9 +168,9 @@ MachineID NetDest::smallestElement(MachineType machine) const
ERROR_MSG("No smallest element of given MachineType."); ERROR_MSG("No smallest element of given MachineType.");
} }
// Returns true iff all bits are set // Returns true iff all bits are set
bool NetDest::isBroadcast() const bool
NetDest::isBroadcast() const
{ {
for (int i = 0; i < m_bits.size(); i++) { for (int i = 0; i < m_bits.size(); i++) {
if (!m_bits[i].isBroadcast()) { if (!m_bits[i].isBroadcast()) {
@@ -172,7 +181,8 @@ bool NetDest::isBroadcast() const
} }
// Returns true iff no bits are set // Returns true iff no bits are set
bool NetDest::isEmpty() const bool
NetDest::isEmpty() const
{ {
for (int i = 0; i < m_bits.size(); i++) { for (int i = 0; i < m_bits.size(); i++) {
if (!m_bits[i].isEmpty()) { if (!m_bits[i].isEmpty()) {
@@ -183,7 +193,8 @@ bool NetDest::isEmpty() const
} }
// returns the logical OR of "this" set and orNetDest // returns the logical OR of "this" set and orNetDest
NetDest NetDest::OR(const NetDest& orNetDest) const NetDest
NetDest::OR(const NetDest& orNetDest) const
{ {
assert(m_bits.size() == orNetDest.getSize()); assert(m_bits.size() == orNetDest.getSize());
NetDest result; NetDest result;
@@ -193,9 +204,9 @@ NetDest NetDest::OR(const NetDest& orNetDest) const
return result; return result;
} }
// returns the logical AND of "this" set and andNetDest // returns the logical AND of "this" set and andNetDest
NetDest NetDest::AND(const NetDest& andNetDest) const NetDest
NetDest::AND(const NetDest& andNetDest) const
{ {
assert(m_bits.size() == andNetDest.getSize()); assert(m_bits.size() == andNetDest.getSize());
NetDest result; NetDest result;
@@ -206,7 +217,8 @@ NetDest NetDest::AND(const NetDest& andNetDest) const
} }
// Returns true if the intersection of the two sets is non-empty // Returns true if the intersection of the two sets is non-empty
bool NetDest::intersectionIsNotEmpty(const NetDest& other_netDest) const bool
NetDest::intersectionIsNotEmpty(const NetDest& other_netDest) const
{ {
assert(m_bits.size() == other_netDest.getSize()); assert(m_bits.size() == other_netDest.getSize());
for (int i = 0; i < m_bits.size(); i++) { for (int i = 0; i < m_bits.size(); i++) {
@@ -217,7 +229,8 @@ bool NetDest::intersectionIsNotEmpty(const NetDest& other_netDest) const
return false; return false;
} }
bool NetDest::isSuperset(const NetDest& test) const bool
NetDest::isSuperset(const NetDest& test) const
{ {
assert(m_bits.size() == test.getSize()); assert(m_bits.size() == test.getSize());
@@ -229,12 +242,14 @@ bool NetDest::isSuperset(const NetDest& test) const
return true; return true;
} }
bool NetDest::isElement(MachineID element) const bool
NetDest::isElement(MachineID element) const
{ {
return ((m_bits[vecIndex(element)])).isElement(bitIndex(element.num)); return ((m_bits[vecIndex(element)])).isElement(bitIndex(element.num));
} }
void NetDest::setSize() void
NetDest::setSize()
{ {
m_bits.setSize(MachineType_base_level(MachineType_NUM)); m_bits.setSize(MachineType_base_level(MachineType_NUM));
assert(m_bits.size() == MachineType_NUM); assert(m_bits.size() == MachineType_NUM);
@@ -244,7 +259,8 @@ void NetDest::setSize()
} }
} }
void NetDest::print(ostream& out) const void
NetDest::print(ostream& out) const
{ {
out << "[NetDest (" << m_bits.size() << ") "; out << "[NetDest (" << m_bits.size() << ") ";

View File

@@ -1,4 +1,3 @@
/* /*
* Copyright (c) 1999-2008 Mark D. Hill and David A. Wood * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
* All rights reserved. * All rights reserved.
@@ -27,22 +26,13 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
/*
* Set.hh
*
* Description:
*
* $Id$
*
*/
// NetDest specifies the network destination of a NetworkMessage // NetDest specifies the network destination of a NetworkMessage
// This is backward compatible with the Set class that was previously // This is backward compatible with the Set class that was previously
// used to specify network destinations. // used to specify network destinations.
// NetDest supports both node networks and component networks // NetDest supports both node networks and component networks
#ifndef NETDEST_H #ifndef __MEM_RUBY_COMMON_NETDEST_HH__
#define NETDEST_H #define __MEM_RUBY_COMMON_NETDEST_HH__
#include "mem/ruby/common/Global.hh" #include "mem/ruby/common/Global.hh"
#include "mem/gems_common/Vector.hh" #include "mem/gems_common/Vector.hh"
@@ -51,9 +41,8 @@
#include "mem/ruby/common/Set.hh" #include "mem/ruby/common/Set.hh"
#include "mem/protocol/MachineType.hh" #include "mem/protocol/MachineType.hh"
class Set; class NetDest
{
class NetDest {
public: public:
// Constructors // Constructors
// creates and empty set // creates and empty set
@@ -62,10 +51,11 @@ public:
NetDest& operator=(const Set& obj); NetDest& operator=(const Set& obj);
// Destructor ~NetDest()
~NetDest() { DEBUG_MSG(MEMORY_COMP, LowPrio, "NetDest Destructor"); } {
DEBUG_MSG(MEMORY_COMP, LowPrio, "NetDest Destructor");
}
// Public Methods
void add(MachineID newElement); void add(MachineID newElement);
void addNetDest(const NetDest& netDest); void addNetDest(const NetDest& netDest);
void addRandom(); void addRandom();
@@ -78,8 +68,11 @@ public:
int count() const; int count() const;
bool isEqual(const NetDest& netDest); bool isEqual(const NetDest& netDest);
NetDest OR(const NetDest& orNetDest) const; // return the logical OR of this netDest and orNetDest // return the logical OR of this netDest and orNetDest
NetDest AND(const NetDest& andNetDest) const; // return the logical AND of this netDest and andNetDest NetDest OR(const NetDest& orNetDest) const;
// return the logical AND of this netDest and andNetDest
NetDest AND(const NetDest& andNetDest) const;
// Returns true if the intersection of the two netDests is non-empty // Returns true if the intersection of the two netDests is non-empty
bool intersectionIsNotEmpty(const NetDest& other_netDest) const; bool intersectionIsNotEmpty(const NetDest& other_netDest) const;
@@ -108,37 +101,32 @@ public:
void print(ostream& out) const; void print(ostream& out) const;
private: private:
// returns a value >= MachineType_base_level("this machine")
// Private Methods // and < MachineType_base_level("next highest machine")
// returns a value >= MachineType_base_level("this machine") and < MachineType_base_level("next highest machine") int
int vecIndex(MachineID m) const { vecIndex(MachineID m) const
{
int vec_index = MachineType_base_level(m.type); int vec_index = MachineType_base_level(m.type);
assert(vec_index < m_bits.size()); assert(vec_index < m_bits.size());
return vec_index; return vec_index;
} }
NodeID bitIndex(NodeID index) const { NodeID
bitIndex(NodeID index) const
{
return index; return index;
} }
// Data Members (m_ prefix)
Vector <Set> m_bits; // a Vector of bit vectors - i.e. Sets Vector <Set> m_bits; // a Vector of bit vectors - i.e. Sets
}; };
// Output operator declaration inline ostream&
ostream& operator<<(ostream& out, const NetDest& obj); operator<<(ostream& out, const NetDest& obj)
// ******************* Definitions *******************
// Output operator definition
extern inline
ostream& operator<<(ostream& out, const NetDest& obj)
{ {
obj.print(out); obj.print(out);
out << flush; out << flush;
return out; return out;
} }
#endif //NETDEST_H #endif // __MEM_RUBY_COMMON_NETDEST_HH__

View File

@@ -41,7 +41,6 @@ Source('Debug.cc')
Source('Driver.cc') Source('Driver.cc')
Source('Global.cc') Source('Global.cc')
Source('Histogram.cc') Source('Histogram.cc')
Source('Message.cc')
Source('NetDest.cc') Source('NetDest.cc')
Source('Set.cc', Werror=False) Source('Set.cc', Werror=False)
Source('SubBlock.cc') Source('SubBlock.cc')

View File

@@ -1,4 +1,3 @@
/* /*
* Copyright (c) 1999-2008 Mark D. Hill and David A. Wood * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
* All rights reserved. * All rights reserved.
@@ -27,10 +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.
*/ */
/*
* $Id$
*/
#include "mem/ruby/common/SubBlock.hh" #include "mem/ruby/common/SubBlock.hh"
SubBlock::SubBlock(const Address& addr, int size) SubBlock::SubBlock(const Address& addr, int size)
@@ -42,7 +37,8 @@ SubBlock::SubBlock(const Address& addr, int size)
} }
} }
void SubBlock::internalMergeFrom(const DataBlock& data) void
SubBlock::internalMergeFrom(const DataBlock& data)
{ {
int size = getSize(); int size = getSize();
assert(size > 0); assert(size > 0);
@@ -52,17 +48,20 @@ void SubBlock::internalMergeFrom(const DataBlock& data)
} }
} }
void SubBlock::internalMergeTo(DataBlock& data) const void
SubBlock::internalMergeTo(DataBlock& data) const
{ {
int size = getSize(); int size = getSize();
assert(size > 0); assert(size > 0);
int offset = m_address.getOffset(); int offset = m_address.getOffset();
for (int i = 0; i < size; i++) { for (int i = 0; i < size; i++) {
data.setByte(offset+i, this->getByte(i)); // This will detect crossing a cache line boundary // This will detect crossing a cache line boundary
data.setByte(offset + i, this->getByte(i));
} }
} }
void SubBlock::print(ostream& out) const void
SubBlock::print(ostream& out) const
{ {
out << "[" << m_address << ", " << getSize() << ", " << m_data << "]"; out << "[" << m_address << ", " << getSize() << ", " << m_data << "]";
} }

View File

@@ -1,4 +1,3 @@
/* /*
* Copyright (c) 1999-2008 Mark D. Hill and David A. Wood * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
* All rights reserved. * All rights reserved.
@@ -27,29 +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.
*/ */
/* #ifndef __MEM_RUBY_COMMON_SUBBLOCK_HH__
* $Id$ #define __MEM_RUBY_COMMON_SUBBLOCK_HH__
*
*/
#ifndef SubBlock_H #include "mem/gems_common/Vector.hh"
#define SubBlock_H
#include "mem/ruby/common/Global.hh"
#include "mem/ruby/common/Address.hh" #include "mem/ruby/common/Address.hh"
#include "mem/ruby/common/DataBlock.hh" #include "mem/ruby/common/DataBlock.hh"
#include "mem/gems_common/Vector.hh" #include "mem/ruby/common/Global.hh"
class SubBlock { class SubBlock
{
public: public:
// Constructors
SubBlock() { } SubBlock() { }
SubBlock(const Address& addr, int size); SubBlock(const Address& addr, int size);
// Destructor
~SubBlock() { } ~SubBlock() { }
// Public Methods
const Address& getAddress() const { return m_address; } const Address& getAddress() const { return m_address; }
void setAddress(const Address& addr) { m_address = addr; } void setAddress(const Address& addr) { m_address = addr; }
@@ -68,8 +59,8 @@ public:
void mergeFrom(const DataBlock& data) { internalMergeFrom(data); } void mergeFrom(const DataBlock& data) { internalMergeFrom(data); }
void print(ostream& out) const; void print(ostream& out) const;
private:
private:
void internalMergeTo(DataBlock& data) const; void internalMergeTo(DataBlock& data) const;
void internalMergeFrom(const DataBlock& data); void internalMergeFrom(const DataBlock& data);
@@ -78,18 +69,12 @@ private:
Vector<uint8_t> m_data; Vector<uint8_t> m_data;
}; };
// Output operator declaration inline ostream&
ostream& operator<<(ostream& out, const SubBlock& obj); operator<<(ostream& out, const SubBlock& obj)
// ******************* Definitions *******************
// Output operator definition
extern inline
ostream& operator<<(ostream& out, const SubBlock& obj)
{ {
obj.print(out); obj.print(out);
out << flush; out << flush;
return out; return out;
} }
#endif //SubBlock_H #endif // __MEM_RUBY_COMMON_SUBBLOCK_HH__

View File

@@ -1,4 +1,3 @@
/* /*
* Copyright (c) 1999-2008 Mark D. Hill and David A. Wood * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
* All rights reserved. * All rights reserved.
@@ -27,16 +26,10 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
/*
* $Id$
*/
#include "mem/ruby/eventqueue/RubyEventQueue.hh"
#include "mem/ruby/common/Consumer.hh" #include "mem/ruby/common/Consumer.hh"
#include "mem/ruby/system/System.hh" #include "mem/ruby/eventqueue/RubyEventQueue.hh"
#include "mem/ruby/eventqueue/RubyEventQueueNode.hh" #include "mem/ruby/eventqueue/RubyEventQueueNode.hh"
#include "mem/ruby/system/System.hh"
// Class public method definitions
RubyEventQueue::RubyEventQueue(EventQueue* eventq, Tick _clock) RubyEventQueue::RubyEventQueue(EventQueue* eventq, Tick _clock)
: EventManager(eventq), m_clock(_clock) : EventManager(eventq), m_clock(_clock)
@@ -47,12 +40,14 @@ RubyEventQueue::~RubyEventQueue()
{ {
} }
void RubyEventQueue::scheduleEvent(Consumer* consumer, Time timeDelta) void
RubyEventQueue::scheduleEvent(Consumer* consumer, Time timeDelta)
{ {
scheduleEventAbsolute(consumer, timeDelta + getTime()); scheduleEventAbsolute(consumer, timeDelta + getTime());
} }
void RubyEventQueue::scheduleEventAbsolute(Consumer* consumer, Time timeAbs) void
RubyEventQueue::scheduleEventAbsolute(Consumer* consumer, Time timeAbs)
{ {
// Check to see if this is a redundant wakeup // Check to see if this is a redundant wakeup
ASSERT(consumer != NULL); ASSERT(consumer != NULL);
@@ -65,8 +60,6 @@ void RubyEventQueue::scheduleEventAbsolute(Consumer* consumer, Time timeAbs)
} }
} }
// Class private method definitions
void void
RubyEventQueue::print(ostream& out) const RubyEventQueue::print(ostream& out) const
{ {

View File

@@ -1,4 +1,3 @@
/* /*
* Copyright (c) 1999-2008 Mark D. Hill and David A. Wood * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
* All rights reserved. * All rights reserved.
@@ -28,9 +27,7 @@
*/ */
/* /*
* $Id$ * The RubyEventQueue class implements an event queue which
*
* Description: The RubyEventQueue class implements an event queue which
* can be trigger events, allowing our simulation to be event driven. * can be trigger events, allowing our simulation to be event driven.
* *
* Currently, the only event we support is a Consumer being signaled * Currently, the only event we support is a Consumer being signaled
@@ -56,8 +53,8 @@
* *
*/ */
#ifndef RUBYEVENTQUEUE_H #ifndef __MEM_RUBY_EVENTQUEUE_RUBYEVENTQUEUE_HH__
#define RUBYEVENTQUEUE_H #define __MEM_RUBY_EVENTQUEUE_RUBYEVENTQUEUE_HH__
#include <iostream> #include <iostream>
@@ -70,16 +67,12 @@ class Consumer;
template <class TYPE> class PrioHeap; template <class TYPE> class PrioHeap;
class RubyEventQueueNode; class RubyEventQueueNode;
class RubyEventQueue : public EventManager { class RubyEventQueue : public EventManager
{
public: public:
// Constructors
RubyEventQueue(EventQueue* eventq, Tick _clock); RubyEventQueue(EventQueue* eventq, Tick _clock);
// Destructor
~RubyEventQueue(); ~RubyEventQueue();
// Public Methods
Time getTime() const { return curTick/m_clock; } Time getTime() const { return curTick/m_clock; }
Tick getClock() const { return m_clock; } Tick getClock() const { return m_clock; }
void scheduleEvent(Consumer* consumer, Time timeDelta); void scheduleEvent(Consumer* consumer, Time timeDelta);
@@ -89,7 +82,6 @@ public:
void triggerEvents(Time t) { assert(0); } void triggerEvents(Time t) { assert(0); }
void triggerAllEvents() { assert(0); } void triggerAllEvents() { assert(0); }
// Private Methods
private: private:
// Private copy constructor and assignment operator // Private copy constructor and assignment operator
RubyEventQueue(const RubyEventQueue& obj); RubyEventQueue(const RubyEventQueue& obj);
@@ -99,19 +91,12 @@ private:
Tick m_clock; Tick m_clock;
}; };
// Output operator declaration inline std::ostream&
inline extern operator<<(std::ostream& out, const RubyEventQueue& obj)
std::ostream& operator<<(std::ostream& out, const RubyEventQueue& obj);
// ******************* Definitions *******************
// Output operator definition
inline extern
std::ostream& operator<<(std::ostream& out, const RubyEventQueue& obj)
{ {
obj.print(out); obj.print(out);
out << std::flush; out << std::flush;
return out; return out;
} }
#endif //EVENTQUEUE_H #endif // __MEM_RUBY_EVENTQUEUE_RUBYEVENTQUEUE_HH__

View File

@@ -1,4 +1,3 @@
/* /*
* Copyright (c) 1999-2008 Mark D. Hill and David A. Wood * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
* All rights reserved. * All rights reserved.
@@ -27,14 +26,10 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
/*
* $Id$
*
*/
#include "mem/ruby/eventqueue/RubyEventQueueNode.hh" #include "mem/ruby/eventqueue/RubyEventQueueNode.hh"
void RubyEventQueueNode::print(std::ostream& out) const void
RubyEventQueueNode::print(std::ostream& out) const
{ {
out << "["; out << "[";
if (m_consumer_ptr != NULL) { if (m_consumer_ptr != NULL) {

View File

@@ -1,4 +1,3 @@
/* /*
* Copyright (c) 1999-2008 Mark D. Hill and David A. Wood * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
* All rights reserved. * All rights reserved.
@@ -27,36 +26,27 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
/* #ifndef __MEM_RUBY_EVENTQUEUE_RUBYEVENTQUEUENODE_HH__
* $Id$ #define __MEM_RUBY_EVENTQUEUE_RUBYEVENTQUEUENODE_HH__
*
*/
#ifndef RUBYEVENTQUEUENODE_H
#define RUBYEVENTQUEUENODE_H
#include <iostream> #include <iostream>
#include "mem/ruby/common/Consumer.hh"
#include "mem/ruby/common/Global.hh" #include "mem/ruby/common/Global.hh"
#include "sim/eventq.hh" #include "sim/eventq.hh"
#include "mem/ruby/common/Consumer.hh"
//class Consumer;
class RubyEventQueueNode : public Event { class RubyEventQueueNode : public Event
{
public: public:
// Constructors
RubyEventQueueNode(Consumer* _consumer, RubyEventQueue* _eventq) RubyEventQueueNode(Consumer* _consumer, RubyEventQueue* _eventq)
: m_consumer_ptr(_consumer), m_eventq_ptr(_eventq) : m_consumer_ptr(_consumer), m_eventq_ptr(_eventq)
{ {
setFlags(AutoDelete); setFlags(AutoDelete);
} }
// Destructor
//~RubyEventQueueNode();
// Public Methods
void print(std::ostream& out) const; void print(std::ostream& out) const;
virtual void process() virtual void
process()
{ {
m_consumer_ptr->wakeup(); m_consumer_ptr->wakeup();
m_consumer_ptr->removeScheduledWakeupTime(m_eventq_ptr->getTime()); m_consumer_ptr->removeScheduledWakeupTime(m_eventq_ptr->getTime());
@@ -64,28 +54,16 @@ public:
virtual const char *description() const { return "Ruby Event"; } virtual const char *description() const { return "Ruby Event"; }
private: private:
// Private Methods
// Default copy constructor and assignment operator
// RubyEventQueueNode(const RubyEventQueueNode& obj);
// Data Members (m_ prefix)
Consumer* m_consumer_ptr; Consumer* m_consumer_ptr;
RubyEventQueue* m_eventq_ptr; RubyEventQueue* m_eventq_ptr;
}; };
// Output operator declaration inline std::ostream&
std::ostream& operator<<(std::ostream& out, const RubyEventQueueNode& obj); operator<<(std::ostream& out, const RubyEventQueueNode& obj)
// ******************* Definitions *******************
// Output operator definition
extern inline
std::ostream& operator<<(std::ostream& out, const RubyEventQueueNode& obj)
{ {
obj.print(out); obj.print(out);
out << std::flush; out << std::flush;
return out; return out;
} }
#endif //EVENTQUEUENODE_H #endif // __MEM_RUBY_EVENTQUEUE_EVENTQUEUENODE_HH__

View File

@@ -1,4 +1,3 @@
/* /*
* Copyright (c) 1999-2008 Mark D. Hill and David A. Wood * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
* All rights reserved. * All rights reserved.
@@ -27,23 +26,15 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
/* #ifndef __MEM_RUBY_FILTERS_ABSTRACTBLOOMFILTER_HH__
* AbstractBloomFilter.hh #define __MEM_RUBY_FILTERS_ABSTRACTBLOOMFILTER_HH__
*
* Description:
*
*
*/
#ifndef ABSTRACT_BLOOM_FILTER_H
#define ABSTRACT_BLOOM_FILTER_H
#include "mem/ruby/common/Global.hh"
#include "mem/ruby/common/Address.hh" #include "mem/ruby/common/Address.hh"
#include "mem/ruby/common/Global.hh"
class AbstractBloomFilter { class AbstractBloomFilter
{
public: public:
virtual ~AbstractBloomFilter() {}; virtual ~AbstractBloomFilter() {};
virtual void clear() = 0; virtual void clear() = 0;
virtual void increment(const Address& addr) = 0; virtual void increment(const Address& addr) = 0;
@@ -61,10 +52,6 @@ public:
virtual int getIndex(const Address& addr) = 0; virtual int getIndex(const Address& addr) = 0;
virtual int readBit(const int index) = 0; virtual int readBit(const int index) = 0;
virtual void writeBit(const int index, const int value) = 0; virtual void writeBit(const int index, const int value) = 0;
private:
}; };
#endif // __MEM_RUBY_FILTERS_ABSTRACTBLOOMFILTER_HH__
#endif

View File

@@ -1,4 +1,3 @@
/* /*
* Copyright (c) 1999-2008 Mark D. Hill and David A. Wood * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
* All rights reserved. * All rights reserved.
@@ -27,17 +26,9 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
/*
* BlockBloomFilter.cc
*
* Description:
*
*
*/
#include "mem/ruby/filters/BlockBloomFilter.hh"
#include "mem/gems_common/Map.hh" #include "mem/gems_common/Map.hh"
#include "mem/ruby/common/Address.hh" #include "mem/ruby/common/Address.hh"
#include "mem/ruby/filters/BlockBloomFilter.hh"
BlockBloomFilter::BlockBloomFilter(string str) BlockBloomFilter::BlockBloomFilter(string str)
{ {
@@ -52,57 +43,65 @@ BlockBloomFilter::BlockBloomFilter(string str)
clear(); clear();
} }
BlockBloomFilter::~BlockBloomFilter(){ BlockBloomFilter::~BlockBloomFilter()
{
} }
void BlockBloomFilter::clear() void
BlockBloomFilter::clear()
{ {
for (int i = 0; i < m_filter_size; i++) { for (int i = 0; i < m_filter_size; i++) {
m_filter[i] = 0; m_filter[i] = 0;
} }
} }
void BlockBloomFilter::increment(const Address& addr) void
BlockBloomFilter::increment(const Address& addr)
{ {
// Not used // Not used
} }
void
void BlockBloomFilter::decrement(const Address& addr) BlockBloomFilter::decrement(const Address& addr)
{ {
// Not used // Not used
} }
void BlockBloomFilter::merge(AbstractBloomFilter * other_filter) void
BlockBloomFilter::merge(AbstractBloomFilter * other_filter)
{ {
// TODO // TODO
} }
void BlockBloomFilter::set(const Address& addr) void
BlockBloomFilter::set(const Address& addr)
{ {
int i = get_index(addr); int i = get_index(addr);
m_filter[i] = 1; m_filter[i] = 1;
} }
void BlockBloomFilter::unset(const Address& addr) void
BlockBloomFilter::unset(const Address& addr)
{ {
int i = get_index(addr); int i = get_index(addr);
m_filter[i] = 0; m_filter[i] = 0;
} }
bool BlockBloomFilter::isSet(const Address& addr) bool
BlockBloomFilter::isSet(const Address& addr)
{ {
int i = get_index(addr); int i = get_index(addr);
return (m_filter[i]); return (m_filter[i]);
} }
int
int BlockBloomFilter::getCount(const Address& addr) BlockBloomFilter::getCount(const Address& addr)
{ {
return m_filter[get_index(addr)]; return m_filter[get_index(addr)];
} }
int BlockBloomFilter::getTotalCount() int
BlockBloomFilter::getTotalCount()
{ {
int count = 0; int count = 0;
@@ -114,31 +113,43 @@ int BlockBloomFilter::getTotalCount()
return count; return count;
} }
int BlockBloomFilter::getIndex(const Address& addr) int
BlockBloomFilter::getIndex(const Address& addr)
{ {
return get_index(addr); return get_index(addr);
} }
void BlockBloomFilter::print(ostream& out) const void
BlockBloomFilter::print(ostream& out) const
{ {
} }
int BlockBloomFilter::readBit(const int index) { int
BlockBloomFilter::readBit(const int index)
{
return m_filter[index]; return m_filter[index];
} }
void BlockBloomFilter::writeBit(const int index, const int value) { void
BlockBloomFilter::writeBit(const int index, const int value)
{
m_filter[index] = value; m_filter[index] = value;
} }
int BlockBloomFilter::get_index(const Address& addr) int
BlockBloomFilter::get_index(const Address& addr)
{ {
// Pull out some bit field ==> B1 // Pull out some bit field ==> B1
// Pull out additional bits, not the same as B1 ==> B2 // Pull out additional bits, not the same as B1 ==> B2
// XOR B1 and B2 to get hash index // XOR B1 and B2 to get hash index
physical_address_t block_bits = addr.bitSelect( RubySystem::getBlockSizeBits(), 2*RubySystem::getBlockSizeBits() - 1); physical_address_t block_bits =
addr.bitSelect(RubySystem::getBlockSizeBits(),
2 * RubySystem::getBlockSizeBits() - 1);
int offset = 5; int offset = 5;
physical_address_t other_bits = addr.bitSelect( 2*RubySystem::getBlockSizeBits() + offset, 2*RubySystem::getBlockSizeBits() + offset + m_filter_size_bits - 1); physical_address_t other_bits =
addr.bitSelect(2 * RubySystem::getBlockSizeBits() + offset,
2 * RubySystem::getBlockSizeBits() + offset +
m_filter_size_bits - 1);
int index = block_bits ^ other_bits; int index = block_bits ^ other_bits;
assert(index < m_filter_size); assert(index < m_filter_size);
return index; return index;

View File

@@ -1,4 +1,3 @@
/* /*
* Copyright (c) 1999-2008 Mark D. Hill and David A. Wood * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
* All rights reserved. * All rights reserved.
@@ -27,27 +26,19 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
/* #ifndef __MEM_RUBY_FILTERS_BLOCKBLOOMFILTER_HH__
* BlockBloomFilter.hh #define __MEM_RUBY_FILTERS_BLOCKBLOOMFILTER_HH__
*
* Description:
*
*
*/
#ifndef BLOCK_BLOOM_FILTER_H
#define BLOCK_BLOOM_FILTER_H
#include "mem/gems_common/Map.hh" #include "mem/gems_common/Map.hh"
#include "mem/ruby/common/Global.hh"
#include "mem/ruby/common/Address.hh" #include "mem/ruby/common/Address.hh"
#include "mem/ruby/common/Global.hh"
#include "mem/ruby/filters/AbstractBloomFilter.hh" #include "mem/ruby/filters/AbstractBloomFilter.hh"
class BlockBloomFilter : public AbstractBloomFilter { class BlockBloomFilter : public AbstractBloomFilter
{
public: public:
~BlockBloomFilter();
BlockBloomFilter(string config); BlockBloomFilter(string config);
~BlockBloomFilter();
void clear(); void clear();
void increment(const Address& addr); void increment(const Address& addr);
@@ -66,7 +57,6 @@ public:
void print(ostream& out) const; void print(ostream& out) const;
private: private:
int get_index(const Address& addr); int get_index(const Address& addr);
Vector<int> m_filter; Vector<int> m_filter;
@@ -77,5 +67,4 @@ private:
int m_count; int m_count;
}; };
#endif // __MEM_RUBY_FILTERS_BLOCKBLOOMFILTER_HH__
#endif

View File

@@ -1,4 +1,3 @@
/* /*
* Copyright (c) 1999-2008 Mark D. Hill and David A. Wood * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
* All rights reserved. * All rights reserved.
@@ -27,17 +26,9 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
/*
* BulkBloomFilter.cc
*
* Description:
*
*
*/
#include "mem/ruby/filters/BulkBloomFilter.hh"
#include "mem/gems_common/Map.hh" #include "mem/gems_common/Map.hh"
#include "mem/ruby/common/Address.hh" #include "mem/ruby/common/Address.hh"
#include "mem/ruby/filters/BulkBloomFilter.hh"
BulkBloomFilter::BulkBloomFilter(string str) BulkBloomFilter::BulkBloomFilter(string str)
{ {
@@ -59,34 +50,38 @@ BulkBloomFilter::BulkBloomFilter(string str)
} }
} }
BulkBloomFilter::~BulkBloomFilter(){ BulkBloomFilter::~BulkBloomFilter()
{
} }
void BulkBloomFilter::clear() void
BulkBloomFilter::clear()
{ {
for (int i = 0; i < m_filter_size; i++) { for (int i = 0; i < m_filter_size; i++) {
m_filter[i] = 0; m_filter[i] = 0;
} }
} }
void BulkBloomFilter::increment(const Address& addr) void
BulkBloomFilter::increment(const Address& addr)
{ {
// Not used // Not used
} }
void
void BulkBloomFilter::decrement(const Address& addr) BulkBloomFilter::decrement(const Address& addr)
{ {
// Not used // Not used
} }
void BulkBloomFilter::merge(AbstractBloomFilter * other_filter) void
BulkBloomFilter::merge(AbstractBloomFilter * other_filter)
{ {
// TODO // TODO
} }
void BulkBloomFilter::set(const Address& addr) void
BulkBloomFilter::set(const Address& addr)
{ {
// c0 contains the cache index bits // c0 contains the cache index bits
int set_bits = m_sector_bits; int set_bits = m_sector_bits;
@@ -105,12 +100,14 @@ void BulkBloomFilter::set(const Address& addr)
m_filter[c1] = 1; m_filter[c1] = 1;
} }
void BulkBloomFilter::unset(const Address& addr) void
BulkBloomFilter::unset(const Address& addr)
{ {
// not used // not used
} }
bool BulkBloomFilter::isSet(const Address& addr) bool
BulkBloomFilter::isSet(const Address& addr)
{ {
// c0 contains the cache index bits // c0 contains the cache index bits
int set_bits = m_sector_bits; int set_bits = m_sector_bits;
@@ -128,8 +125,8 @@ bool BulkBloomFilter::isSet(const Address& addr)
// set v1 bit // set v1 bit
m_temp_filter[c1] = 1; m_temp_filter[c1] = 1;
// perform filter intersection. If any c part is 0, no possibility of address being in signature. // perform filter intersection. If any c part is 0, no possibility
// get first c intersection part // of address being in signature. get first c intersection part
bool zero = false; bool zero = false;
for (int i = 0; i < m_filter_size/2; ++i){ for (int i = 0; i < m_filter_size/2; ++i){
// get intersection of signatures // get intersection of signatures
@@ -165,14 +162,15 @@ bool BulkBloomFilter::isSet(const Address& addr)
return true; return true;
} }
int
int BulkBloomFilter::getCount(const Address& addr) BulkBloomFilter::getCount(const Address& addr)
{ {
// not used // not used
return 0; return 0;
} }
int BulkBloomFilter::getTotalCount() int
BulkBloomFilter::getTotalCount()
{ {
int count = 0; int count = 0;
for (int i = 0; i < m_filter_size; i++) { for (int i = 0; i < m_filter_size; i++) {
@@ -183,49 +181,64 @@ int BulkBloomFilter::getTotalCount()
return count; return count;
} }
int BulkBloomFilter::getIndex(const Address& addr) int
BulkBloomFilter::getIndex(const Address& addr)
{ {
return get_index(addr); return get_index(addr);
} }
int BulkBloomFilter::readBit(const int index) { int
BulkBloomFilter::readBit(const int index)
{
return 0; return 0;
// TODO // TODO
} }
void BulkBloomFilter::writeBit(const int index, const int value) { void
BulkBloomFilter::writeBit(const int index, const int value)
{
// TODO // TODO
} }
void BulkBloomFilter::print(ostream& out) const void
BulkBloomFilter::print(ostream& out) const
{ {
} }
int BulkBloomFilter::get_index(const Address& addr) int
BulkBloomFilter::get_index(const Address& addr)
{ {
return addr.bitSelect( RubySystem::getBlockSizeBits(), RubySystem::getBlockSizeBits() + m_filter_size_bits - 1); return addr.bitSelect(RubySystem::getBlockSizeBits(),
RubySystem::getBlockSizeBits() +
m_filter_size_bits - 1);
} }
Address BulkBloomFilter::permute(const Address & addr){ Address
BulkBloomFilter::permute(const Address & addr)
{
// permutes the original address bits according to Table 5 // permutes the original address bits according to Table 5
int block_offset = RubySystem::getBlockSizeBits(); int block_offset = RubySystem::getBlockSizeBits();
physical_address_t part1 = addr.bitSelect( block_offset, block_offset + 6 ); physical_address_t part1 = addr.bitSelect(block_offset, block_offset + 6),
physical_address_t part2 = addr.bitSelect( block_offset + 9, block_offset + 9 ); part2 = addr.bitSelect(block_offset + 9, block_offset + 9),
physical_address_t part3 = addr.bitSelect( block_offset + 11, block_offset + 11 ); part3 = addr.bitSelect(block_offset + 11, block_offset + 11),
physical_address_t part4 = addr.bitSelect( block_offset + 17, block_offset + 17 ); part4 = addr.bitSelect(block_offset + 17, block_offset + 17),
physical_address_t part5 = addr.bitSelect( block_offset + 7, block_offset + 8 ); part5 = addr.bitSelect(block_offset + 7, block_offset + 8),
physical_address_t part6 = addr.bitSelect( block_offset + 10, block_offset + 10 ); part6 = addr.bitSelect(block_offset + 10, block_offset + 10),
physical_address_t part7 = addr.bitSelect( block_offset + 12, block_offset + 12 ); part7 = addr.bitSelect(block_offset + 12, block_offset + 12),
physical_address_t part8 = addr.bitSelect( block_offset + 13, block_offset + 13 ); part8 = addr.bitSelect(block_offset + 13, block_offset + 13),
physical_address_t part9 = addr.bitSelect( block_offset + 15, block_offset + 16 ); part9 = addr.bitSelect(block_offset + 15, block_offset + 16),
physical_address_t part10 = addr.bitSelect( block_offset + 18, block_offset + 20 ); part10 = addr.bitSelect(block_offset + 18, block_offset + 20),
physical_address_t part11 = addr.bitSelect( block_offset + 14, block_offset + 14 ); part11 = addr.bitSelect(block_offset + 14, block_offset + 14);
physical_address_t result =
(part1 << 14) | (part2 << 13) | (part3 << 12) | (part4 << 11) |
(part5 << 9) | (part6 << 8) | (part7 << 7) | (part8 << 6) |
(part9 << 4) | (part10 << 1) | (part11);
physical_address_t result = (part1 << 14 ) | (part2 << 13 ) | (part3 << 12 ) | (part4 << 11 ) | (part5 << 9) | (part6 << 8)
| (part7 << 7) | (part8 << 6) | (part9 << 4) | (part10 << 1) | (part11);
// assume 32 bit addresses (both virtual and physical) // assume 32 bit addresses (both virtual and physical)
// select the remaining high-order 11 bits // select the remaining high-order 11 bits
physical_address_t remaining_bits = (addr.bitSelect( block_offset + 21, 31 )) << 21; physical_address_t remaining_bits =
addr.bitSelect(block_offset + 21, 31) << 21;
result = result | remaining_bits; result = result | remaining_bits;
return Address(result); return Address(result);

View File

@@ -1,4 +1,3 @@
/* /*
* Copyright (c) 1999-2008 Mark D. Hill and David A. Wood * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
* All rights reserved. * All rights reserved.
@@ -27,27 +26,19 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
/* #ifndef __MEM_RUBY_FILTERS_BULKBLOOMFILTER_HH__
* BulkBloomFilter.hh #define __MEM_RUBY_FILTERS_BULKBLOOMFILTER_HH__
*
* Description:
*
*
*/
#ifndef BULK_BLOOM_FILTER_H
#define BULK_BLOOM_FILTER_H
#include "mem/gems_common/Map.hh" #include "mem/gems_common/Map.hh"
#include "mem/ruby/common/Global.hh"
#include "mem/ruby/common/Address.hh" #include "mem/ruby/common/Address.hh"
#include "mem/ruby/common/Global.hh"
#include "mem/ruby/filters/AbstractBloomFilter.hh" #include "mem/ruby/filters/AbstractBloomFilter.hh"
class BulkBloomFilter : public AbstractBloomFilter { class BulkBloomFilter : public AbstractBloomFilter
{
public: public:
~BulkBloomFilter();
BulkBloomFilter(string config); BulkBloomFilter(string config);
~BulkBloomFilter();
void clear(); void clear();
void increment(const Address& addr); void increment(const Address& addr);
@@ -66,7 +57,6 @@ public:
void print(ostream& out) const; void print(ostream& out) const;
private: private:
int get_index(const Address& addr); int get_index(const Address& addr);
Address permute(const Address & addr); Address permute(const Address & addr);
@@ -82,5 +72,4 @@ private:
int m_count; int m_count;
}; };
#endif // __MEM_RUBY_FILTERS_BULKBLOOMFILTER_HH__
#endif

View File

@@ -1,4 +1,3 @@
/* /*
* Copyright (c) 1999-2008 Mark D. Hill and David A. Wood * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
* All rights reserved. * All rights reserved.
@@ -27,25 +26,16 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
/*
* GenericBloomFilter.hh
*
* Description:
*
*
*/
#include "mem/ruby/common/Global.hh"
#include "mem/ruby/common/Address.hh" #include "mem/ruby/common/Address.hh"
#include "mem/ruby/common/Global.hh"
#include "mem/ruby/filters/GenericBloomFilter.hh"
#include "mem/ruby/filters/LSB_CountingBloomFilter.hh"
#include "mem/ruby/filters/NonCountingBloomFilter.hh"
#include "mem/ruby/filters/BulkBloomFilter.hh"
#include "mem/ruby/filters/BlockBloomFilter.hh" #include "mem/ruby/filters/BlockBloomFilter.hh"
#include "mem/ruby/filters/MultiGrainBloomFilter.hh" #include "mem/ruby/filters/BulkBloomFilter.hh"
#include "mem/ruby/filters/MultiBitSelBloomFilter.hh" #include "mem/ruby/filters/GenericBloomFilter.hh"
#include "mem/ruby/filters/H3BloomFilter.hh" #include "mem/ruby/filters/H3BloomFilter.hh"
#include "mem/ruby/filters/LSB_CountingBloomFilter.hh"
#include "mem/ruby/filters/MultiBitSelBloomFilter.hh"
#include "mem/ruby/filters/MultiGrainBloomFilter.hh"
#include "mem/ruby/filters/NonCountingBloomFilter.hh"
GenericBloomFilter::GenericBloomFilter(string config) GenericBloomFilter::GenericBloomFilter(string config)
{ {
@@ -54,26 +44,19 @@ GenericBloomFilter::GenericBloomFilter(string config)
if (head == "LSB_Counting" ) { if (head == "LSB_Counting" ) {
m_filter = new LSB_CountingBloomFilter(tail); m_filter = new LSB_CountingBloomFilter(tail);
} } else if(head == "NonCounting" ) {
else if(head == "NonCounting" ) {
m_filter = new NonCountingBloomFilter(tail); m_filter = new NonCountingBloomFilter(tail);
} } else if(head == "Bulk" ) {
else if(head == "Bulk" ) {
m_filter = new BulkBloomFilter(tail); m_filter = new BulkBloomFilter(tail);
} } else if(head == "Block") {
else if(head == "Block") {
m_filter = new BlockBloomFilter(tail); m_filter = new BlockBloomFilter(tail);
} } else if(head == "Multigrain"){
else if(head == "Multigrain"){
m_filter = new MultiGrainBloomFilter(tail); m_filter = new MultiGrainBloomFilter(tail);
} } else if(head == "MultiBitSel"){
else if(head == "MultiBitSel"){
m_filter = new MultiBitSelBloomFilter(tail); m_filter = new MultiBitSelBloomFilter(tail);
} } else if(head == "H3"){
else if(head == "H3"){
m_filter = new H3BloomFilter(tail); m_filter = new H3BloomFilter(tail);
} } else {
else {
assert(0); assert(0);
} }
} }
@@ -83,65 +66,80 @@ GenericBloomFilter::~GenericBloomFilter()
delete m_filter; delete m_filter;
} }
void GenericBloomFilter::clear() void
GenericBloomFilter::clear()
{ {
m_filter->clear(); m_filter->clear();
} }
void GenericBloomFilter::increment(const Address& addr) void
GenericBloomFilter::increment(const Address& addr)
{ {
m_filter->increment(addr); m_filter->increment(addr);
} }
void GenericBloomFilter::decrement(const Address& addr) void
GenericBloomFilter::decrement(const Address& addr)
{ {
m_filter->decrement(addr); m_filter->decrement(addr);
} }
void GenericBloomFilter::merge(GenericBloomFilter * other_filter) void
GenericBloomFilter::merge(GenericBloomFilter * other_filter)
{ {
m_filter->merge(other_filter->getFilter()); m_filter->merge(other_filter->getFilter());
} }
void GenericBloomFilter::set(const Address& addr) void
GenericBloomFilter::set(const Address& addr)
{ {
m_filter->set(addr); m_filter->set(addr);
} }
void GenericBloomFilter::unset(const Address& addr) void
GenericBloomFilter::unset(const Address& addr)
{ {
m_filter->unset(addr); m_filter->unset(addr);
} }
bool GenericBloomFilter::isSet(const Address& addr) bool
GenericBloomFilter::isSet(const Address& addr)
{ {
return m_filter->isSet(addr); return m_filter->isSet(addr);
} }
int GenericBloomFilter::getCount(const Address& addr) int
GenericBloomFilter::getCount(const Address& addr)
{ {
return m_filter->getCount(addr); return m_filter->getCount(addr);
} }
int GenericBloomFilter::getTotalCount() int
GenericBloomFilter::getTotalCount()
{ {
return m_filter->getTotalCount(); return m_filter->getTotalCount();
} }
int GenericBloomFilter::getIndex(const Address& addr) int
GenericBloomFilter::getIndex(const Address& addr)
{ {
return m_filter->getIndex(addr); return m_filter->getIndex(addr);
} }
int GenericBloomFilter::readBit(const int index) { int
GenericBloomFilter::readBit(const int index)
{
return m_filter->readBit(index); return m_filter->readBit(index);
} }
void GenericBloomFilter::writeBit(const int index, const int value) { void
GenericBloomFilter::writeBit(const int index, const int value)
{
m_filter->writeBit(index, value); m_filter->writeBit(index, value);
} }
void GenericBloomFilter::print(ostream& out) const void
GenericBloomFilter::print(ostream& out) const
{ {
return m_filter->print(out); return m_filter->print(out);
} }

View File

@@ -1,4 +1,3 @@
/* /*
* Copyright (c) 1999-2008 Mark D. Hill and David A. Wood * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
* All rights reserved. * All rights reserved.
@@ -27,26 +26,18 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
/* #ifndef __MEM_RUBY_FILTERS_GENERICBLOOMFILTER_HH__
* GenericBloomFilter.hh #define __MEM_RUBY_FILTERS_GENERICBLOOMFILTER_HH__
*
* Description:
*
*
*/
#ifndef GENERIC_BLOOM_FILTER_H
#define GENERIC_BLOOM_FILTER_H
#include "mem/ruby/common/Global.hh" #include "mem/ruby/common/Global.hh"
#include "mem/ruby/common/Address.hh" #include "mem/ruby/common/Address.hh"
#include "mem/ruby/filters/AbstractBloomFilter.hh" #include "mem/ruby/filters/AbstractBloomFilter.hh"
class GenericBloomFilter { class GenericBloomFilter
{
public: public:
// Constructors
GenericBloomFilter(string config); GenericBloomFilter(string config);
~GenericBloomFilter();
void clear(); void clear();
void increment(const Address& addr); void increment(const Address& addr);
@@ -54,7 +45,9 @@ public:
void merge(GenericBloomFilter * other_filter); void merge(GenericBloomFilter * other_filter);
void set(const Address& addr); void set(const Address& addr);
void unset(const Address& addr); void unset(const Address& addr);
AbstractBloomFilter * getFilter(){ AbstractBloomFilter *
getFilter()
{
return m_filter; return m_filter;
} }
@@ -71,23 +64,16 @@ public:
void print(ostream& out) const; void print(ostream& out) const;
void printConfig(ostream& out) { out << "GenericBloomFilter" << endl; } void printConfig(ostream& out) { out << "GenericBloomFilter" << endl; }
// Destructor
~GenericBloomFilter();
private: private:
AbstractBloomFilter* m_filter; AbstractBloomFilter* m_filter;
}; };
// Output operator definition inline ostream&
extern inline operator<<(ostream& out, const GenericBloomFilter& obj)
ostream& operator<<(ostream& out, const GenericBloomFilter& obj)
{ {
obj.print(out); obj.print(out);
out << flush; out << flush;
return out; return out;
} }
#endif // __MEM_RUBY_FILTERS_GENERICBLOOMFILTER_HH__
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -1,4 +1,3 @@
/* /*
* Copyright (c) 1999-2008 Mark D. Hill and David A. Wood * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
* All rights reserved. * All rights reserved.
@@ -27,29 +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.
*/ */
/* #ifndef __MEM_RUBY_FILTERS_H3BLOOMFILTER_HH__
* H3BloomFilter.hh #define __MEM_RUBY_FILTERS_H3BLOOMFILTER_HH__
*
* Description:
*
*
*/
#ifndef H3_BLOOM_FILTER_H
#define H3_BLOOM_FILTER_H
#include "mem/gems_common/Map.hh" #include "mem/gems_common/Map.hh"
#include "mem/ruby/common/Global.hh"
#include "mem/ruby/system/System.hh"
#include "mem/ruby/profiler/Profiler.hh"
#include "mem/ruby/common/Address.hh" #include "mem/ruby/common/Address.hh"
#include "mem/ruby/common/Global.hh"
#include "mem/ruby/filters/AbstractBloomFilter.hh" #include "mem/ruby/filters/AbstractBloomFilter.hh"
#include "mem/ruby/profiler/Profiler.hh"
#include "mem/ruby/system/System.hh"
class H3BloomFilter : public AbstractBloomFilter { class H3BloomFilter : public AbstractBloomFilter
{
public: public:
~H3BloomFilter();
H3BloomFilter(string config); H3BloomFilter(string config);
~H3BloomFilter();
void clear(); void clear();
void increment(const Address& addr); void increment(const Address& addr);
@@ -67,12 +58,13 @@ public:
int readBit(const int index); int readBit(const int index);
void writeBit(const int index, const int value); void writeBit(const int index, const int value);
int operator[](const int index) const{ int
operator[](const int index) const
{
return this->m_filter[index]; return this->m_filter[index];
} }
private: private:
int get_index(const Address& addr, int hashNumber); int get_index(const Address& addr, int hashNumber);
int hash_H3(uint64 value, int index); int hash_H3(uint64 value, int index);
@@ -88,15 +80,11 @@ private:
int m_count_bits; int m_count_bits;
int m_count; int m_count;
int primes_list[6];// = {9323,11279,10247,30637,25717,43711}; int primes_list[6];// = {9323,11279,10247,30637,25717,43711};
int mults_list[6]; //= {255,29,51,3,77,43}; int mults_list[6]; //= {255,29,51,3,77,43};
int adds_list[6]; //= {841,627,1555,241,7777,65391}; int adds_list[6]; //= {841,627,1555,241,7777,65391};
bool isParallel; bool isParallel;
}; };
#endif // __MEM_RUBY_FILTERS_H3BLOOMFILTER_HH__
#endif

View File

@@ -1,4 +1,3 @@
/* /*
* Copyright (c) 1999-2008 Mark D. Hill and David A. Wood * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
* All rights reserved. * All rights reserved.
@@ -27,17 +26,9 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
/*
* LSB_CountingBloomFilter.cc
*
* Description:
*
*
*/
#include "mem/ruby/filters/LSB_CountingBloomFilter.hh"
#include "mem/gems_common/Map.hh" #include "mem/gems_common/Map.hh"
#include "mem/ruby/common/Address.hh" #include "mem/ruby/common/Address.hh"
#include "mem/ruby/filters/LSB_CountingBloomFilter.hh"
LSB_CountingBloomFilter::LSB_CountingBloomFilter(string str) LSB_CountingBloomFilter::LSB_CountingBloomFilter(string str)
{ {
@@ -54,59 +45,68 @@ LSB_CountingBloomFilter::LSB_CountingBloomFilter(string str)
clear(); clear();
} }
LSB_CountingBloomFilter::~LSB_CountingBloomFilter(){ LSB_CountingBloomFilter::~LSB_CountingBloomFilter()
{
} }
void LSB_CountingBloomFilter::clear() void
LSB_CountingBloomFilter::clear()
{ {
for (int i = 0; i < m_filter_size; i++) { for (int i = 0; i < m_filter_size; i++) {
m_filter[i] = 0; m_filter[i] = 0;
} }
} }
void LSB_CountingBloomFilter::increment(const Address& addr) void
LSB_CountingBloomFilter::increment(const Address& addr)
{ {
int i = get_index(addr); int i = get_index(addr);
if (m_filter[i] < m_count); if (m_filter[i] < m_count)
m_filter[i] += 1; m_filter[i] += 1;
} }
void LSB_CountingBloomFilter::decrement(const Address& addr) void
LSB_CountingBloomFilter::decrement(const Address& addr)
{ {
int i = get_index(addr); int i = get_index(addr);
if (m_filter[i] > 0) if (m_filter[i] > 0)
m_filter[i] -= 1; m_filter[i] -= 1;
} }
void LSB_CountingBloomFilter::merge(AbstractBloomFilter * other_filter) void
LSB_CountingBloomFilter::merge(AbstractBloomFilter * other_filter)
{ {
// TODO // TODO
} }
void LSB_CountingBloomFilter::set(const Address& addr) void
LSB_CountingBloomFilter::set(const Address& addr)
{ {
// TODO // TODO
} }
void LSB_CountingBloomFilter::unset(const Address& addr) void
LSB_CountingBloomFilter::unset(const Address& addr)
{ {
// TODO // TODO
} }
bool LSB_CountingBloomFilter::isSet(const Address& addr) bool
LSB_CountingBloomFilter::isSet(const Address& addr)
{ {
// TODO // TODO
return false; return false;
} }
int
int LSB_CountingBloomFilter::getCount(const Address& addr) LSB_CountingBloomFilter::getCount(const Address& addr)
{ {
return m_filter[get_index(addr)]; return m_filter[get_index(addr)];
} }
int LSB_CountingBloomFilter::getTotalCount() int
LSB_CountingBloomFilter::getTotalCount()
{ {
int count = 0; int count = 0;
@@ -116,27 +116,36 @@ int LSB_CountingBloomFilter::getTotalCount()
return count; return count;
} }
int LSB_CountingBloomFilter::getIndex(const Address& addr) int
LSB_CountingBloomFilter::getIndex(const Address& addr)
{ {
return get_index(addr); return get_index(addr);
} }
void LSB_CountingBloomFilter::print(ostream& out) const void
LSB_CountingBloomFilter::print(ostream& out) const
{ {
} }
int LSB_CountingBloomFilter::readBit(const int index) { int
LSB_CountingBloomFilter::readBit(const int index)
{
return 0; return 0;
// TODO // TODO
} }
void LSB_CountingBloomFilter::writeBit(const int index, const int value) { void
LSB_CountingBloomFilter::writeBit(const int index, const int value)
{
// TODO // TODO
} }
int LSB_CountingBloomFilter::get_index(const Address& addr) int
LSB_CountingBloomFilter::get_index(const Address& addr)
{ {
return addr.bitSelect( RubySystem::getBlockSizeBits(), RubySystem::getBlockSizeBits() + m_filter_size_bits - 1); return addr.bitSelect(RubySystem::getBlockSizeBits(),
RubySystem::getBlockSizeBits() +
m_filter_size_bits - 1);
} }

View File

@@ -1,4 +1,3 @@
/* /*
* Copyright (c) 1999-2008 Mark D. Hill and David A. Wood * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
* All rights reserved. * All rights reserved.
@@ -27,27 +26,19 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
/* #ifndef __MEM_RUBY_FILTERS_LSBCOUNTINGBLOOMFILTER_HH__
* LSB_CountingBloomFilter.hh #define __MEM_RUBY_FILTERS_LSBCOUNTINGBLOOMFILTER_HH__
*
* Description:
*
*
*/
#ifndef LSB_COUNTING_BLOOM_FILTER_H
#define LSB_COUNTING_BLOOM_FILTER_H
#include "mem/gems_common/Map.hh" #include "mem/gems_common/Map.hh"
#include "mem/ruby/common/Global.hh"
#include "mem/ruby/common/Address.hh" #include "mem/ruby/common/Address.hh"
#include "mem/ruby/common/Global.hh"
#include "mem/ruby/filters/AbstractBloomFilter.hh" #include "mem/ruby/filters/AbstractBloomFilter.hh"
class LSB_CountingBloomFilter : public AbstractBloomFilter { class LSB_CountingBloomFilter : public AbstractBloomFilter
{
public: public:
~LSB_CountingBloomFilter();
LSB_CountingBloomFilter(string config); LSB_CountingBloomFilter(string config);
~LSB_CountingBloomFilter();
void clear(); void clear();
void increment(const Address& addr); void increment(const Address& addr);
@@ -66,7 +57,6 @@ public:
void print(ostream& out) const; void print(ostream& out) const;
private: private:
int get_index(const Address& addr); int get_index(const Address& addr);
Vector<int> m_filter; Vector<int> m_filter;
@@ -77,5 +67,4 @@ private:
int m_count; int m_count;
}; };
#endif // __MEM_RUBY_FILTERS_LSBCOUNTINGBLOOMFILTER_HH__
#endif

View File

@@ -1,4 +1,3 @@
/* /*
* Copyright (c) 1999-2008 Mark D. Hill and David A. Wood * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
* All rights reserved. * All rights reserved.
@@ -27,21 +26,12 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
/*
* NonCountingBloomFilter.cc
*
* Description:
*
*
*/
#include "mem/ruby/filters/MultiBitSelBloomFilter.hh"
#include "mem/gems_common/Map.hh" #include "mem/gems_common/Map.hh"
#include "mem/ruby/common/Address.hh" #include "mem/ruby/common/Address.hh"
#include "mem/ruby/filters/MultiBitSelBloomFilter.hh"
MultiBitSelBloomFilter::MultiBitSelBloomFilter(string str) MultiBitSelBloomFilter::MultiBitSelBloomFilter(string str)
{ {
string tail(str); string tail(str);
string head = string_split(tail, '_'); string head = string_split(tail, '_');
@@ -59,7 +49,8 @@ MultiBitSelBloomFilter::MultiBitSelBloomFilter(string str)
} else if (tail == "Parallel") { } else if (tail == "Parallel") {
isParallel = true; isParallel = true;
} else { } else {
cout << "ERROR: Incorrect config string for MultiBitSel Bloom! :" << str << endl; cout << "ERROR: Incorrect config string for MultiBitSel Bloom! :"
<< str << endl;
assert(0); assert(0);
} }
@@ -72,54 +63,59 @@ MultiBitSelBloomFilter::MultiBitSelBloomFilter(string str)
clear(); clear();
} }
MultiBitSelBloomFilter::~MultiBitSelBloomFilter(){ MultiBitSelBloomFilter::~MultiBitSelBloomFilter()
{
} }
void MultiBitSelBloomFilter::clear() void
MultiBitSelBloomFilter::clear()
{ {
for (int i = 0; i < m_filter_size; i++) { for (int i = 0; i < m_filter_size; i++) {
m_filter[i] = 0; m_filter[i] = 0;
} }
} }
void MultiBitSelBloomFilter::increment(const Address& addr) void
MultiBitSelBloomFilter::increment(const Address& addr)
{ {
// Not used // Not used
} }
void MultiBitSelBloomFilter::decrement(const Address& addr) void
MultiBitSelBloomFilter::decrement(const Address& addr)
{ {
// Not used // Not used
} }
void MultiBitSelBloomFilter::merge(AbstractBloomFilter * other_filter){ void
MultiBitSelBloomFilter::merge(AbstractBloomFilter *other_filter)
{
// assumes both filters are the same size! // assumes both filters are the same size!
MultiBitSelBloomFilter * temp = (MultiBitSelBloomFilter*) other_filter; MultiBitSelBloomFilter * temp = (MultiBitSelBloomFilter*) other_filter;
for(int i = 0; i < m_filter_size; ++i){ for(int i = 0; i < m_filter_size; ++i){
m_filter[i] |= (*temp)[i]; m_filter[i] |= (*temp)[i];
} }
} }
void MultiBitSelBloomFilter::set(const Address& addr) void
MultiBitSelBloomFilter::set(const Address& addr)
{ {
for (int i = 0; i < m_num_hashes; i++) { for (int i = 0; i < m_num_hashes; i++) {
int idx = get_index(addr, i); int idx = get_index(addr, i);
m_filter[idx] = 1; m_filter[idx] = 1;
//Profile hash value distribution
//g_system_ptr->getProfiler()->getXactProfiler()->profileHashValue(i, idx); //gem5:Arka for decomissioning of log_tm
} }
} }
void MultiBitSelBloomFilter::unset(const Address& addr) void
MultiBitSelBloomFilter::unset(const Address& addr)
{ {
cout << "ERROR: Unset should never be called in a Bloom filter"; cout << "ERROR: Unset should never be called in a Bloom filter";
assert(0); assert(0);
} }
bool MultiBitSelBloomFilter::isSet(const Address& addr) bool
MultiBitSelBloomFilter::isSet(const Address& addr)
{ {
bool res = true; bool res = true;
@@ -130,26 +126,31 @@ bool MultiBitSelBloomFilter::isSet(const Address& addr)
return res; return res;
} }
int
int MultiBitSelBloomFilter::getCount(const Address& addr) MultiBitSelBloomFilter::getCount(const Address& addr)
{ {
return isSet(addr)? 1: 0; return isSet(addr)? 1: 0;
} }
int MultiBitSelBloomFilter::getIndex(const Address& addr) int
MultiBitSelBloomFilter::getIndex(const Address& addr)
{ {
return 0; return 0;
} }
int MultiBitSelBloomFilter::readBit(const int index) { int
MultiBitSelBloomFilter::readBit(const int index)
{
return 0; return 0;
} }
void MultiBitSelBloomFilter::writeBit(const int index, const int value) { void
MultiBitSelBloomFilter::writeBit(const int index, const int value)
{
} }
int MultiBitSelBloomFilter::getTotalCount() int
MultiBitSelBloomFilter::getTotalCount()
{ {
int count = 0; int count = 0;
@@ -159,13 +160,17 @@ int MultiBitSelBloomFilter::getTotalCount()
return count; return count;
} }
void MultiBitSelBloomFilter::print(ostream& out) const void
MultiBitSelBloomFilter::print(ostream& out) const
{ {
} }
int MultiBitSelBloomFilter::get_index(const Address& addr, int i) int
MultiBitSelBloomFilter::get_index(const Address& addr, int i)
{ {
// m_skip_bits is used to perform BitSelect after skipping some bits. Used to simulate BitSel hashing on larger than cache-line granularities // m_skip_bits is used to perform BitSelect after skipping some
// bits. Used to simulate BitSel hashing on larger than cache-line
// granularities
uint64 x = (addr.getLineAddress()) >> m_skip_bits; uint64 x = (addr.getLineAddress()) >> m_skip_bits;
int y = hash_bitsel(x, i, m_num_hashes, 30, m_filter_size_bits); int y = hash_bitsel(x, i, m_num_hashes, 30, m_filter_size_bits);
//36-bit addresses, 6-bit cache lines //36-bit addresses, 6-bit cache lines
@@ -177,8 +182,10 @@ int MultiBitSelBloomFilter::get_index(const Address& addr, int i)
} }
} }
int
int MultiBitSelBloomFilter::hash_bitsel(uint64 value, int index, int jump, int maxBits, int numBits) { MultiBitSelBloomFilter::hash_bitsel(uint64 value, int index, int jump,
int maxBits, int numBits)
{
uint64 mask = 1; uint64 mask = 1;
int result = 0; int result = 0;
int bit, i; int bit, i;

View File

@@ -1,4 +1,3 @@
/* /*
* Copyright (c) 1999-2008 Mark D. Hill and David A. Wood * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
* All rights reserved. * All rights reserved.
@@ -27,29 +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.
*/ */
/* #ifndef __MEM_RUBY_FILTERS_MULTIBITSELBLOOMFILTER_HH__
* MultiBitSelBloomFilter.hh #define __MEM_RUBY_FILTERS_MULTIBITSELBLOOMFILTER_HH__
*
* Description:
*
*
*/
#ifndef MULTIBITSEL_BLOOM_FILTER_H
#define MULTIBITSEL_BLOOM_FILTER_H
#include "mem/gems_common/Map.hh" #include "mem/gems_common/Map.hh"
#include "mem/ruby/common/Global.hh"
#include "mem/ruby/system/System.hh"
#include "mem/ruby/profiler/Profiler.hh"
#include "mem/ruby/common/Address.hh" #include "mem/ruby/common/Address.hh"
#include "mem/ruby/common/Global.hh"
#include "mem/ruby/filters/AbstractBloomFilter.hh" #include "mem/ruby/filters/AbstractBloomFilter.hh"
#include "mem/ruby/profiler/Profiler.hh"
#include "mem/ruby/system/System.hh"
class MultiBitSelBloomFilter : public AbstractBloomFilter { class MultiBitSelBloomFilter : public AbstractBloomFilter
{
public: public:
~MultiBitSelBloomFilter();
MultiBitSelBloomFilter(string config); MultiBitSelBloomFilter(string config);
~MultiBitSelBloomFilter();
void clear(); void clear();
void increment(const Address& addr); void increment(const Address& addr);
@@ -67,15 +58,17 @@ public:
int readBit(const int index); int readBit(const int index);
void writeBit(const int index, const int value); void writeBit(const int index, const int value);
int operator[](const int index) const{ int
operator[](const int index) const
{
return this->m_filter[index]; return this->m_filter[index];
} }
private: private:
int get_index(const Address& addr, int hashNumber); int get_index(const Address& addr, int hashNumber);
int hash_bitsel(uint64 value, int index, int jump, int maxBits, int numBits); int hash_bitsel(uint64 value, int index, int jump, int maxBits,
int numBits);
Vector<int> m_filter; Vector<int> m_filter;
int m_filter_size; int m_filter_size;
@@ -90,7 +83,6 @@ private:
int m_count; int m_count;
bool isParallel; bool isParallel;
}; };
#endif #endif // __MEM_RUBY_FILTERS_MULTIBITSELBLOOMFILTER_HH__

View File

@@ -1,4 +1,3 @@
/* /*
* Copyright (c) 1999-2008 Mark D. Hill and David A. Wood * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
* All rights reserved. * All rights reserved.
@@ -27,17 +26,9 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
/*
* MultiGrainBloomFilter.cc
*
* Description:
*
*
*/
#include "mem/ruby/filters/MultiGrainBloomFilter.hh"
#include "mem/gems_common/Map.hh" #include "mem/gems_common/Map.hh"
#include "mem/ruby/common/Address.hh" #include "mem/ruby/common/Address.hh"
#include "mem/ruby/filters/MultiGrainBloomFilter.hh"
MultiGrainBloomFilter::MultiGrainBloomFilter(string str) MultiGrainBloomFilter::MultiGrainBloomFilter(string str)
{ {
@@ -46,7 +37,8 @@ MultiGrainBloomFilter::MultiGrainBloomFilter(string str)
// split into the 2 filter sizes // split into the 2 filter sizes
string head = string_split(tail, '_'); string head = string_split(tail, '_');
// head contains size of 1st bloom filter, tail contains size of 2nd bloom filter // head contains size of 1st bloom filter, tail contains size of
// 2nd bloom filter
m_filter_size = atoi(head.c_str()); m_filter_size = atoi(head.c_str());
m_filter_size_bits = log_int(m_filter_size); m_filter_size_bits = log_int(m_filter_size);
@@ -59,10 +51,12 @@ MultiGrainBloomFilter::MultiGrainBloomFilter(string str)
clear(); clear();
} }
MultiGrainBloomFilter::~MultiGrainBloomFilter(){ MultiGrainBloomFilter::~MultiGrainBloomFilter()
{
} }
void MultiGrainBloomFilter::clear() void
MultiGrainBloomFilter::clear()
{ {
for (int i = 0; i < m_filter_size; i++) { for (int i = 0; i < m_filter_size; i++) {
m_filter[i] = 0; m_filter[i] = 0;
@@ -72,23 +66,27 @@ void MultiGrainBloomFilter::clear()
} }
} }
void MultiGrainBloomFilter::increment(const Address& addr) void
MultiGrainBloomFilter::increment(const Address& addr)
{ {
// Not used // Not used
} }
void MultiGrainBloomFilter::decrement(const Address& addr) void
MultiGrainBloomFilter::decrement(const Address& addr)
{ {
// Not used // Not used
} }
void MultiGrainBloomFilter::merge(AbstractBloomFilter * other_filter) void
MultiGrainBloomFilter::merge(AbstractBloomFilter *other_filter)
{ {
// TODO // TODO
} }
void MultiGrainBloomFilter::set(const Address& addr) void
MultiGrainBloomFilter::set(const Address& addr)
{ {
int i = get_block_index(addr); int i = get_block_index(addr);
assert(i < m_filter_size); assert(i < m_filter_size);
@@ -98,12 +96,14 @@ void MultiGrainBloomFilter::set(const Address& addr)
} }
void MultiGrainBloomFilter::unset(const Address& addr) void
MultiGrainBloomFilter::unset(const Address& addr)
{ {
// not used // not used
} }
bool MultiGrainBloomFilter::isSet(const Address& addr) bool
MultiGrainBloomFilter::isSet(const Address& addr)
{ {
int i = get_block_index(addr); int i = get_block_index(addr);
assert(i < m_filter_size); assert(i < m_filter_size);
@@ -112,13 +112,15 @@ bool MultiGrainBloomFilter::isSet(const Address& addr)
return (m_filter[i] && m_page_filter[i]); return (m_filter[i] && m_page_filter[i]);
} }
int MultiGrainBloomFilter::getCount(const Address& addr) int
MultiGrainBloomFilter::getCount(const Address& addr)
{ {
// not used // not used
return 0; return 0;
} }
int MultiGrainBloomFilter::getTotalCount() int
MultiGrainBloomFilter::getTotalCount()
{ {
int count = 0; int count = 0;
@@ -133,36 +135,47 @@ int MultiGrainBloomFilter::getTotalCount()
return count; return count;
} }
int MultiGrainBloomFilter::getIndex(const Address& addr) int
MultiGrainBloomFilter::getIndex(const Address& addr)
{ {
return 0; return 0;
// TODO // TODO
} }
int MultiGrainBloomFilter::readBit(const int index) { int
MultiGrainBloomFilter::readBit(const int index)
{
return 0; return 0;
// TODO // TODO
} }
void MultiGrainBloomFilter::writeBit(const int index, const int value) { void
MultiGrainBloomFilter::writeBit(const int index, const int value)
{
// TODO // TODO
} }
void MultiGrainBloomFilter::print(ostream& out) const void
MultiGrainBloomFilter::print(ostream& out) const
{ {
} }
int MultiGrainBloomFilter::get_block_index(const Address& addr) int
MultiGrainBloomFilter::get_block_index(const Address& addr)
{ {
// grap a chunk of bits after byte offset // grap a chunk of bits after byte offset
return addr.bitSelect( RubySystem::getBlockSizeBits(), RubySystem::getBlockSizeBits() + m_filter_size_bits - 1); return addr.bitSelect(RubySystem::getBlockSizeBits(),
RubySystem::getBlockSizeBits() +
m_filter_size_bits - 1);
} }
int MultiGrainBloomFilter::get_page_index(const Address & addr) int
MultiGrainBloomFilter::get_page_index(const Address & addr)
{ {
int bits = RubySystem::getBlockSizeBits() + m_filter_size_bits - 1;
// grap a chunk of bits after first chunk // grap a chunk of bits after first chunk
return addr.bitSelect( RubySystem::getBlockSizeBits() + m_filter_size_bits - 1, return addr.bitSelect(bits, bits + m_page_filter_size_bits - 1);
RubySystem::getBlockSizeBits() + m_filter_size_bits - 1 + m_page_filter_size_bits - 1);
} }

View File

@@ -1,4 +1,3 @@
/* /*
* Copyright (c) 1999-2008 Mark D. Hill and David A. Wood * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
* All rights reserved. * All rights reserved.
@@ -27,27 +26,19 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
/* #ifndef __MEM_RUBY_FILTERS_MULTIGRAINBLOOMFILTER_HH__
* MultiGrainBloomFilter.hh #define __MEM_RUBY_FILTERS_MULTIGRAINBLOOMFILTER_HH__
*
* Description:
*
*
*/
#ifndef MULTIGRAIN_BLOOM_FILTER_H
#define MULTIGRAIN_BLOOM_FILTER_H
#include "mem/gems_common/Map.hh" #include "mem/gems_common/Map.hh"
#include "mem/ruby/common/Global.hh"
#include "mem/ruby/common/Address.hh" #include "mem/ruby/common/Address.hh"
#include "mem/ruby/common/Global.hh"
#include "mem/ruby/filters/AbstractBloomFilter.hh" #include "mem/ruby/filters/AbstractBloomFilter.hh"
class MultiGrainBloomFilter : public AbstractBloomFilter { class MultiGrainBloomFilter : public AbstractBloomFilter
{
public: public:
~MultiGrainBloomFilter();
MultiGrainBloomFilter(string str); MultiGrainBloomFilter(string str);
~MultiGrainBloomFilter();
void clear(); void clear();
void increment(const Address& addr); void increment(const Address& addr);
@@ -66,7 +57,6 @@ public:
void print(ostream& out) const; void print(ostream& out) const;
private: private:
int get_block_index(const Address& addr); int get_block_index(const Address& addr);
int get_page_index(const Address & addr); int get_page_index(const Address & addr);
@@ -83,5 +73,4 @@ private:
int m_count; int m_count;
}; };
#endif // __MEM_RUBY_FILTERS_MULTIGRAINBLOOMFILTER_HH__
#endif

View File

@@ -1,4 +1,3 @@
/* /*
* Copyright (c) 1999-2008 Mark D. Hill and David A. Wood * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
* All rights reserved. * All rights reserved.
@@ -27,17 +26,9 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
/*
* NonCountingBloomFilter.cc
*
* Description:
*
*
*/
#include "mem/ruby/filters/NonCountingBloomFilter.hh"
#include "mem/gems_common/Map.hh" #include "mem/gems_common/Map.hh"
#include "mem/ruby/common/Address.hh" #include "mem/ruby/common/Address.hh"
#include "mem/ruby/filters/NonCountingBloomFilter.hh"
NonCountingBloomFilter::NonCountingBloomFilter(string str) NonCountingBloomFilter::NonCountingBloomFilter(string str)
{ {
@@ -49,66 +40,74 @@ NonCountingBloomFilter::NonCountingBloomFilter(string str)
m_offset = atoi(tail.c_str()); m_offset = atoi(tail.c_str());
m_filter_size_bits = log_int(m_filter_size); m_filter_size_bits = log_int(m_filter_size);
m_filter.setSize(m_filter_size); m_filter.setSize(m_filter_size);
clear(); clear();
} }
NonCountingBloomFilter::~NonCountingBloomFilter(){ NonCountingBloomFilter::~NonCountingBloomFilter()
{
} }
void NonCountingBloomFilter::clear() void
NonCountingBloomFilter::clear()
{ {
for (int i = 0; i < m_filter_size; i++) { for (int i = 0; i < m_filter_size; i++) {
m_filter[i] = 0; m_filter[i] = 0;
} }
} }
void NonCountingBloomFilter::increment(const Address& addr) void
NonCountingBloomFilter::increment(const Address& addr)
{ {
// Not used // Not used
} }
void
void NonCountingBloomFilter::decrement(const Address& addr) NonCountingBloomFilter::decrement(const Address& addr)
{ {
// Not used // Not used
} }
void NonCountingBloomFilter::merge(AbstractBloomFilter * other_filter){ void
NonCountingBloomFilter::merge(AbstractBloomFilter *other_filter)
{
// assumes both filters are the same size! // assumes both filters are the same size!
NonCountingBloomFilter * temp = (NonCountingBloomFilter*) other_filter; NonCountingBloomFilter * temp = (NonCountingBloomFilter*) other_filter;
for(int i = 0; i < m_filter_size; ++i){ for(int i = 0; i < m_filter_size; ++i){
m_filter[i] |= (*temp)[i]; m_filter[i] |= (*temp)[i];
} }
} }
void NonCountingBloomFilter::set(const Address& addr) void
NonCountingBloomFilter::set(const Address& addr)
{ {
int i = get_index(addr); int i = get_index(addr);
m_filter[i] = 1; m_filter[i] = 1;
} }
void NonCountingBloomFilter::unset(const Address& addr) void
NonCountingBloomFilter::unset(const Address& addr)
{ {
int i = get_index(addr); int i = get_index(addr);
m_filter[i] = 0; m_filter[i] = 0;
} }
bool NonCountingBloomFilter::isSet(const Address& addr) bool
NonCountingBloomFilter::isSet(const Address& addr)
{ {
int i = get_index(addr); int i = get_index(addr);
return (m_filter[i]); return (m_filter[i]);
} }
int NonCountingBloomFilter::getCount(const Address& addr) int
NonCountingBloomFilter::getCount(const Address& addr)
{ {
return m_filter[get_index(addr)]; return m_filter[get_index(addr)];
} }
int NonCountingBloomFilter::getTotalCount() int
NonCountingBloomFilter::getTotalCount()
{ {
int count = 0; int count = 0;
@@ -118,27 +117,35 @@ int NonCountingBloomFilter::getTotalCount()
return count; return count;
} }
void NonCountingBloomFilter::print(ostream& out) const void
NonCountingBloomFilter::print(ostream& out) const
{ {
} }
int NonCountingBloomFilter::getIndex(const Address& addr) int
NonCountingBloomFilter::getIndex(const Address& addr)
{ {
return get_index(addr); return get_index(addr);
} }
int NonCountingBloomFilter::readBit(const int index) { int
NonCountingBloomFilter::readBit(const int index)
{
return m_filter[index]; return m_filter[index];
} }
void NonCountingBloomFilter::writeBit(const int index, const int value) { void
NonCountingBloomFilter::writeBit(const int index, const int value)
{
m_filter[index] = value; m_filter[index] = value;
} }
int NonCountingBloomFilter::get_index(const Address& addr) int
NonCountingBloomFilter::get_index(const Address& addr)
{ {
return addr.bitSelect(RubySystem::getBlockSizeBits() + m_offset, return addr.bitSelect(RubySystem::getBlockSizeBits() + m_offset,
RubySystem::getBlockSizeBits() + m_offset + m_filter_size_bits - 1); RubySystem::getBlockSizeBits() + m_offset +
m_filter_size_bits - 1);
} }

View File

@@ -1,4 +1,3 @@
/* /*
* Copyright (c) 1999-2008 Mark D. Hill and David A. Wood * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
* All rights reserved. * All rights reserved.
@@ -27,27 +26,19 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
/* #ifndef __MEM_RUBY_FILTERS_NONCOUNTINGBLOOMFILTER_HH__
* NonCountingBloomFilter.hh #define __MEM_RUBY_FILTERS_NONCOUNTINGBLOOMFILTER_HH__
*
* Description:
*
*
*/
#ifndef NONCOUNTING_BLOOM_FILTER_H
#define NONCOUNTING_BLOOM_FILTER_H
#include "mem/gems_common/Map.hh" #include "mem/gems_common/Map.hh"
#include "mem/ruby/common/Global.hh"
#include "mem/ruby/common/Address.hh" #include "mem/ruby/common/Address.hh"
#include "mem/ruby/common/Global.hh"
#include "mem/ruby/filters/AbstractBloomFilter.hh" #include "mem/ruby/filters/AbstractBloomFilter.hh"
class NonCountingBloomFilter : public AbstractBloomFilter { class NonCountingBloomFilter : public AbstractBloomFilter
{
public: public:
~NonCountingBloomFilter();
NonCountingBloomFilter(string config); NonCountingBloomFilter(string config);
~NonCountingBloomFilter();
void clear(); void clear();
void increment(const Address& addr); void increment(const Address& addr);
@@ -66,12 +57,13 @@ public:
void print(ostream& out) const; void print(ostream& out) const;
int operator[](const int index) const{ int
operator[](const int index) const
{
return this->m_filter[index]; return this->m_filter[index];
} }
private: private:
int get_index(const Address& addr); int get_index(const Address& addr);
Vector<int> m_filter; Vector<int> m_filter;
@@ -83,5 +75,4 @@ private:
int m_count; int m_count;
}; };
#endif // __MEM_RUBY_FILTERS_NONCOUNTINGBLOOMFILTER_HH__
#endif

View File

@@ -30,15 +30,16 @@
#include <algorithm> #include <algorithm>
#include "config/gems_root.hh" #include "config/gems_root.hh"
#include "mem/ruby/common/Address.hh"
#include "mem/ruby/eventqueue/RubyEventQueue.hh"
#include "mem/ruby/libruby_internal.hh" #include "mem/ruby/libruby_internal.hh"
#include "mem/ruby/recorder/Tracer.hh"
#include "mem/ruby/system/MemoryVector.hh"
#include "mem/ruby/system/RubyPort.hh" #include "mem/ruby/system/RubyPort.hh"
#include "mem/ruby/system/System.hh" #include "mem/ruby/system/System.hh"
#include "mem/ruby/eventqueue/RubyEventQueue.hh"
#include "mem/ruby/system/MemoryVector.hh"
#include "mem/ruby/common/Address.hh"
#include "mem/ruby/recorder/Tracer.hh"
string RubyRequestType_to_string(const RubyRequestType& obj) string
RubyRequestType_to_string(const RubyRequestType& obj)
{ {
switch(obj) { switch(obj) {
case RubyRequestType_IFETCH: case RubyRequestType_IFETCH:
@@ -62,7 +63,8 @@ string RubyRequestType_to_string(const RubyRequestType& obj)
} }
} }
RubyRequestType string_to_RubyRequestType(std::string str) RubyRequestType
string_to_RubyRequestType(std::string str)
{ {
if (str == "IFETCH") if (str == "IFETCH")
return RubyRequestType_IFETCH; return RubyRequestType_IFETCH;
@@ -83,14 +85,16 @@ RubyRequestType string_to_RubyRequestType(std::string str)
return RubyRequestType_NULL; return RubyRequestType_NULL;
} }
ostream& operator<<(ostream& out, const RubyRequestType& obj) ostream&
operator<<(ostream& out, const RubyRequestType& obj)
{ {
out << RubyRequestType_to_string(obj); out << RubyRequestType_to_string(obj);
out << flush; out << flush;
return out; return out;
} }
ostream& operator<<(std::ostream& out, const RubyRequest& obj) ostream&
operator<<(std::ostream& out, const RubyRequest& obj)
{ {
out << hex << "0x" << obj.paddr << " data: 0x" << flush; out << hex << "0x" << obj.paddr << " data: 0x" << flush;
for (int i = 0; i < obj.len; i++) { for (int i = 0; i < obj.len; i++) {
@@ -100,7 +104,8 @@ ostream& operator<<(std::ostream& out, const RubyRequest& obj)
return out; return out;
} }
vector<string> tokenizeString(string str, string delims) vector<string>
tokenizeString(string str, string delims)
{ {
vector<string> tokens; vector<string> tokens;
char* pch; char* pch;
@@ -120,7 +125,6 @@ vector<string> tokenizeString(string str, string delims)
return tokens; return tokens;
} }
/* /*
* The current state of M5/Ruby integration breaks the libruby * The current state of M5/Ruby integration breaks the libruby
* interface. This code is ifdef'd out for now so that we can move * interface. This code is ifdef'd out for now so that we can move
@@ -129,7 +133,8 @@ vector<string> tokenizeString(string str, string delims)
* later date. * later date.
*/ */
#if 0 #if 0
void libruby_init(const char* cfg_filename) void
libruby_init(const char* cfg_filename)
{ {
ifstream cfg_output(cfg_filename); ifstream cfg_output(cfg_filename);
@@ -157,7 +162,9 @@ void libruby_init(const char* cfg_filename)
} }
#endif #endif
RubyPortHandle libruby_get_port(const char* port_name, void (*hit_callback)(int64_t access_id)) RubyPortHandle
libruby_get_port(const char* port_name,
void (*hit_callback)(int64_t access_id))
{ {
// //
// Fix me: Hit callback is now a non-static member function pointer of // Fix me: Hit callback is now a non-static member function pointer of
@@ -175,17 +182,20 @@ RubyPortHandle libruby_get_port_by_name(const char* port_name)
return NULL;//static_cast<RubyPortHandle>(RubySystem::getPortOnly(port_name)); return NULL;//static_cast<RubyPortHandle>(RubySystem::getPortOnly(port_name));
} }
void libruby_write_ram(uint64_t paddr, uint8_t* data, int len) void
libruby_write_ram(uint64_t paddr, uint8_t* data, int len)
{ {
RubySystem::getMemoryVector()->write(Address(paddr), data, len); RubySystem::getMemoryVector()->write(Address(paddr), data, len);
} }
void libruby_read_ram(uint64_t paddr, uint8_t* data, int len) void
libruby_read_ram(uint64_t paddr, uint8_t* data, int len)
{ {
RubySystem::getMemoryVector()->read(Address(paddr), data, len); RubySystem::getMemoryVector()->read(Address(paddr), data, len);
} }
int64_t libruby_issue_request(RubyPortHandle p, struct RubyRequest request) int64_t
libruby_issue_request(RubyPortHandle p, struct RubyRequest request)
{ {
// //
// Fix me: Ports should now be accessed using the python configuration // Fix me: Ports should now be accessed using the python configuration
@@ -194,45 +204,58 @@ int64_t libruby_issue_request(RubyPortHandle p, struct RubyRequest request)
return 0;//return static_cast<RubyPort*>(p)->makeRequest(request); return 0;//return static_cast<RubyPort*>(p)->makeRequest(request);
} }
int libruby_tick(int n) int
libruby_tick(int n)
{ {
RubySystem::getEventQueue()->triggerEvents(RubySystem::getEventQueue()->getTime() + n); RubyEventQueue *eventq = RubySystem::getEventQueue();
eventq->triggerEvents(eventq->getTime() + n);
return 0; return 0;
} }
void libruby_destroy() void
libruby_destroy()
{ {
} }
const char* libruby_last_error() const char*
libruby_last_error()
{ {
return ""; return "";
} }
void libruby_print_config(std::ostream & out) void
libruby_print_config(std::ostream & out)
{ {
RubySystem::printConfig(out); RubySystem::printConfig(out);
} }
void libruby_print_stats(std::ostream & out) void
libruby_print_stats(std::ostream & out)
{ {
RubySystem::printStats(out); RubySystem::printStats(out);
} }
void libruby_playback_trace(char * trace_filename) void
libruby_playback_trace(char * trace_filename)
{ {
RubySystem::getTracer()->playbackTrace(trace_filename); RubySystem::getTracer()->playbackTrace(trace_filename);
} }
void libruby_start_tracing(char * record_filename) { void
libruby_start_tracing(char * record_filename)
{
// start the trace // start the trace
RubySystem::getTracer()->startTrace(record_filename); RubySystem::getTracer()->startTrace(record_filename);
} }
void libruby_stop_tracing() { void
libruby_stop_tracing()
{
// start the trace // start the trace
RubySystem::getTracer()->stopTrace(); RubySystem::getTracer()->stopTrace();
} }
uint64_t libruby_get_time() { uint64_t
libruby_get_time()
{
return RubySystem::getCycleCount(0); return RubySystem::getCycleCount(0);
} }

View File

@@ -26,11 +26,12 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#ifndef LIBRUBY_H #ifndef __MEM_RUBY_LIBRUBY_HH__
#define LIBRUBY_H #define __MEM_RUBY_LIBRUBY_HH__
#include <stdint.h>
#include <ostream> #include <ostream>
#include "base/types.hh"
#include "mem/packet.hh" #include "mem/packet.hh"
typedef void* RubyPortHandle; typedef void* RubyPortHandle;
@@ -52,7 +53,8 @@ enum RubyAccessMode {
RubyAccessMode_Device RubyAccessMode_Device
}; };
struct RubyRequest { struct RubyRequest
{
uint64_t paddr; uint64_t paddr;
uint8_t* data; uint8_t* data;
int len; int len;
@@ -90,7 +92,8 @@ std::ostream& operator<<(std::ostream& out, const RubyRequest& obj);
void libruby_init(const char* cfg_file); void libruby_init(const char* cfg_file);
/** /**
* Tear down a configured system. Must be invoked after a call to libruby_init. * Tear down a configured system. Must be invoked after a call to
* libruby_init.
*/ */
void libruby_destroy(); void libruby_destroy();
@@ -105,7 +108,8 @@ const char* libruby_last_error();
* this port to use when a request completes. Only one handle to a * this port to use when a request completes. Only one handle to a
* port is allowed at a time. * port is allowed at a time.
*/ */
RubyPortHandle libruby_get_port(const char* name, void (*hit_callback)(int64_t access_id)); RubyPortHandle libruby_get_port(const char* name,
void (*hit_callback)(int64_t access_id));
/** /**
* Retrieve a handle to a RubyPort object, identified by name in the * Retrieve a handle to a RubyPort object, identified by name in the
@@ -113,7 +117,6 @@ RubyPortHandle libruby_get_port(const char* name, void (*hit_callback)(int64_t a
*/ */
RubyPortHandle libruby_get_port_by_name(const char* name); RubyPortHandle libruby_get_port_by_name(const char* name);
/** /**
* issue_request returns a unique access_id to identify the ruby * issue_request returns a unique access_id to identify the ruby
* transaction. This access_id is later returned to the caller via * transaction. This access_id is later returned to the caller via
@@ -170,4 +173,5 @@ void libruby_stop_tracing();
* get time * get time
*/ */
uint64_t libruby_get_time(); uint64_t libruby_get_time();
#endif
#endif // __MEM_RUBY_LIBRUBY_HH__

View File

@@ -26,16 +26,16 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#ifndef LIBRUBY_INTERNAL_H #ifndef __MEM_RUBY_LIBRUBY_INTERNAL_HH__
#define LIBRUBY_INTERNAL_H #define __MEM_RUBY_LIBRUBY_INTERNAL_HH__
#include "mem/ruby/libruby.hh"
#include <ostream> #include <ostream>
#include <string> #include <string>
#include "mem/ruby/libruby.hh"
std::string RubyRequestType_to_string(const RubyRequestType& obj); std::string RubyRequestType_to_string(const RubyRequestType& obj);
RubyRequestType string_to_RubyRequestType(std::string); RubyRequestType string_to_RubyRequestType(std::string);
std::ostream& operator<<(std::ostream& out, const RubyRequestType& obj); std::ostream& operator<<(std::ostream& out, const RubyRequestType& obj);
#endif #endif // __MEM_RUBY_LIBRUBY_INTERNAL_HH__

View File

@@ -1,4 +1,3 @@
/* /*
* Copyright (c) 1999-2008 Mark D. Hill and David A. Wood * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
* All rights reserved. * All rights reserved.
@@ -27,21 +26,15 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
/*
* $Id$
*
* Description: See AbstractCacheEntry.hh
*
*/
#include "mem/ruby/slicc_interface/AbstractCacheEntry.hh" #include "mem/ruby/slicc_interface/AbstractCacheEntry.hh"
AbstractCacheEntry::AbstractCacheEntry() { AbstractCacheEntry::AbstractCacheEntry()
{
m_Address.setAddress(0); m_Address.setAddress(0);
m_Permission = AccessPermission_NotPresent; m_Permission = AccessPermission_NotPresent;
} }
// still need to define destructor for subclasses AbstractCacheEntry::~AbstractCacheEntry()
AbstractCacheEntry::~AbstractCacheEntry() { {
} }

View File

@@ -1,4 +1,3 @@
/* /*
* Copyright (c) 1999-2008 Mark D. Hill and David A. Wood * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
* All rights reserved. * All rights reserved.
@@ -28,49 +27,39 @@
*/ */
/* /*
* $Id$ * Common base class for a machine node.
*
* Description: Common base class for a machine node.
*
*/ */
#ifndef AbstractCacheEntry_H #ifndef __MEM_RUBY_SLICC_INTERFACE_ABSTRACTCACHEENTRY_HH__
#define AbstractCacheEntry_H #define __MEM_RUBY_SLICC_INTERFACE_ABSTRACTCACHEENTRY_HH__
#include "mem/ruby/common/Global.hh"
#include "mem/ruby/common/Address.hh"
#include "mem/protocol/AccessPermission.hh" #include "mem/protocol/AccessPermission.hh"
#include "mem/ruby/common/Address.hh"
#include "mem/ruby/common/Global.hh"
#include "mem/ruby/slicc_interface/AbstractEntry.hh" #include "mem/ruby/slicc_interface/AbstractEntry.hh"
class DataBlock; class DataBlock;
class AbstractCacheEntry : public AbstractEntry { class AbstractCacheEntry : public AbstractEntry
{
public: public:
// Constructors
AbstractCacheEntry(); AbstractCacheEntry();
// Destructor, prevent it from instantiation
virtual ~AbstractCacheEntry() = 0; virtual ~AbstractCacheEntry() = 0;
// Data Members (m_ prefix)
Address m_Address; // Address of this block, required by CacheMemory Address m_Address; // Address of this block, required by CacheMemory
Time m_LastRef; // Last time this block was referenced, required by CacheMemory Time m_LastRef; // Last time this block was referenced, required
AccessPermission m_Permission; // Access permission for this block, required by CacheMemory // by CacheMemory
AccessPermission m_Permission; // Access permission for this
// block, required by CacheMemory
}; };
// Output operator declaration inline ostream&
ostream& operator<<(ostream& out, const AbstractCacheEntry& obj); operator<<(ostream& out, const AbstractCacheEntry& obj)
// ******************* Definitions *******************
// Output operator definition
extern inline
ostream& operator<<(ostream& out, const AbstractCacheEntry& obj)
{ {
obj.print(out); obj.print(out);
out << flush; out << flush;
return out; return out;
} }
#endif //AbstractCacheEntry_H #endif // __MEM_RUBY_SLICC_INTERFACE_ABSTRACTCACHEENTRY_HH__

View File

@@ -26,8 +26,8 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#ifndef ABSTRACTCONTROLLER_H #ifndef __MEM_RUBY_SLICC_INTERFACE_ABSTRACTCONTROLLER_HH__
#define ABSTRACTCONTROLLER_H #define __MEM_RUBY_SLICC_INTERFACE_ABSTRACTCONTROLLER_HH__
#include "sim/sim_object.hh" #include "sim/sim_object.hh"
#include "params/RubyController.hh" #include "params/RubyController.hh"
@@ -40,7 +40,8 @@
class MessageBuffer; class MessageBuffer;
class Network; class Network;
class AbstractController : public SimObject, public Consumer { class AbstractController : public SimObject, public Consumer
{
public: public:
typedef RubyControllerParams Params; typedef RubyControllerParams Params;
AbstractController(const Params *p) : SimObject(p) {} AbstractController(const Params *p) : SimObject(p) {}
@@ -49,7 +50,8 @@ public:
// virtual int getNumberOfControllers() const = 0; // virtual int getNumberOfControllers() const = 0;
virtual MessageBuffer* getMandatoryQueue() const = 0; virtual MessageBuffer* getMandatoryQueue() const = 0;
virtual const int & getVersion() const = 0; virtual const int & getVersion() const = 0;
virtual const string toString() const = 0; // returns text version of controller type virtual const string toString() const = 0; // returns text version of
// controller type
virtual const string getName() const = 0; // return instance name virtual const string getName() const = 0; // return instance name
virtual const MachineType getMachineType() const = 0; virtual const MachineType getMachineType() const = 0;
virtual void blockOnQueue(Address, MessageBuffer*) = 0; virtual void blockOnQueue(Address, MessageBuffer*) = 0;
@@ -62,7 +64,6 @@ public:
virtual void wakeup() = 0; virtual void wakeup() = 0;
// virtual void dumpStats(ostream & out) = 0; // virtual void dumpStats(ostream & out) = 0;
virtual void clearStats() = 0; virtual void clearStats() = 0;
}; };
#endif #endif // __MEM_RUBY_SLICC_INTERFACE_ABSTRACTCONTROLLER_HH__

View File

@@ -1,4 +1,3 @@
/* /*
* Copyright (c) 1999-2008 Mark D. Hill and David A. Wood * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
* All rights reserved. * All rights reserved.
@@ -29,10 +28,10 @@
#include "mem/ruby/slicc_interface/AbstractEntry.hh" #include "mem/ruby/slicc_interface/AbstractEntry.hh"
// Must define constructor and destructor in subclasses AbstractEntry::AbstractEntry()
AbstractEntry::AbstractEntry() { {
} }
AbstractEntry::~AbstractEntry() { AbstractEntry::~AbstractEntry()
{
} }

View File

@@ -1,4 +1,3 @@
/* /*
* Copyright (c) 1999-2008 Mark D. Hill and David A. Wood * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
* All rights reserved. * All rights reserved.
@@ -27,47 +26,35 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#ifndef AbstractEntry_H #ifndef __MEM_RUBY_SLICC_INTERFACE_ABSTRACTENTRY_HH__
#define AbstractEntry_H #define __MEM_RUBY_SLICC_INTERFACE_ABSTRACTENTRY_HH__
#include "mem/ruby/common/Global.hh"
#include "mem/ruby/common/Address.hh" #include "mem/ruby/common/Address.hh"
#include "mem/ruby/common/Global.hh"
#include "mem/protocol/AccessPermission.hh" #include "mem/protocol/AccessPermission.hh"
class DataBlock; class DataBlock;
class AbstractEntry { class AbstractEntry
{
public: public:
// Constructors
AbstractEntry(); AbstractEntry();
// Destructor, prevent it from instantiation
virtual ~AbstractEntry() = 0; virtual ~AbstractEntry() = 0;
// Public Methods // The methods below are those called by ruby runtime, add when it
// is absolutely necessary and should all be virtual function.
// The methods below are those called by ruby runtime, add when it is
// absolutely necessary and should all be virtual function.
virtual DataBlock& getDataBlk() = 0; virtual DataBlock& getDataBlk() = 0;
virtual void print(ostream& out) const = 0; virtual void print(ostream& out) const = 0;
}; };
// Output operator declaration inline ostream&
ostream& operator<<(ostream& out, const AbstractEntry& obj); operator<<(ostream& out, const AbstractEntry& obj)
// ******************* Definitions *******************
// Output operator definition
extern inline
ostream& operator<<(ostream& out, const AbstractEntry& obj)
{ {
obj.print(out); obj.print(out);
out << flush; out << flush;
return out; return out;
} }
#endif //AbstractEntry_H #endif // __MEM_RUBY_SLICC_INTERFACE_ABSTRACTENTRY_HH__

View File

@@ -1,4 +1,3 @@
/* /*
* Copyright (c) 1999-2008 Mark D. Hill and David A. Wood * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
* All rights reserved. * All rights reserved.
@@ -28,33 +27,24 @@
*/ */
/* /*
* $Id$ * Define all possible protocol parameters and their default value
* * here. Normally, all parameters should have default value "false"
* Description: Define all possible protocol parameters and their * means the feature of the protocol is turned off.
* default value here. Normally, all parameters should
* have default value "false" means the feature of the
* protocol is turned off.
*
*/ */
#ifndef AbstractProtocol_H #ifndef __MEM_RUBY_SLICC_INTERFACE_ABSTRACTPROTOCOL_HH__
#define AbstractProtocol_H #define __MEM_RUBY_SLICC_INTERFACE_ABSTRACTPROTOCOL_HH__
class AbstractProtocol { class AbstractProtocol
{
public: public:
// Constructors AbstractProtocol() {}
AbstractProtocol() {};
// Destructor, no instantiation
// No definition also, so no subclass can be instantiated also
virtual ~AbstractProtocol() = 0; virtual ~AbstractProtocol() = 0;
// Public Methods
// Data Members (m_ prefix)
static const bool m_CMP = false ; static const bool m_CMP = false ;
static const bool m_TwoLevelCache = false ; static const bool m_TwoLevelCache = false ;
}; };
#endif //AbstractProtocol_H #endif // __MEM_RUBY_SLICC_INTERFACE_ABSTRACTPROTOCOL_HH__

View File

@@ -1,4 +1,3 @@
/* /*
* Copyright (c) 1999-2008 Mark D. Hill and David A. Wood * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
* All rights reserved. * All rights reserved.
@@ -27,32 +26,32 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
/* #ifndef __MEM_RUBY_SLICC_INTERFACE_MESSAGE_HH__
* $Id$ #define __MEM_RUBY_SLICC_INTERFACE_MESSAGE_HH__
*/
#ifndef MESSAGE_H
#define MESSAGE_H
#include <iostream> #include <iostream>
#include "mem/ruby/common/Global.hh"
#include "mem/gems_common/RefCnt.hh" #include "mem/gems_common/RefCnt.hh"
#include "mem/gems_common/RefCountable.hh" #include "mem/gems_common/RefCountable.hh"
#include "mem/ruby/common/Global.hh"
#include "mem/ruby/eventqueue/RubyEventQueue.hh" #include "mem/ruby/eventqueue/RubyEventQueue.hh"
class Message; class Message;
typedef RefCnt<Message> MsgPtr; typedef RefCnt<Message> MsgPtr;
class Message : public RefCountable { class Message : public RefCountable
{
public: public:
// Constructors Message()
Message() : RefCountable() { m_time = g_eventQueue_ptr->getTime(); m_LastEnqueueTime = g_eventQueue_ptr->getTime(); m_DelayedCycles = 0;} : RefCountable()
{
m_time = g_eventQueue_ptr->getTime();
m_LastEnqueueTime = g_eventQueue_ptr->getTime();
m_DelayedCycles = 0;
}
// Destructor
virtual ~Message() { } virtual ~Message() { }
// Public Methods
virtual Message* clone() const = 0; virtual Message* clone() const = 0;
virtual void destroy() = 0; virtual void destroy() = 0;
virtual void print(std::ostream& out) const = 0; virtual void print(std::ostream& out) const = 0;
@@ -66,28 +65,19 @@ public:
const Time& getTime() const { return m_time; } const Time& getTime() const { return m_time; }
void setTime(const Time& new_time) { m_time = new_time; } void setTime(const Time& new_time) { m_time = new_time; }
private:
// Private Methods
// Data Members (m_ prefix) private:
Time m_time; Time m_time;
Time m_LastEnqueueTime; // my last enqueue time Time m_LastEnqueueTime; // my last enqueue time
int m_DelayedCycles; // my delayed cycles int m_DelayedCycles; // my delayed cycles
}; };
// Output operator declaration inline std::ostream&
std::ostream& operator<<(std::ostream& out, const Message& obj); operator<<(std::ostream& out, const Message& obj)
// ******************* Definitions *******************
// Output operator definition
extern inline
std::ostream& operator<<(std::ostream& out, const Message& obj)
{ {
obj.print(out); obj.print(out);
out << std::flush; out << std::flush;
return out; return out;
} }
#endif //MESSAGE_H #endif // __MEM_RUBY_SLICC_INTERFACE_MESSAGE_HH__

View File

@@ -1,4 +1,3 @@
/* /*
* Copyright (c) 1999-2008 Mark D. Hill and David A. Wood * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
* All rights reserved. * All rights reserved.
@@ -27,60 +26,49 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
/* #ifndef __MEM_RUBY_SLICC_INTERFACE_NETWORKMESSAGE_HH__
* NetworkMessage.hh #define __MEM_RUBY_SLICC_INTERFACE_NETWORKMESSAGE_HH__
*
* Description:
*
* $Id$
*
*/
#ifndef NetworkMessage_H
#define NetworkMessage_H
#include "mem/ruby/common/Global.hh"
#include "mem/gems_common/RefCnt.hh" #include "mem/gems_common/RefCnt.hh"
#include "mem/gems_common/RefCountable.hh" #include "mem/gems_common/RefCountable.hh"
#include "mem/ruby/slicc_interface/Message.hh"
#include "mem/protocol/MessageSizeType.hh" #include "mem/protocol/MessageSizeType.hh"
#include "mem/ruby/common/Global.hh"
#include "mem/ruby/common/NetDest.hh" #include "mem/ruby/common/NetDest.hh"
#include "mem/ruby/slicc_interface/Message.hh"
class Address; class Address;
class NetworkMessage; class NetworkMessage;
typedef RefCnt<NetworkMessage> NetMsgPtr; typedef RefCnt<NetworkMessage> NetMsgPtr;
class NetworkMessage : public Message { class NetworkMessage : public Message
{
public: public:
// Constructors
NetworkMessage() NetworkMessage()
: Message() : Message()
{ {
m_internal_dest_valid = false; m_internal_dest_valid = false;
} }
// Destructor
virtual ~NetworkMessage() { } virtual ~NetworkMessage() { }
// Public Methods
virtual const NetDest& getDestination() const = 0; virtual const NetDest& getDestination() const = 0;
virtual NetDest& getDestination() = 0; virtual NetDest& getDestination() = 0;
virtual const MessageSizeType& getMessageSize() const = 0; virtual const MessageSizeType& getMessageSize() const = 0;
virtual MessageSizeType& getMessageSize() = 0; virtual MessageSizeType& getMessageSize() = 0;
// virtual const Address& getAddress() const = 0;
// virtual Address& getAddress() = 0;
const NetDest& getInternalDestination() const { const NetDest&
if (m_internal_dest_valid == false) { getInternalDestination() const
{
if (m_internal_dest_valid == false)
return getDestination(); return getDestination();
} else {
return m_internal_dest; return m_internal_dest;
} }
}
NetDest& getInternalDestination() { NetDest&
getInternalDestination()
{
if (m_internal_dest_valid == false) { if (m_internal_dest_valid == false) {
m_internal_dest = getDestination(); m_internal_dest = getDestination();
m_internal_dest_valid = true; m_internal_dest_valid = true;
@@ -91,25 +79,16 @@ public:
virtual void print(ostream& out) const = 0; virtual void print(ostream& out) const = 0;
private: private:
// Private Methods
// Data Members (m_ prefix)
NetDest m_internal_dest; NetDest m_internal_dest;
bool m_internal_dest_valid; bool m_internal_dest_valid;
}; };
// Output operator declaration inline ostream&
ostream& operator<<(ostream& out, const NetworkMessage& obj); operator<<(ostream& out, const NetworkMessage& obj)
// ******************* Definitions *******************
// Output operator definition
extern inline
ostream& operator<<(ostream& out, const NetworkMessage& obj)
{ {
obj.print(out); obj.print(out);
out << flush; out << flush;
return out; return out;
} }
#endif //NetworkMessage_H #endif // __MEM_RUBY_SLICC_INTERFACE_NETWORKMESSAGE_HH__

View File

@@ -1,4 +1,3 @@
/* /*
* Copyright (c) 1999-2008 Mark D. Hill and David A. Wood * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
* All rights reserved. * All rights reserved.
@@ -27,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/ruby/slicc_interface/RubySlicc_ComponentMapping.hh" #include "mem/ruby/slicc_interface/RubySlicc_ComponentMapping.hh"
#include "mem/ruby/system/CacheMemory.hh" #include "mem/ruby/system/CacheMemory.hh"

View File

@@ -1,4 +1,3 @@
/* /*
* Copyright (c) 1999-2008 Mark D. Hill and David A. Wood * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
* All rights reserved. * All rights reserved.
@@ -27,22 +26,18 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
/* #ifndef __MEM_RUBY_SLICC_INTERFACE_RUBYSLICC_COMPONENTMAPPINGS_HH__
* $Id$ #define __MEM_RUBY_SLICC_INTERFACE_RUBYSLICC_COMPONENTMAPPINGS_HH__
*/
#ifndef COMPONENTMAPPINGFNS_H
#define COMPONENTMAPPINGFNS_H
#include "mem/ruby/common/Global.hh"
#include "mem/ruby/system/NodeID.hh"
#include "mem/ruby/system/MachineID.hh"
#include "mem/ruby/common/Address.hh"
#include "mem/ruby/common/Set.hh"
#include "mem/ruby/common/NetDest.hh"
#include "mem/protocol/GenericMachineType.hh" #include "mem/protocol/GenericMachineType.hh"
#include "mem/ruby/system/DirectoryMemory.hh"
#include "mem/protocol/MachineType.hh" #include "mem/protocol/MachineType.hh"
#include "mem/ruby/common/Address.hh"
#include "mem/ruby/common/Global.hh"
#include "mem/ruby/common/NetDest.hh"
#include "mem/ruby/common/Set.hh"
#include "mem/ruby/system/DirectoryMemory.hh"
#include "mem/ruby/system/MachineID.hh"
#include "mem/ruby/system/NodeID.hh"
#ifdef MACHINETYPE_L1Cache #ifdef MACHINETYPE_L1Cache
#define MACHINETYPE_L1CACHE_ENUM MachineType_L1Cache #define MACHINETYPE_L1CACHE_ENUM MachineType_L1Cache
@@ -70,30 +65,31 @@
// used to determine the home directory // used to determine the home directory
// returns a value between 0 and total_directories_within_the_system // returns a value between 0 and total_directories_within_the_system
inline inline NodeID
NodeID map_Address_to_DirectoryNode(const Address& addr) map_Address_to_DirectoryNode(const Address& addr)
{ {
return DirectoryMemory::mapAddressToDirectoryVersion(addr); return DirectoryMemory::mapAddressToDirectoryVersion(addr);
} }
// used to determine the home directory // used to determine the home directory
// returns a value between 0 and total_directories_within_the_system // returns a value between 0 and total_directories_within_the_system
inline inline MachineID
MachineID map_Address_to_Directory(const Address &addr) map_Address_to_Directory(const Address &addr)
{ {
MachineID mach = {MachineType_Directory, map_Address_to_DirectoryNode(addr)}; MachineID mach =
{MachineType_Directory, map_Address_to_DirectoryNode(addr)};
return mach; return mach;
} }
inline inline MachineID
MachineID map_Address_to_DMA(const Address & addr) map_Address_to_DMA(const Address & addr)
{ {
MachineID dma = {MACHINETYPE_DMA_ENUM, 0}; MachineID dma = {MACHINETYPE_DMA_ENUM, 0};
return dma; return dma;
} }
inline inline NetDest
NetDest broadcast(MachineType type) broadcast(MachineType type)
{ {
NetDest dest; NetDest dest;
for (int i = 0; i < MachineType_base_count(type); i++) { for (int i = 0; i < MachineType_base_count(type); i++) {
@@ -103,8 +99,9 @@ NetDest broadcast(MachineType type)
return dest; return dest;
} }
inline inline MachineID
MachineID mapAddressToRange(const Address & addr, MachineType type, int low_bit, int num_bits) mapAddressToRange(const Address & addr, MachineType type, int low_bit,
int num_bits)
{ {
MachineID mach = {type, 0}; MachineID mach = {type, 0};
if (num_bits == 0) if (num_bits == 0)
@@ -113,45 +110,55 @@ MachineID mapAddressToRange(const Address & addr, MachineType type, int low_bit,
return mach; return mach;
} }
extern inline NodeID machineIDToNodeID(MachineID machID) inline NodeID
machineIDToNodeID(MachineID machID)
{ {
return machID.num; return machID.num;
} }
extern inline MachineType machineIDToMachineType(MachineID machID) inline MachineType
machineIDToMachineType(MachineID machID)
{ {
return machID.type; return machID.type;
} }
extern inline NodeID L1CacheMachIDToProcessorNum(MachineID machID) inline NodeID
L1CacheMachIDToProcessorNum(MachineID machID)
{ {
assert(machID.type == MachineType_L1Cache); assert(machID.type == MachineType_L1Cache);
return machID.num; return machID.num;
} }
extern inline MachineID getL1MachineID(NodeID L1RubyNode) inline MachineID
getL1MachineID(NodeID L1RubyNode)
{ {
MachineID mach = {MACHINETYPE_L1CACHE_ENUM, L1RubyNode}; MachineID mach = {MACHINETYPE_L1CACHE_ENUM, L1RubyNode};
return mach; return mach;
} }
extern inline GenericMachineType ConvertMachToGenericMach(MachineType machType) { inline GenericMachineType
if (machType == MACHINETYPE_L1CACHE_ENUM) { ConvertMachToGenericMach(MachineType machType)
{
if (machType == MACHINETYPE_L1CACHE_ENUM)
return GenericMachineType_L1Cache; return GenericMachineType_L1Cache;
} else if (machType == MACHINETYPE_L2CACHE_ENUM) {
if (machType == MACHINETYPE_L2CACHE_ENUM)
return GenericMachineType_L2Cache; return GenericMachineType_L2Cache;
} else if (machType == MACHINETYPE_L3CACHE_ENUM) {
if (machType == MACHINETYPE_L3CACHE_ENUM)
return GenericMachineType_L3Cache; return GenericMachineType_L3Cache;
} else if (machType == MachineType_Directory) {
if (machType == MachineType_Directory)
return GenericMachineType_Directory; return GenericMachineType_Directory;
} else {
ERROR_MSG("cannot convert to a GenericMachineType"); ERROR_MSG("cannot convert to a GenericMachineType");
return GenericMachineType_NULL; return GenericMachineType_NULL;
} }
}
extern inline int machineCount(MachineType machType) { inline int
machineCount(MachineType machType)
{
return MachineType_base_count(machType); return MachineType_base_count(machType);
} }
#endif // COMPONENTMAPPINGFNS_H #endif // __MEM_RUBY_SLICC_INTERFACE_COMPONENTMAPPINGS_HH__

View File

@@ -1,4 +1,3 @@
/* /*
* Copyright (c) 1999-2008 Mark D. Hill and David A. Wood * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
* All rights reserved. * All rights reserved.
@@ -27,66 +26,75 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
/*
* slicc_util.cc
*
* Description: See slicc_util.hh
*
* $Id$
*
*/
#include "mem/ruby/common/Global.hh"
#include "mem/ruby/system/System.hh"
#include "mem/ruby/profiler/Profiler.hh"
#include "mem/ruby/profiler/AddressProfiler.hh"
#include "mem/protocol/Protocol.hh" #include "mem/protocol/Protocol.hh"
#include "mem/ruby/slicc_interface/RubySlicc_Profiler_interface.hh" #include "mem/ruby/common/Global.hh"
#include "mem/ruby/profiler/AddressProfiler.hh"
#include "mem/ruby/profiler/Profiler.hh"
#include "mem/ruby/slicc_interface/RubySlicc_ComponentMapping.hh" #include "mem/ruby/slicc_interface/RubySlicc_ComponentMapping.hh"
// #include "TransactionInterfaceManager.hh" #include "mem/ruby/slicc_interface/RubySlicc_Profiler_interface.hh"
#include "mem/ruby/system/System.hh"
void profile_request(int cache_state, Directory_State directory_state, GenericRequestType request_type) void
profile_request(int cache_state, Directory_State directory_state,
GenericRequestType request_type)
{ {
string requestStr = L1Cache_State_to_string(L1Cache_State(cache_state))+":"+ string requestStr = L1Cache_State_to_string(L1Cache_State(cache_state))+
":" +
Directory_State_to_string(directory_state) + ":" + Directory_State_to_string(directory_state) + ":" +
GenericRequestType_to_string(request_type); GenericRequestType_to_string(request_type);
g_system_ptr->getProfiler()->profileRequest(requestStr); g_system_ptr->getProfiler()->profileRequest(requestStr);
} }
void profile_request(const string& L1CacheState, const string& L2CacheState, const string& directoryState, const string& requestType) void
profile_request(const string& L1CacheState, const string& L2CacheState,
const string& directoryState, const string& requestType)
{ {
string requestStr = L1CacheState+":"+L2CacheState+":"+directoryState+":"+requestType; string requestStr = L1CacheState + ":" + L2CacheState + ":" +
directoryState + ":" + requestType;
g_system_ptr->getProfiler()->profileRequest(requestStr); g_system_ptr->getProfiler()->profileRequest(requestStr);
} }
void profile_outstanding_request(int outstanding) void
profile_outstanding_request(int outstanding)
{ {
g_system_ptr->getProfiler()->profileOutstandingRequest(outstanding); g_system_ptr->getProfiler()->profileOutstandingRequest(outstanding);
} }
void profile_average_latency_estimate(int latency) void
profile_average_latency_estimate(int latency)
{ {
g_system_ptr->getProfiler()->profileAverageLatencyEstimate(latency); g_system_ptr->getProfiler()->profileAverageLatencyEstimate(latency);
} }
void profile_sharing(const Address& addr, AccessType type, NodeID requestor, const Set& sharers, const Set& owner) void
profile_sharing(const Address& addr, AccessType type, NodeID requestor,
const Set& sharers, const Set& owner)
{ {
g_system_ptr->getProfiler()->profileSharing(addr, type, requestor, sharers, owner); g_system_ptr->getProfiler()->
profileSharing(addr, type, requestor, sharers, owner);
} }
void profileMsgDelay(int virtualNetwork, int delayCycles) void
profileMsgDelay(int virtualNetwork, int delayCycles)
{ {
g_system_ptr->getProfiler()->profileMsgDelay(virtualNetwork, delayCycles); g_system_ptr->getProfiler()->profileMsgDelay(virtualNetwork, delayCycles);
} }
void profileGetX(const Address& datablock, const Address& PC, const Set& owner, const Set& sharers, NodeID requestor) void
profileGetX(const Address& datablock, const Address& PC, const Set& owner,
const Set& sharers, NodeID requestor)
{ {
g_system_ptr->getProfiler()->getAddressProfiler()->profileGetX(datablock, PC, owner, sharers, requestor); g_system_ptr->getProfiler()->getAddressProfiler()->
profileGetX(datablock, PC, owner, sharers, requestor);
} }
void profileGetS(const Address& datablock, const Address& PC, const Set& owner, const Set& sharers, NodeID requestor) void
profileGetS(const Address& datablock, const Address& PC, const Set& owner,
const Set& sharers, NodeID requestor)
{ {
g_system_ptr->getProfiler()->getAddressProfiler()->profileGetS(datablock, PC, owner, sharers, requestor); g_system_ptr->getProfiler()->getAddressProfiler()->
profileGetS(datablock, PC, owner, sharers, requestor);
} }

View File

@@ -1,4 +1,3 @@
/* /*
* Copyright (c) 1999-2008 Mark D. Hill and David A. Wood * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
* All rights reserved. * All rights reserved.
@@ -28,36 +27,37 @@
*/ */
/* /*
* slicc_util.hh * These are the functions that exported to slicc from ruby.
*
* Description: These are the functions that exported to slicc from ruby.
*
* $Id$
*
*/ */
#ifndef RUBYSLICC_PROFILER_INTERFACE_H #ifndef __MEM_RUBY_SLICC_INTERFACE_RUBYSLICC_PROFILER_INTERFACE_HH__
#define RUBYSLICC_PROFILER_INTERFACE_H #define __MEM_RUBY_SLICC_INTERFACE_RUBYSLICC_PROFILER_INTERFACE_HH__
#include "mem/protocol/AccessType.hh"
#include "mem/protocol/Directory_State.hh"
#include "mem/protocol/GenericRequestType.hh"
#include "mem/protocol/L1Cache_State.hh"
#include "mem/ruby/common/Address.hh"
#include "mem/ruby/common/Global.hh" #include "mem/ruby/common/Global.hh"
#include "mem/ruby/profiler/Profiler.hh" #include "mem/ruby/profiler/Profiler.hh"
#include "mem/ruby/common/Address.hh"
#include "mem/protocol/L1Cache_State.hh"
#include "mem/protocol/AccessType.hh"
#include "mem/protocol/GenericRequestType.hh"
#include "mem/protocol/Directory_State.hh"
#include "mem/ruby/system/NodeID.hh" #include "mem/ruby/system/NodeID.hh"
class Set; class Set;
void profile_request(int cache_state, Directory_State directory_state, GenericRequestType request_type); void profile_request(int cache_state, Directory_State directory_state,
GenericRequestType request_type);
void profile_outstanding_persistent_request(int outstanding); void profile_outstanding_persistent_request(int outstanding);
void profile_outstanding_request(int outstanding); void profile_outstanding_request(int outstanding);
void profile_sharing(const Address& addr, AccessType type, NodeID requestor, const Set& sharers, const Set& owner); void profile_sharing(const Address& addr, AccessType type, NodeID requestor,
void profile_request(const string& L1CacheStateStr, const string& L2CacheStateStr, const string& directoryStateStr, const string& requestTypeStr); const Set& sharers, const Set& owner);
void profile_request(const string& L1CacheStateStr,
const string& L2CacheStateStr,
const string& directoryStateStr,
const string& requestTypeStr);
void profile_miss(const CacheMsg& msg, NodeID id); void profile_miss(const CacheMsg& msg, NodeID id);
void profile_L1Cache_miss(const CacheMsg& msg, NodeID id); void profile_L1Cache_miss(const CacheMsg& msg, NodeID id);
void profile_L2Cache_miss(GenericRequestType requestType, AccessModeType type, int msgSize, PrefetchBit pfBit, NodeID l2cacheID); void profile_L2Cache_miss(GenericRequestType requestType, AccessModeType type,
int msgSize, PrefetchBit pfBit, NodeID l2cacheID);
void profile_token_retry(const Address& addr, AccessType type, int count); void profile_token_retry(const Address& addr, AccessType type, int count);
void profile_filter_action(int action); void profile_filter_action(int action);
void profile_persistent_prediction(const Address& addr, AccessType type); void profile_persistent_prediction(const Address& addr, AccessType type);
@@ -65,9 +65,11 @@ void profile_average_latency_estimate(int latency);
void profileMsgDelay(int virtualNetwork, int delayCycles); void profileMsgDelay(int virtualNetwork, int delayCycles);
void profile_multicast_retry(const Address& addr, int count); void profile_multicast_retry(const Address& addr, int count);
void profileGetX(const Address& datablock, const Address& PC, const Set& owner, const Set& sharers, NodeID requestor); void profileGetX(const Address& datablock, const Address& PC, const Set& owner,
void profileGetS(const Address& datablock, const Address& PC, const Set& owner, const Set& sharers, NodeID requestor); const Set& sharers, NodeID requestor);
void profileGetS(const Address& datablock, const Address& PC, const Set& owner,
const Set& sharers, NodeID requestor);
void profileOverflow(const Address & addr, MachineID mach); void profileOverflow(const Address & addr, MachineID mach);
#endif // RUBYSLICC_PROFILER_INTERFACE_H #endif // __MEM_RUBY_SLICC_INTERFACE_RUBYSLICC_PROFILER_INTERFACE_HH__

View File

@@ -1,4 +1,3 @@
/* /*
* Copyright (c) 1999-2008 Mark D. Hill and David A. Wood * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
* All rights reserved. * All rights reserved.
@@ -28,44 +27,40 @@
*/ */
/* /*
* slicc_util.hh * These are the functions that exported to slicc from ruby.
*
* Description: These are the functions that exported to slicc from ruby.
*
* $Id$
*
*/ */
#ifndef SLICC_UTIL_H #ifndef __MEM_RUBY_SLICC_INTERFACE_RUBYSLICCUTIL_HH__
#define SLICC_UTIL_H #define __MEM_RUBY_SLICC_INTERFACE_RUBYSLICCUTIL_HH__
#include "mem/ruby/common/Global.hh"
#include "mem/ruby/common/Address.hh"
#include "mem/ruby/system/NodeID.hh"
#include "mem/ruby/system/MachineID.hh"
#include "mem/protocol/CacheMsg.hh"
#include "mem/protocol/GenericRequestType.hh"
#include "mem/protocol/CacheRequestType.hh"
#include "mem/protocol/AccessType.hh" #include "mem/protocol/AccessType.hh"
#include "mem/protocol/MachineType.hh" #include "mem/protocol/CacheMsg.hh"
#include "mem/protocol/CacheRequestType.hh"
#include "mem/protocol/Directory_State.hh" #include "mem/protocol/Directory_State.hh"
#include "mem/protocol/GenericRequestType.hh"
#include "mem/protocol/L1Cache_State.hh" #include "mem/protocol/L1Cache_State.hh"
#include "mem/protocol/MachineType.hh"
#include "mem/protocol/MessageSizeType.hh" #include "mem/protocol/MessageSizeType.hh"
#include "mem/ruby/network/Network.hh"
#include "mem/protocol/PrefetchBit.hh" #include "mem/protocol/PrefetchBit.hh"
#include "mem/ruby/system/System.hh" #include "mem/ruby/common/Address.hh"
#include "mem/ruby/common/Global.hh"
#include "mem/ruby/network/Network.hh"
#include "mem/ruby/slicc_interface/RubySlicc_ComponentMapping.hh" #include "mem/ruby/slicc_interface/RubySlicc_ComponentMapping.hh"
#include "mem/ruby/system/MachineID.hh"
#include "mem/ruby/system/NodeID.hh"
#include "mem/ruby/system/System.hh"
class Set; class Set;
class NetDest; class NetDest;
extern inline int random(int n) inline int
random(int n)
{ {
return random() % n; return random() % n;
} }
extern inline bool multicast_retry() inline bool
multicast_retry()
{ {
if (RubySystem::getRandomization()) { if (RubySystem::getRandomization()) {
return (random() & 0x1); return (random() & 0x1);
@@ -74,65 +69,77 @@ extern inline bool multicast_retry()
} }
} }
extern inline int cache_state_to_int(L1Cache_State state) inline int
cache_state_to_int(L1Cache_State state)
{ {
return state; return state;
} }
extern inline Time get_time() inline Time
get_time()
{ {
return g_eventQueue_ptr->getTime(); return g_eventQueue_ptr->getTime();
} }
extern inline Time zero_time() inline Time
zero_time()
{ {
return 0; return 0;
} }
extern inline NodeID intToID(int nodenum) inline NodeID
intToID(int nodenum)
{ {
NodeID id = nodenum; NodeID id = nodenum;
return id; return id;
} }
extern inline int IDToInt(NodeID id) inline int
IDToInt(NodeID id)
{ {
int nodenum = id; int nodenum = id;
return nodenum; return nodenum;
} }
extern inline int addressToInt(Address addr) inline int
addressToInt(Address addr)
{ {
return (int)addr.getLineAddress(); return (int)addr.getLineAddress();
} }
extern inline bool long_enough_ago(Time event) inline bool
long_enough_ago(Time event)
{ {
return ((get_time() - event) > 200); return ((get_time() - event) > 200);
} }
extern inline int getAddThenMod(int addend1, int addend2, int modulus) inline int
getAddThenMod(int addend1, int addend2, int modulus)
{ {
return (addend1 + addend2) % modulus; return (addend1 + addend2) % modulus;
} }
extern inline Time getTimeModInt(Time time, int modulus) inline Time
getTimeModInt(Time time, int modulus)
{ {
return time % modulus; return time % modulus;
} }
extern inline Time getTimePlusInt(Time addend1, int addend2) inline Time
getTimePlusInt(Time addend1, int addend2)
{ {
return (Time) addend1 + addend2; return (Time) addend1 + addend2;
} }
extern inline Time getTimeMinusTime(Time t1, Time t2) inline Time
getTimeMinusTime(Time t1, Time t2)
{ {
ASSERT(t1 >= t2); ASSERT(t1 >= t2);
return t1 - t2; return t1 - t2;
} }
extern inline Time getPreviousDelayedCycles(Time t1, Time t2) inline Time
getPreviousDelayedCycles(Time t1, Time t2)
{ {
if (RubySystem::getRandomization()) { // when randomizing delayed if (RubySystem::getRandomization()) { // when randomizing delayed
return 0; return 0;
@@ -141,19 +148,23 @@ extern inline Time getPreviousDelayedCycles(Time t1, Time t2)
} }
} }
extern inline void WARN_ERROR_TIME(Time time) inline void
WARN_ERROR_TIME(Time time)
{ {
WARN_EXPR(time); WARN_EXPR(time);
} }
// Return type for time_to_int is "Time" and not "int" so we get a 64-bit integer // Return type for time_to_int is "Time" and not "int" so we get a
extern inline Time time_to_int(Time time) // 64-bit integer
inline Time
time_to_int(Time time)
{ {
return time; return time;
} }
// Appends an offset to an address // Appends an offset to an address
extern inline Address setOffset(Address addr, int offset) inline Address
setOffset(Address addr, int offset)
{ {
Address result = addr; Address result = addr;
result.setOffset(offset); result.setOffset(offset);
@@ -161,16 +172,18 @@ extern inline Address setOffset(Address addr, int offset)
} }
// Makes an address into a line address // Makes an address into a line address
extern inline Address makeLineAddress(Address addr) inline Address
makeLineAddress(Address addr)
{ {
Address result = addr; Address result = addr;
result.makeLineAddress(); result.makeLineAddress();
return result; return result;
} }
extern inline int addressOffset(Address addr) inline int
addressOffset(Address addr)
{ {
return addr.getOffset(); return addr.getOffset();
} }
#endif //SLICC_UTIL_H #endif // __MEM_RUBY_SLICC_INTERFACE_RUBYSLICCUTIL_HH__

View File

@@ -26,12 +26,12 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#ifndef RUBYSLICC_INCLUDES_H #ifndef __MEM_RUBY_SLICC_INTERFACE_RUBYSLICC_INCLUDES_HH__
#define RUBYSLICC_INCLUDES_H #define __MEM_RUBY_SLICC_INTERFACE_RUBYSLICC_INCLUDES_HH__
#include "mem/ruby/slicc_interface/RubySlicc_ComponentMapping.hh" #include "mem/ruby/slicc_interface/RubySlicc_ComponentMapping.hh"
#include "mem/ruby/slicc_interface/RubySlicc_Util.hh" #include "mem/ruby/slicc_interface/RubySlicc_Util.hh"
#include "mem/ruby/slicc_interface/RubySlicc_Profiler_interface.hh" #include "mem/ruby/slicc_interface/RubySlicc_Profiler_interface.hh"
#endif #endif // __MEM_RUBY_SLICC_INTERFACE_RUBYSLICC_INCLUDES_HH__

View File

@@ -26,23 +26,20 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
/* #ifndef __MEM_RUBY_SYSTEM_ABSTRACTMEMORCACHE_HH__
* AbstractMemOrCache.hh #define __MEM_RUBY_SYSTEM_ABSTRACTMEMORCACHE_HH__
*
* Description:
*
*
*/
#ifndef ABSTRACT_MEM_OR_CACHE_H #include <iosfwd>
#define ABSTRACT_MEM_OR_CACHE_H
#include "mem/ruby/common/Global.hh" #include "mem/ruby/slicc_interface/Message.hh"
#include "mem/ruby/common/Address.hh"
class AbstractMemOrCache { class Consumer;
class MemoryNode;
class Message;
class AbstractMemOrCache
{
public: public:
virtual ~AbstractMemOrCache() {}; virtual ~AbstractMemOrCache() {};
virtual void setConsumer(Consumer* consumer_ptr) = 0; virtual void setConsumer(Consumer* consumer_ptr) = 0;
virtual Consumer* getConsumer() = 0; virtual Consumer* getConsumer() = 0;
@@ -54,14 +51,9 @@ public:
virtual bool isReady () = 0; virtual bool isReady () = 0;
virtual MemoryNode peekNode () = 0; virtual MemoryNode peekNode () = 0;
virtual bool areNSlotsAvailable (int n) = 0; virtual bool areNSlotsAvailable (int n) = 0;
virtual void printConfig (ostream& out) = 0; virtual void printConfig (std::ostream& out) = 0;
virtual void print (ostream& out) const = 0; virtual void print (std::ostream& out) const = 0;
virtual void setDebug (int debugFlag) = 0; virtual void setDebug (int debugFlag) = 0;
private:
}; };
#endif // __MEM_RUBY_SYSTEM_ABSTRACTMEMORCACHE_HH__
#endif

View File

@@ -26,15 +26,14 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#ifndef ABSTRACTREPLACEMENTPOLICY_H #ifndef __MEM_RUBY_SYSTEM_ABSTRACTREPLACEMENTPOLICY_HH__
#define ABSTRACTREPLACEMENTPOLICY_H #define __MEM_RUBY_SYSTEM_ABSTRACTREPLACEMENTPOLICY_HH__
#include "mem/ruby/common/Global.hh" #include "mem/ruby/common/Global.hh"
class AbstractReplacementPolicy { class AbstractReplacementPolicy
{
public: public:
AbstractReplacementPolicy(Index num_sets, Index assoc); AbstractReplacementPolicy(Index num_sets, Index assoc);
virtual ~AbstractReplacementPolicy(); virtual ~AbstractReplacementPolicy();
@@ -48,20 +47,21 @@ public:
Time getLastAccess(Index set, Index way); Time getLastAccess(Index set, Index way);
protected: protected:
unsigned int m_num_sets; /** total number of sets */ unsigned m_num_sets; /** total number of sets */
unsigned int m_assoc; /** set associativity */ unsigned m_assoc; /** set associativity */
Time **m_last_ref_ptr; /** timestamp of last reference */ Time **m_last_ref_ptr; /** timestamp of last reference */
}; };
inline inline
AbstractReplacementPolicy::AbstractReplacementPolicy(Index num_sets, Index assoc) AbstractReplacementPolicy::AbstractReplacementPolicy(Index num_sets,
Index assoc)
{ {
m_num_sets = num_sets; m_num_sets = num_sets;
m_assoc = assoc; m_assoc = assoc;
m_last_ref_ptr = new Time*[m_num_sets]; m_last_ref_ptr = new Time*[m_num_sets];
for(unsigned int i = 0; i < m_num_sets; i++){ for(unsigned i = 0; i < m_num_sets; i++){
m_last_ref_ptr[i] = new Time[m_assoc]; m_last_ref_ptr[i] = new Time[m_assoc];
for(unsigned int j = 0; j < m_assoc; j++){ for(unsigned j = 0; j < m_assoc; j++){
m_last_ref_ptr[i][j] = 0; m_last_ref_ptr[i][j] = 0;
} }
} }
@@ -71,7 +71,7 @@ inline
AbstractReplacementPolicy::~AbstractReplacementPolicy() AbstractReplacementPolicy::~AbstractReplacementPolicy()
{ {
if (m_last_ref_ptr != NULL){ if (m_last_ref_ptr != NULL){
for(unsigned int i = 0; i < m_num_sets; i++){ for (unsigned i = 0; i < m_num_sets; i++){
if (m_last_ref_ptr[i] != NULL){ if (m_last_ref_ptr[i] != NULL){
delete[] m_last_ref_ptr[i]; delete[] m_last_ref_ptr[i];
} }
@@ -80,10 +80,10 @@ AbstractReplacementPolicy::~AbstractReplacementPolicy()
} }
} }
inline inline Time
Time AbstractReplacementPolicy::getLastAccess(Index set, Index way) AbstractReplacementPolicy::getLastAccess(Index set, Index way)
{ {
return m_last_ref_ptr[set][way]; return m_last_ref_ptr[set][way];
} }
#endif // ABSTRACTREPLACEMENTPOLICY_H #endif // __MEM_RUBY_SYSTEM_ABSTRACTREPLACEMENTPOLICY_HH__

View File

@@ -28,19 +28,14 @@
#include "mem/ruby/system/CacheMemory.hh" #include "mem/ruby/system/CacheMemory.hh"
// ******************* Definitions ******************* ostream&
operator<<(ostream& out, const CacheMemory& obj)
// Output operator definition
ostream& operator<<(ostream& out, const CacheMemory& obj)
{ {
obj.print(out); obj.print(out);
out << flush; out << flush;
return out; return out;
} }
// ****************************************************************
CacheMemory * CacheMemory *
RubyCacheParams::create() RubyCacheParams::create()
{ {
@@ -57,18 +52,21 @@ CacheMemory::CacheMemory(const Params *p)
m_profiler_ptr = new CacheProfiler(name()); m_profiler_ptr = new CacheProfiler(name());
} }
void
void CacheMemory::init() CacheMemory::init()
{ {
m_cache_num_sets = (m_cache_size / m_cache_assoc) / RubySystem::getBlockSizeBytes(); m_cache_num_sets = (m_cache_size / m_cache_assoc) /
RubySystem::getBlockSizeBytes();
assert(m_cache_num_sets > 1); assert(m_cache_num_sets > 1);
m_cache_num_set_bits = log_int(m_cache_num_sets); m_cache_num_set_bits = log_int(m_cache_num_sets);
assert(m_cache_num_set_bits > 0); assert(m_cache_num_set_bits > 0);
if (m_policy == "PSEUDO_LRU") if (m_policy == "PSEUDO_LRU")
m_replacementPolicy_ptr = new PseudoLRUPolicy(m_cache_num_sets, m_cache_assoc); m_replacementPolicy_ptr =
new PseudoLRUPolicy(m_cache_num_sets, m_cache_assoc);
else if (m_policy == "LRU") else if (m_policy == "LRU")
m_replacementPolicy_ptr = new LRUPolicy(m_cache_num_sets, m_cache_assoc); m_replacementPolicy_ptr =
new LRUPolicy(m_cache_num_sets, m_cache_assoc);
else else
assert(false); assert(false);
@@ -96,51 +94,60 @@ CacheMemory::~CacheMemory()
} }
} }
void CacheMemory::printConfig(ostream& out) void
CacheMemory::printConfig(ostream& out)
{ {
int block_size = RubySystem::getBlockSizeBytes();
out << "Cache config: " << m_cache_name << endl; out << "Cache config: " << m_cache_name << endl;
out << " cache_associativity: " << m_cache_assoc << endl; out << " cache_associativity: " << m_cache_assoc << endl;
out << " num_cache_sets_bits: " << m_cache_num_set_bits << endl; out << " num_cache_sets_bits: " << m_cache_num_set_bits << endl;
const int cache_num_sets = 1 << m_cache_num_set_bits; const int cache_num_sets = 1 << m_cache_num_set_bits;
out << " num_cache_sets: " << cache_num_sets << endl; out << " num_cache_sets: " << cache_num_sets << endl;
out << " cache_set_size_bytes: " << cache_num_sets * RubySystem::getBlockSizeBytes() << endl; out << " cache_set_size_bytes: " << cache_num_sets * block_size << endl;
out << " cache_set_size_Kbytes: " out << " cache_set_size_Kbytes: "
<< double(cache_num_sets * RubySystem::getBlockSizeBytes()) / (1<<10) << endl; << double(cache_num_sets * block_size) / (1<<10) << endl;
out << " cache_set_size_Mbytes: " out << " cache_set_size_Mbytes: "
<< double(cache_num_sets * RubySystem::getBlockSizeBytes()) / (1<<20) << endl; << double(cache_num_sets * block_size) / (1<<20) << endl;
out << " cache_size_bytes: " out << " cache_size_bytes: "
<< cache_num_sets * RubySystem::getBlockSizeBytes() * m_cache_assoc << endl; << cache_num_sets * block_size * m_cache_assoc << endl;
out << " cache_size_Kbytes: " out << " cache_size_Kbytes: "
<< double(cache_num_sets * RubySystem::getBlockSizeBytes() * m_cache_assoc) / (1<<10) << endl; << double(cache_num_sets * block_size * m_cache_assoc) / (1<<10)
<< endl;
out << " cache_size_Mbytes: " out << " cache_size_Mbytes: "
<< double(cache_num_sets * RubySystem::getBlockSizeBytes() * m_cache_assoc) / (1<<20) << endl; << double(cache_num_sets * block_size * m_cache_assoc) / (1<<20)
<< endl;
} }
// PRIVATE METHODS
// convert a Address to its location in the cache // convert a Address to its location in the cache
Index CacheMemory::addressToCacheSet(const Address& address) const Index
CacheMemory::addressToCacheSet(const Address& address) const
{ {
assert(address == line_address(address)); assert(address == line_address(address));
return address.bitSelect(RubySystem::getBlockSizeBits(), RubySystem::getBlockSizeBits() + m_cache_num_set_bits-1); return address.bitSelect(RubySystem::getBlockSizeBits(),
RubySystem::getBlockSizeBits() + m_cache_num_set_bits - 1);
} }
// Given a cache index: returns the index of the tag in a set. // Given a cache index: returns the index of the tag in a set.
// returns -1 if the tag is not found. // returns -1 if the tag is not found.
int CacheMemory::findTagInSet(Index cacheSet, const Address& tag) const int
CacheMemory::findTagInSet(Index cacheSet, const Address& tag) const
{ {
assert(tag == line_address(tag)); assert(tag == line_address(tag));
// search the set for the tags // search the set for the tags
m5::hash_map<Address, int>::const_iterator it = m_tag_index.find(tag); m5::hash_map<Address, int>::const_iterator it = m_tag_index.find(tag);
if (it != m_tag_index.end()) if (it != m_tag_index.end())
if (m_cache[cacheSet][it->second]->m_Permission != AccessPermission_NotPresent) if (m_cache[cacheSet][it->second]->m_Permission !=
AccessPermission_NotPresent)
return it->second; return it->second;
return -1; // Not found return -1; // Not found
} }
// Given a cache index: returns the index of the tag in a set. // Given a cache index: returns the index of the tag in a set.
// returns -1 if the tag is not found. // returns -1 if the tag is not found.
int CacheMemory::findTagInSetIgnorePermissions(Index cacheSet, const Address& tag) const int
CacheMemory::findTagInSetIgnorePermissions(Index cacheSet,
const Address& tag) const
{ {
assert(tag == line_address(tag)); assert(tag == line_address(tag));
// search the set for the tags // search the set for the tags
@@ -150,18 +157,19 @@ int CacheMemory::findTagInSetIgnorePermissions(Index cacheSet, const Address& ta
return -1; // Not found return -1; // Not found
} }
// PUBLIC METHODS bool
bool CacheMemory::tryCacheAccess(const Address& address, CacheMemory::tryCacheAccess(const Address& address, CacheRequestType type,
CacheRequestType type,
DataBlock*& data_ptr) DataBlock*& data_ptr)
{ {
assert(address == line_address(address)); assert(address == line_address(address));
DEBUG_EXPR(CACHE_COMP, HighPrio, address); DEBUG_EXPR(CACHE_COMP, HighPrio, address);
Index cacheSet = addressToCacheSet(address); Index cacheSet = addressToCacheSet(address);
int loc = findTagInSet(cacheSet, address); int loc = findTagInSet(cacheSet, address);
if(loc != -1){ // Do we even have a tag match? if (loc != -1) {
// Do we even have a tag match?
AbstractCacheEntry* entry = m_cache[cacheSet][loc]; AbstractCacheEntry* entry = m_cache[cacheSet][loc];
m_replacementPolicy_ptr->touch(cacheSet, loc, g_eventQueue_ptr->getTime()); m_replacementPolicy_ptr->
touch(cacheSet, loc, g_eventQueue_ptr->getTime());
data_ptr = &(entry->getDataBlk()); data_ptr = &(entry->getDataBlk());
if (entry->m_Permission == AccessPermission_Read_Write) { if (entry->m_Permission == AccessPermission_Read_Write) {
@@ -177,33 +185,39 @@ bool CacheMemory::tryCacheAccess(const Address& address,
return false; return false;
} }
bool CacheMemory::testCacheAccess(const Address& address, bool
CacheRequestType type, CacheMemory::testCacheAccess(const Address& address, CacheRequestType type,
DataBlock*& data_ptr) DataBlock*& data_ptr)
{ {
assert(address == line_address(address)); assert(address == line_address(address));
DEBUG_EXPR(CACHE_COMP, HighPrio, address); DEBUG_EXPR(CACHE_COMP, HighPrio, address);
Index cacheSet = addressToCacheSet(address); Index cacheSet = addressToCacheSet(address);
int loc = findTagInSet(cacheSet, address); int loc = findTagInSet(cacheSet, address);
if(loc != -1){ // Do we even have a tag match?
if (loc != -1) {
// Do we even have a tag match?
AbstractCacheEntry* entry = m_cache[cacheSet][loc]; AbstractCacheEntry* entry = m_cache[cacheSet][loc];
m_replacementPolicy_ptr->touch(cacheSet, loc, g_eventQueue_ptr->getTime()); m_replacementPolicy_ptr->
touch(cacheSet, loc, g_eventQueue_ptr->getTime());
data_ptr = &(entry->getDataBlk()); data_ptr = &(entry->getDataBlk());
return (m_cache[cacheSet][loc]->m_Permission != AccessPermission_NotPresent); return m_cache[cacheSet][loc]->m_Permission !=
AccessPermission_NotPresent;
} }
data_ptr = NULL; data_ptr = NULL;
return false; return false;
} }
// tests to see if an address is present in the cache // tests to see if an address is present in the cache
bool CacheMemory::isTagPresent(const Address& address) const bool
CacheMemory::isTagPresent(const Address& address) const
{ {
assert(address == line_address(address)); assert(address == line_address(address));
Index cacheSet = addressToCacheSet(address); Index cacheSet = addressToCacheSet(address);
int location = findTagInSet(cacheSet, address); int loc = findTagInSet(cacheSet, address);
if (location == -1) { if (loc == -1) {
// We didn't find the tag // We didn't find the tag
DEBUG_EXPR(CACHE_COMP, LowPrio, address); DEBUG_EXPR(CACHE_COMP, LowPrio, address);
DEBUG_MSG(CACHE_COMP, LowPrio, "No tag match"); DEBUG_MSG(CACHE_COMP, LowPrio, "No tag match");
@@ -217,7 +231,8 @@ bool CacheMemory::isTagPresent(const Address& address) const
// Returns true if there is: // Returns true if there is:
// a) a tag match on this address or there is // a) a tag match on this address or there is
// b) an unused line in the same cache "way" // b) an unused line in the same cache "way"
bool CacheMemory::cacheAvail(const Address& address) const bool
CacheMemory::cacheAvail(const Address& address) const
{ {
assert(address == line_address(address)); assert(address == line_address(address));
@@ -226,8 +241,9 @@ bool CacheMemory::cacheAvail(const Address& address) const
for (int i = 0; i < m_cache_assoc; i++) { for (int i = 0; i < m_cache_assoc; i++) {
AbstractCacheEntry* entry = m_cache[cacheSet][i]; AbstractCacheEntry* entry = m_cache[cacheSet][i];
if (entry != NULL) { if (entry != NULL) {
if (entry->m_Address == address || // Already in the cache if (entry->m_Address == address ||
entry->m_Permission == AccessPermission_NotPresent) { // We found an empty entry entry->m_Permission == AccessPermission_NotPresent) {
// Already in the cache or we found an empty entry
return true; return true;
} }
} else { } else {
@@ -237,7 +253,8 @@ bool CacheMemory::cacheAvail(const Address& address) const
return false; return false;
} }
void CacheMemory::allocate(const Address& address, AbstractCacheEntry* entry) void
CacheMemory::allocate(const Address& address, AbstractCacheEntry* entry)
{ {
assert(address == line_address(address)); assert(address == line_address(address));
assert(!isTagPresent(address)); assert(!isTagPresent(address));
@@ -246,17 +263,19 @@ void CacheMemory::allocate(const Address& address, AbstractCacheEntry* entry)
// Find the first open slot // Find the first open slot
Index cacheSet = addressToCacheSet(address); Index cacheSet = addressToCacheSet(address);
Vector<AbstractCacheEntry*> &set = m_cache[cacheSet];
for (int i = 0; i < m_cache_assoc; i++) { for (int i = 0; i < m_cache_assoc; i++) {
if (m_cache[cacheSet][i] == NULL || if (!set[i] || set[i]->m_Permission == AccessPermission_NotPresent) {
m_cache[cacheSet][i]->m_Permission == AccessPermission_NotPresent) { set[i] = entry; // Init entry
m_cache[cacheSet][i] = entry; // Init entry set[i]->m_Address = address;
m_cache[cacheSet][i]->m_Address = address; set[i]->m_Permission = AccessPermission_Invalid;
m_cache[cacheSet][i]->m_Permission = AccessPermission_Invalid; DPRINTF(RubyCache, "Allocate clearing lock for addr: %x\n",
DPRINTF(RubyCache, "Allocate clearing lock for addr: %llx\n", address); address);
m_locked[cacheSet][i] = -1; m_locked[cacheSet][i] = -1;
m_tag_index[address] = i; m_tag_index[address] = i;
m_replacementPolicy_ptr->touch(cacheSet, i, g_eventQueue_ptr->getTime()); m_replacementPolicy_ptr->
touch(cacheSet, i, g_eventQueue_ptr->getTime());
return; return;
} }
@@ -264,34 +283,39 @@ void CacheMemory::allocate(const Address& address, AbstractCacheEntry* entry)
ERROR_MSG("Allocate didn't find an available entry"); ERROR_MSG("Allocate didn't find an available entry");
} }
void CacheMemory::deallocate(const Address& address) void
CacheMemory::deallocate(const Address& address)
{ {
assert(address == line_address(address)); assert(address == line_address(address));
assert(isTagPresent(address)); assert(isTagPresent(address));
DEBUG_EXPR(CACHE_COMP, HighPrio, address); DEBUG_EXPR(CACHE_COMP, HighPrio, address);
Index cacheSet = addressToCacheSet(address); Index cacheSet = addressToCacheSet(address);
int location = findTagInSet(cacheSet, address); int loc = findTagInSet(cacheSet, address);
if (location != -1){ if (loc != -1) {
delete m_cache[cacheSet][location]; delete m_cache[cacheSet][loc];
m_cache[cacheSet][location] = NULL; m_cache[cacheSet][loc] = NULL;
DPRINTF(RubyCache, "Deallocate clearing lock for addr: %llx\n", address); DPRINTF(RubyCache, "Deallocate clearing lock for addr: %x\n",
m_locked[cacheSet][location] = -1; address);
m_locked[cacheSet][loc] = -1;
m_tag_index.erase(address); m_tag_index.erase(address);
} }
} }
// Returns with the physical address of the conflicting cache line // Returns with the physical address of the conflicting cache line
Address CacheMemory::cacheProbe(const Address& address) const Address
CacheMemory::cacheProbe(const Address& address) const
{ {
assert(address == line_address(address)); assert(address == line_address(address));
assert(!cacheAvail(address)); assert(!cacheAvail(address));
Index cacheSet = addressToCacheSet(address); Index cacheSet = addressToCacheSet(address);
return m_cache[cacheSet][m_replacementPolicy_ptr->getVictim(cacheSet)]->m_Address; return m_cache[cacheSet][m_replacementPolicy_ptr->getVictim(cacheSet)]->
m_Address;
} }
// looks an address up in the cache // looks an address up in the cache
AbstractCacheEntry& CacheMemory::lookup(const Address& address) AbstractCacheEntry&
CacheMemory::lookup(const Address& address)
{ {
assert(address == line_address(address)); assert(address == line_address(address));
Index cacheSet = addressToCacheSet(address); Index cacheSet = addressToCacheSet(address);
@@ -301,7 +325,8 @@ AbstractCacheEntry& CacheMemory::lookup(const Address& address)
} }
// looks an address up in the cache // looks an address up in the cache
const AbstractCacheEntry& CacheMemory::lookup(const Address& address) const const AbstractCacheEntry&
CacheMemory::lookup(const Address& address) const
{ {
assert(address == line_address(address)); assert(address == line_address(address));
Index cacheSet = addressToCacheSet(address); Index cacheSet = addressToCacheSet(address);
@@ -310,43 +335,49 @@ const AbstractCacheEntry& CacheMemory::lookup(const Address& address) const
return *m_cache[cacheSet][loc]; return *m_cache[cacheSet][loc];
} }
AccessPermission CacheMemory::getPermission(const Address& address) const AccessPermission
CacheMemory::getPermission(const Address& address) const
{ {
assert(address == line_address(address)); assert(address == line_address(address));
return lookup(address).m_Permission; return lookup(address).m_Permission;
} }
void CacheMemory::changePermission(const Address& address, AccessPermission new_perm) void
CacheMemory::changePermission(const Address& address,
AccessPermission new_perm)
{ {
assert(address == line_address(address)); assert(address == line_address(address));
lookup(address).m_Permission = new_perm; lookup(address).m_Permission = new_perm;
Index cacheSet = addressToCacheSet(address); Index cacheSet = addressToCacheSet(address);
int loc = findTagInSet(cacheSet, address); int loc = findTagInSet(cacheSet, address);
if (new_perm != AccessPermission_Read_Write) { if (new_perm != AccessPermission_Read_Write) {
DPRINTF(RubyCache, "Permission clearing lock for addr: %llx\n", address); DPRINTF(RubyCache, "Permission clearing lock for addr: %x\n", address);
m_locked[cacheSet][loc] = -1; m_locked[cacheSet][loc] = -1;
} }
assert(getPermission(address) == new_perm); assert(getPermission(address) == new_perm);
} }
// Sets the most recently used bit for a cache block // Sets the most recently used bit for a cache block
void CacheMemory::setMRU(const Address& address) void
CacheMemory::setMRU(const Address& address)
{ {
Index cacheSet; Index cacheSet;
cacheSet = addressToCacheSet(address); cacheSet = addressToCacheSet(address);
m_replacementPolicy_ptr->touch(cacheSet, m_replacementPolicy_ptr->
findTagInSet(cacheSet, address), touch(cacheSet, findTagInSet(cacheSet, address),
g_eventQueue_ptr->getTime()); g_eventQueue_ptr->getTime());
} }
void CacheMemory::profileMiss(const CacheMsg & msg) void
CacheMemory::profileMiss(const CacheMsg& msg)
{ {
m_profiler_ptr->addStatSample(msg.getType(), msg.getAccessMode(), m_profiler_ptr->addStatSample(msg.getType(), msg.getAccessMode(),
msg.getSize(), msg.getPrefetch()); msg.getSize(), msg.getPrefetch());
} }
void CacheMemory::recordCacheContents(CacheRecorder& tr) const void
CacheMemory::recordCacheContents(CacheRecorder& tr) const
{ {
for (int i = 0; i < m_cache_num_sets; i++) { for (int i = 0; i < m_cache_num_sets; i++) {
for (int j = 0; j < m_cache_assoc; j++) { for (int j = 0; j < m_cache_assoc; j++) {
@@ -363,14 +394,18 @@ void CacheMemory::recordCacheContents(CacheRecorder& tr) const
} }
if (request_type != CacheRequestType_NULL) { if (request_type != CacheRequestType_NULL) {
// tr.addRecord(m_chip_ptr->getID(), m_cache[i][j].m_Address, #if 0
// Address(0), request_type, m_replacementPolicy_ptr->getLastAccess(i, j)); tr.addRecord(m_chip_ptr->getID(), m_cache[i][j].m_Address,
Address(0), request_type,
m_replacementPolicy_ptr->getLastAccess(i, j));
#endif
} }
} }
} }
} }
void CacheMemory::print(ostream& out) const void
CacheMemory::print(ostream& out) const
{ {
out << "Cache dump: " << m_cache_name << endl; out << "Cache dump: " << m_cache_name << endl;
for (int i = 0; i < m_cache_num_sets; i++) { for (int i = 0; i < m_cache_num_sets; i++) {
@@ -388,36 +423,43 @@ void CacheMemory::print(ostream& out) const
} }
} }
void CacheMemory::printData(ostream& out) const void
CacheMemory::printData(ostream& out) const
{ {
out << "printData() not supported" << endl; out << "printData() not supported" << endl;
} }
void CacheMemory::clearStats() const void
CacheMemory::clearStats() const
{ {
m_profiler_ptr->clearStats(); m_profiler_ptr->clearStats();
} }
void CacheMemory::printStats(ostream& out) const void
CacheMemory::printStats(ostream& out) const
{ {
m_profiler_ptr->printStats(out); m_profiler_ptr->printStats(out);
} }
void CacheMemory::getMemoryValue(const Address& addr, char* value, void
unsigned int size_in_bytes ){ CacheMemory::getMemoryValue(const Address& addr, char* value,
unsigned size_in_bytes)
{
AbstractCacheEntry& entry = lookup(line_address(addr)); AbstractCacheEntry& entry = lookup(line_address(addr));
unsigned int startByte = addr.getAddress() - line_address(addr).getAddress(); unsigned startByte = addr.getAddress() - line_address(addr).getAddress();
for(unsigned int i=0; i<size_in_bytes; ++i){ for (unsigned i = 0; i < size_in_bytes; ++i) {
value[i] = entry.getDataBlk().getByte(i + startByte); value[i] = entry.getDataBlk().getByte(i + startByte);
} }
} }
void CacheMemory::setMemoryValue(const Address& addr, char* value, void
unsigned int size_in_bytes ){ CacheMemory::setMemoryValue(const Address& addr, char* value,
unsigned size_in_bytes)
{
AbstractCacheEntry& entry = lookup(line_address(addr)); AbstractCacheEntry& entry = lookup(line_address(addr));
unsigned int startByte = addr.getAddress() - line_address(addr).getAddress(); unsigned startByte = addr.getAddress() - line_address(addr).getAddress();
assert(size_in_bytes > 0); assert(size_in_bytes > 0);
for(unsigned int i=0; i<size_in_bytes; ++i){ for (unsigned i = 0; i < size_in_bytes; ++i) {
entry.getDataBlk().setByte(i + startByte, value[i]); entry.getDataBlk().setByte(i + startByte, value[i]);
} }
@@ -427,10 +469,7 @@ void CacheMemory::setMemoryValue(const Address& addr, char* value,
void void
CacheMemory::setLocked(const Address& address, int context) CacheMemory::setLocked(const Address& address, int context)
{ {
DPRINTF(RubyCache, DPRINTF(RubyCache, "Setting Lock for addr: %x to %d\n", address, context);
"Setting Lock for addr: %llx to %d\n",
address,
context);
assert(address == line_address(address)); assert(address == line_address(address));
Index cacheSet = addressToCacheSet(address); Index cacheSet = addressToCacheSet(address);
int loc = findTagInSet(cacheSet, address); int loc = findTagInSet(cacheSet, address);
@@ -441,7 +480,7 @@ CacheMemory::setLocked(const Address& address, int context)
void void
CacheMemory::clearLocked(const Address& address) CacheMemory::clearLocked(const Address& address)
{ {
DPRINTF(RubyCache, "Clear Lock for addr: %llx\n", address); DPRINTF(RubyCache, "Clear Lock for addr: %x\n", address);
assert(address == line_address(address)); assert(address == line_address(address));
Index cacheSet = addressToCacheSet(address); Index cacheSet = addressToCacheSet(address);
int loc = findTagInSet(cacheSet, address); int loc = findTagInSet(cacheSet, address);
@@ -456,11 +495,8 @@ CacheMemory::isLocked(const Address& address, int context)
Index cacheSet = addressToCacheSet(address); Index cacheSet = addressToCacheSet(address);
int loc = findTagInSet(cacheSet, address); int loc = findTagInSet(cacheSet, address);
assert(loc != -1); assert(loc != -1);
DPRINTF(RubyCache, DPRINTF(RubyCache, "Testing Lock for addr: %llx cur %d con %d\n",
"Testing Lock for addr: %llx cur %d con %d\n", address, m_locked[cacheSet][loc], context);
address,
m_locked[cacheSet][loc],
context);
return m_locked[cacheSet][loc] == context; return m_locked[cacheSet][loc] == context;
} }

View File

@@ -26,60 +26,50 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
/* #ifndef __MEM_RUBY_SYSTEM_CACHEMEMORY_HH__
* CacheMemory.hh #define __MEM_RUBY_SYSTEM_CACHEMEMORY_HH__
*
* Description:
*
* $Id: CacheMemory.hh,v 3.7 2004/06/18 20:15:15 beckmann Exp $
*
*/
#ifndef CACHEMEMORY_H
#define CACHEMEMORY_H
#include "sim/sim_object.hh"
#include "params/RubyCache.hh"
#include "mem/ruby/common/Global.hh"
#include "mem/protocol/AccessPermission.hh"
#include "mem/ruby/common/Address.hh"
#include "mem/ruby/recorder/CacheRecorder.hh"
#include "mem/protocol/CacheRequestType.hh"
#include "mem/gems_common/Vector.hh"
#include "mem/ruby/common/DataBlock.hh"
#include "mem/protocol/MachineType.hh"
#include "mem/ruby/slicc_interface/RubySlicc_ComponentMapping.hh"
#include "mem/ruby/system/PseudoLRUPolicy.hh"
#include "mem/ruby/system/LRUPolicy.hh"
#include "mem/ruby/slicc_interface/AbstractCacheEntry.hh"
#include "mem/ruby/system/System.hh"
#include "mem/ruby/slicc_interface/AbstractController.hh"
#include "mem/ruby/profiler/CacheProfiler.hh"
#include "mem/protocol/CacheMsg.hh"
#include "base/hashmap.hh"
#include <vector> #include <vector>
class CacheMemory : public SimObject { #include "base/hashmap.hh"
#include "mem/gems_common/Vector.hh"
#include "mem/protocol/AccessPermission.hh"
#include "mem/protocol/CacheMsg.hh"
#include "mem/protocol/CacheRequestType.hh"
#include "mem/protocol/MachineType.hh"
#include "mem/ruby/common/Address.hh"
#include "mem/ruby/common/DataBlock.hh"
#include "mem/ruby/common/Global.hh"
#include "mem/ruby/profiler/CacheProfiler.hh"
#include "mem/ruby/recorder/CacheRecorder.hh"
#include "mem/ruby/slicc_interface/AbstractCacheEntry.hh"
#include "mem/ruby/slicc_interface/AbstractController.hh"
#include "mem/ruby/slicc_interface/RubySlicc_ComponentMapping.hh"
#include "mem/ruby/system/LRUPolicy.hh"
#include "mem/ruby/system/PseudoLRUPolicy.hh"
#include "mem/ruby/system/System.hh"
#include "params/RubyCache.hh"
#include "sim/sim_object.hh"
class CacheMemory : public SimObject
{
public: public:
typedef RubyCacheParams Params; typedef RubyCacheParams Params;
// Constructors
CacheMemory(const Params *p); CacheMemory(const Params *p);
// CacheMemory(const string & name);
void init();
// Destructor
~CacheMemory(); ~CacheMemory();
void init();
// Public Methods // Public Methods
void printConfig(ostream& out); void printConfig(ostream& out);
// perform a cache access and see if we hit or not. Return true on a hit. // perform a cache access and see if we hit or not. Return true on a hit.
bool tryCacheAccess(const Address& address, CacheRequestType type, DataBlock*& data_ptr); bool tryCacheAccess(const Address& address, CacheRequestType type,
DataBlock*& data_ptr);
// similar to above, but doesn't require full access check // similar to above, but doesn't require full access check
bool testCacheAccess(const Address& address, CacheRequestType type, DataBlock*& data_ptr); bool testCacheAccess(const Address& address, CacheRequestType type,
DataBlock*& data_ptr);
// tests to see if an address is present in the cache // tests to see if an address is present in the cache
bool isTagPresent(const Address& address) const; bool isTagPresent(const Address& address) const;
@@ -110,7 +100,11 @@ public:
// Hook for checkpointing the contents of the cache // Hook for checkpointing the contents of the cache
void recordCacheContents(CacheRecorder& tr) const; void recordCacheContents(CacheRecorder& tr) const;
void setAsInstructionCache(bool is_icache) { m_is_instruction_only_cache = is_icache; } void
setAsInstructionCache(bool is_icache)
{
m_is_instruction_only_cache = is_icache;
}
// Set this address to most recently used // Set this address to most recently used
void setMRU(const Address& address); void setMRU(const Address& address);
@@ -133,15 +127,14 @@ public:
void printStats(ostream& out) const; void printStats(ostream& out) const;
private: private:
// Private Methods
// convert a Address to its location in the cache // convert a Address to its location in the cache
Index addressToCacheSet(const Address& address) const; Index addressToCacheSet(const Address& address) const;
// Given a cache tag: returns the index of the tag in a set. // Given a cache tag: returns the index of the tag in a set.
// returns -1 if the tag is not found. // returns -1 if the tag is not found.
int findTagInSet(Index line, const Address& tag) const; int findTagInSet(Index line, const Address& tag) const;
int findTagInSetIgnorePermissions(Index cacheSet, const Address& tag) const; int findTagInSetIgnorePermissions(Index cacheSet,
const Address& tag) const;
// Private copy constructor and assignment operator // Private copy constructor and assignment operator
CacheMemory(const CacheMemory& obj); CacheMemory(const CacheMemory& obj);
@@ -172,5 +165,5 @@ private:
int m_cache_assoc; int m_cache_assoc;
}; };
#endif //CACHEMEMORY_H #endif // __MEM_RUBY_SYSTEM_CACHEMEMORY_HH__

View File

@@ -26,32 +26,28 @@
* 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/ruby/system/DMASequencer.hh"
#include "mem/ruby/buffers/MessageBuffer.hh"
#include "mem/ruby/slicc_interface/AbstractController.hh"
/* SLICC generated types */
#include "mem/protocol/SequencerMsg.hh" #include "mem/protocol/SequencerMsg.hh"
#include "mem/protocol/SequencerRequestType.hh" #include "mem/protocol/SequencerRequestType.hh"
#include "mem/ruby/buffers/MessageBuffer.hh"
#include "mem/ruby/slicc_interface/AbstractController.hh"
#include "mem/ruby/system/DMASequencer.hh"
#include "mem/ruby/system/System.hh" #include "mem/ruby/system/System.hh"
//
// Fix me: This code needs comments!
//
DMASequencer::DMASequencer(const Params *p) DMASequencer::DMASequencer(const Params *p)
: RubyPort(p) : RubyPort(p)
{ {
} }
void DMASequencer::init() void
DMASequencer::init()
{ {
RubyPort::init(); RubyPort::init();
m_is_busy = false; m_is_busy = false;
m_data_block_mask = ~ (~0 << RubySystem::getBlockSizeBits()); m_data_block_mask = ~ (~0 << RubySystem::getBlockSizeBits());
} }
RequestStatus DMASequencer::makeRequest(const RubyRequest & request) RequestStatus
DMASequencer::makeRequest(const RubyRequest &request)
{ {
uint64_t paddr = request.paddr; uint64_t paddr = request.paddr;
uint8_t* data = request.data; uint8_t* data = request.data;
@@ -71,7 +67,7 @@ RequestStatus DMASequencer::makeRequest(const RubyRequest & request)
case RubyRequestType_RMW_Read: case RubyRequestType_RMW_Read:
case RubyRequestType_RMW_Write: case RubyRequestType_RMW_Write:
case RubyRequestType_NUM: case RubyRequestType_NUM:
panic("DMASequencer::makeRequest does not support the RubyRequestType"); panic("DMASequencer::makeRequest does not support RubyRequestType");
return RequestStatus_NULL; return RequestStatus_NULL;
} }
@@ -93,8 +89,7 @@ RequestStatus DMASequencer::makeRequest(const RubyRequest & request)
int offset = paddr & m_data_block_mask; int offset = paddr & m_data_block_mask;
msg.getLen() = (offset + len) <= RubySystem::getBlockSizeBytes() ? msg.getLen() = (offset + len) <= RubySystem::getBlockSizeBytes() ?
len : len : RubySystem::getBlockSizeBytes() - offset;
RubySystem::getBlockSizeBytes() - offset;
if (write) { if (write) {
msg.getDataBlk().setData(data, offset, msg.getLen()); msg.getDataBlk().setData(data, offset, msg.getLen());
@@ -107,7 +102,8 @@ RequestStatus DMASequencer::makeRequest(const RubyRequest & request)
return RequestStatus_Issued; return RequestStatus_Issued;
} }
void DMASequencer::issueNext() void
DMASequencer::issueNext()
{ {
assert(m_is_busy == true); assert(m_is_busy == true);
active_request.bytes_completed = active_request.bytes_issued; active_request.bytes_completed = active_request.bytes_issued;
@@ -127,13 +123,15 @@ void DMASequencer::issueNext()
msg.getType() = (active_request.write ? SequencerRequestType_ST : msg.getType() = (active_request.write ? SequencerRequestType_ST :
SequencerRequestType_LD); SequencerRequestType_LD);
msg.getLen() = (active_request.len - msg.getLen() =
(active_request.len -
active_request.bytes_completed < RubySystem::getBlockSizeBytes() ? active_request.bytes_completed < RubySystem::getBlockSizeBytes() ?
active_request.len - active_request.bytes_completed : active_request.len - active_request.bytes_completed :
RubySystem::getBlockSizeBytes()); RubySystem::getBlockSizeBytes());
if (active_request.write) { if (active_request.write) {
msg.getDataBlk().setData(&active_request.data[active_request.bytes_completed], msg.getDataBlk().
setData(&active_request.data[active_request.bytes_completed],
0, msg.getLen()); 0, msg.getLen());
msg.getType() = SequencerRequestType_ST; msg.getType() = SequencerRequestType_ST;
} else { } else {
@@ -145,7 +143,8 @@ void DMASequencer::issueNext()
active_request.bytes_issued += msg.getLen(); active_request.bytes_issued += msg.getLen();
} }
void DMASequencer::dataCallback(const DataBlock & dblk) void
DMASequencer::dataCallback(const DataBlock & dblk)
{ {
assert(m_is_busy == true); assert(m_is_busy == true);
int len = active_request.bytes_issued - active_request.bytes_completed; int len = active_request.bytes_issued - active_request.bytes_completed;
@@ -158,17 +157,17 @@ void DMASequencer::dataCallback(const DataBlock & dblk)
issueNext(); issueNext();
} }
void DMASequencer::ackCallback() void
DMASequencer::ackCallback()
{ {
issueNext(); issueNext();
} }
void DMASequencer::printConfig(ostream & out) void
DMASequencer::printConfig(ostream & out)
{ {
} }
DMASequencer * DMASequencer *
DMASequencerParams::create() DMASequencerParams::create()
{ {

View File

@@ -26,16 +26,17 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#ifndef DMASEQUENCER_H #ifndef __MEM_RUBY_SYSTEM_DMASEQUENCER_HH__
#define DMASEQUENCER_H #define __MEM_RUBY_SYSTEM_DMASEQUENCER_HH__
#include <ostream> #include <ostream>
#include "mem/ruby/common/DataBlock.hh" #include "mem/ruby/common/DataBlock.hh"
#include "mem/ruby/system/RubyPort.hh" #include "mem/ruby/system/RubyPort.hh"
#include "params/DMASequencer.hh" #include "params/DMASequencer.hh"
struct DMARequest { struct DMARequest
{
uint64_t start_paddr; uint64_t start_paddr;
int len; int len;
bool write; bool write;
@@ -45,7 +46,8 @@ struct DMARequest {
PacketPtr pkt; PacketPtr pkt;
}; };
class DMASequencer :public RubyPort { class DMASequencer : public RubyPort
{
public: public:
typedef DMASequencerParams Params; typedef DMASequencerParams Params;
DMASequencer(const Params *); DMASequencer(const Params *);
@@ -70,4 +72,4 @@ private:
int num_active_requests; int num_active_requests;
}; };
#endif // DMACONTROLLER_H #endif // __MEM_RUBY_SYSTEM_DMASEQUENCER_HH__

View File

@@ -1,4 +1,3 @@
/* /*
* Copyright (c) 1999-2008 Mark D. Hill and David A. Wood * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
* All rights reserved. * All rights reserved.
@@ -27,19 +26,10 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
/*
* DirectoryMemory.cc
*
* Description: See DirectoryMemory.hh
*
* $Id$
*
*/
#include "mem/ruby/system/System.hh"
#include "mem/ruby/system/DirectoryMemory.hh"
#include "mem/ruby/slicc_interface/RubySlicc_Util.hh"
#include "mem/gems_common/util.hh" #include "mem/gems_common/util.hh"
#include "mem/ruby/slicc_interface/RubySlicc_Util.hh"
#include "mem/ruby/system/DirectoryMemory.hh"
#include "mem/ruby/system/System.hh"
int DirectoryMemory::m_num_directories = 0; int DirectoryMemory::m_num_directories = 0;
int DirectoryMemory::m_num_directories_bits = 0; int DirectoryMemory::m_num_directories_bits = 0;
@@ -58,7 +48,8 @@ DirectoryMemory::DirectoryMemory(const Params *p)
m_numa_high_bit = p->numa_high_bit; m_numa_high_bit = p->numa_high_bit;
} }
void DirectoryMemory::init() void
DirectoryMemory::init()
{ {
m_num_entries = m_size_bytes / RubySystem::getBlockSizeBytes(); m_num_entries = m_size_bytes / RubySystem::getBlockSizeBytes();
@@ -98,49 +89,54 @@ DirectoryMemory::~DirectoryMemory()
} }
} }
void DirectoryMemory::printConfig(ostream& out) const void
DirectoryMemory::printConfig(ostream& out) const
{ {
out << "DirectoryMemory module config: " << m_name << endl; out << "DirectoryMemory module config: " << m_name << endl
out << " version: " << m_version << endl; << " version: " << m_version << endl
out << " memory_bits: " << m_size_bits << endl; << " memory_bits: " << m_size_bits << endl
out << " memory_size_bytes: " << m_size_bytes << endl; << " memory_size_bytes: " << m_size_bytes << endl
out << " memory_size_Kbytes: " << double(m_size_bytes) / (1<<10) << endl; << " memory_size_Kbytes: " << double(m_size_bytes) / (1<<10) << endl
out << " memory_size_Mbytes: " << double(m_size_bytes) / (1<<20) << endl; << " memory_size_Mbytes: " << double(m_size_bytes) / (1<<20) << endl
out << " memory_size_Gbytes: " << double(m_size_bytes) / (1<<30) << endl; << " memory_size_Gbytes: " << double(m_size_bytes) / (1<<30) << endl;
} }
// Static method // Static method
void DirectoryMemory::printGlobalConfig(ostream & out) void
DirectoryMemory::printGlobalConfig(ostream & out)
{ {
out << "DirectoryMemory Global Config: " << endl; out << "DirectoryMemory Global Config: " << endl;
out << " number of directory memories: " << m_num_directories << endl; out << " number of directory memories: " << m_num_directories << endl;
if (m_num_directories > 1) { if (m_num_directories > 1) {
out << " number of selection bits: " << m_num_directories_bits << endl; out << " number of selection bits: " << m_num_directories_bits << endl
out << " selection bits: " << m_numa_high_bit << " selection bits: " << m_numa_high_bit
<< "-" << m_numa_high_bit-m_num_directories_bits << "-" << m_numa_high_bit-m_num_directories_bits
<< endl; << endl;
} }
out << " total memory size bytes: " << m_total_size_bytes << endl; out << " total memory size bytes: " << m_total_size_bytes << endl;
out << " total memory bits: " << log_int(m_total_size_bytes) << endl; out << " total memory bits: " << log_int(m_total_size_bytes) << endl;
} }
uint64 DirectoryMemory::mapAddressToDirectoryVersion(PhysAddress address) uint64
DirectoryMemory::mapAddressToDirectoryVersion(PhysAddress address)
{ {
if (m_num_directories_bits == 0) return 0; if (m_num_directories_bits == 0)
return 0;
uint64 ret = address.bitSelect(m_numa_high_bit - m_num_directories_bits, uint64 ret = address.bitSelect(m_numa_high_bit - m_num_directories_bits,
m_numa_high_bit); m_numa_high_bit);
return ret; return ret;
} }
// Public method bool
bool DirectoryMemory::isPresent(PhysAddress address) DirectoryMemory::isPresent(PhysAddress address)
{ {
bool ret = (mapAddressToDirectoryVersion(address) == m_version); bool ret = (mapAddressToDirectoryVersion(address) == m_version);
return ret; return ret;
} }
uint64 DirectoryMemory::mapAddressToLocalIdx(PhysAddress address) uint64
DirectoryMemory::mapAddressToLocalIdx(PhysAddress address)
{ {
uint64 ret = address.bitRemove(m_numa_high_bit - m_num_directories_bits, uint64 ret = address.bitRemove(m_numa_high_bit - m_num_directories_bits,
m_numa_high_bit) m_numa_high_bit)
@@ -148,7 +144,8 @@ uint64 DirectoryMemory::mapAddressToLocalIdx(PhysAddress address)
return ret; return ret;
} }
Directory_Entry& DirectoryMemory::lookup(PhysAddress address) Directory_Entry&
DirectoryMemory::lookup(PhysAddress address)
{ {
assert(isPresent(address)); assert(isPresent(address));
Directory_Entry* entry; Directory_Entry* entry;
@@ -160,9 +157,7 @@ Directory_Entry& DirectoryMemory::lookup(PhysAddress address)
entry = m_sparseMemory->lookup(address); entry = m_sparseMemory->lookup(address);
assert(entry != NULL); assert(entry != NULL);
} else { } else {
//
// Note: SparseMemory internally creates a new Directory Entry // Note: SparseMemory internally creates a new Directory Entry
//
m_sparseMemory->add(address); m_sparseMemory->add(address);
entry = m_sparseMemory->lookup(address); entry = m_sparseMemory->lookup(address);
} }
@@ -178,10 +173,12 @@ Directory_Entry& DirectoryMemory::lookup(PhysAddress address)
} }
} }
return (*entry); return *entry;
} }
/*
Directory_Entry& DirectoryMemory::lookup(PhysAddress address) #if 0
Directory_Entry&
DirectoryMemory::lookup(PhysAddress address)
{ {
assert(isPresent(address)); assert(isPresent(address));
Index index = address.memoryModuleIndex(); Index index = address.memoryModuleIndex();
@@ -190,7 +187,7 @@ Directory_Entry& DirectoryMemory::lookup(PhysAddress address)
WARN_EXPR(address.getAddress()); WARN_EXPR(address.getAddress());
WARN_EXPR(index); WARN_EXPR(index);
WARN_EXPR(m_size); WARN_EXPR(m_size);
ERROR_MSG("Directory Memory Assertion: accessing memory out of range."); ERROR_MSG("Directory Memory Assertion: accessing memory out of range");
} }
Directory_Entry* entry = m_entries[index]; Directory_Entry* entry = m_entries[index];
@@ -203,25 +200,26 @@ Directory_Entry& DirectoryMemory::lookup(PhysAddress address)
m_entries[index] = entry; m_entries[index] = entry;
} }
return (*entry); return *entry;
} }
*/ #endif
void DirectoryMemory::invalidateBlock(PhysAddress address) void
DirectoryMemory::invalidateBlock(PhysAddress address)
{ {
if (m_use_map) { if (m_use_map) {
assert(m_sparseMemory->exist(address)); assert(m_sparseMemory->exist(address));
m_sparseMemory->remove(address); m_sparseMemory->remove(address);
} }
/* #if 0
else { else {
assert(isPresent(address)); assert(isPresent(address));
Index index = address.memoryModuleIndex(); Index index = address.memoryModuleIndex();
if (index < 0 || index > m_size) { if (index < 0 || index > m_size) {
ERROR_MSG("Directory Memory Assertion: accessing memory out of range."); ERROR_MSG("Directory Memory Assertion: "
"accessing memory out of range.");
} }
if (m_entries[index] != NULL){ if (m_entries[index] != NULL){
@@ -229,17 +227,16 @@ void DirectoryMemory::invalidateBlock(PhysAddress address)
m_entries[index] = NULL; m_entries[index] = NULL;
} }
} }
*/ #endif
} }
void DirectoryMemory::print(ostream& out) const void
DirectoryMemory::print(ostream& out) const
{ {
} }
void DirectoryMemory::printStats(ostream& out) const void
DirectoryMemory::printStats(ostream& out) const
{ {
if (m_use_map) { if (m_use_map) {
m_sparseMemory->printStats(out); m_sparseMemory->printStats(out);

View File

@@ -1,4 +1,3 @@
/* /*
* Copyright (c) 1999-2008 Mark D. Hill and David A. Wood * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
* All rights reserved. * All rights reserved.
@@ -27,44 +26,32 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
/* #ifndef __MEM_RUBY_SYSTEM_DIRECTORYMEMORY_HH__
* DirectoryMemory.hh #define __MEM_RUBY_SYSTEM_DIRECTORYMEMORY_HH__
*
* Description:
*
* $Id$
*
*/
#ifndef DIRECTORYMEMORY_H
#define DIRECTORYMEMORY_H
#include "mem/ruby/common/Global.hh"
#include "mem/ruby/common/Address.hh"
#include "mem/ruby/system/MemoryVector.hh"
#include "mem/protocol/Directory_Entry.hh" #include "mem/protocol/Directory_Entry.hh"
#include "sim/sim_object.hh" #include "mem/ruby/common/Address.hh"
#include "params/RubyDirectoryMemory.hh" #include "mem/ruby/common/Global.hh"
#include "mem/ruby/system/MemoryVector.hh"
#include "mem/ruby/system/SparseMemory.hh" #include "mem/ruby/system/SparseMemory.hh"
#include "params/RubyDirectoryMemory.hh"
#include "sim/sim_object.hh"
class DirectoryMemory : public SimObject { class DirectoryMemory : public SimObject
{
public: public:
// Constructors
typedef RubyDirectoryMemoryParams Params; typedef RubyDirectoryMemoryParams Params;
DirectoryMemory(const Params *p); DirectoryMemory(const Params *p);
void init();
// DirectoryMemory(int version);
// Destructor
~DirectoryMemory(); ~DirectoryMemory();
void init();
uint64 mapAddressToLocalIdx(PhysAddress address); uint64 mapAddressToLocalIdx(PhysAddress address);
static uint64 mapAddressToDirectoryVersion(PhysAddress address); static uint64 mapAddressToDirectoryVersion(PhysAddress address);
bool isSparseImplementation() { return m_use_map; } bool isSparseImplementation() { return m_use_map; }
uint64 getSize() { return m_size_bytes; } uint64 getSize() { return m_size_bytes; }
// Public Methods
void printConfig(ostream& out) const; void printConfig(ostream& out) const;
static void printGlobalConfig(ostream & out); static void printGlobalConfig(ostream & out);
bool isPresent(PhysAddress address); bool isPresent(PhysAddress address);
@@ -76,17 +63,15 @@ public:
void printStats(ostream& out) const; void printStats(ostream& out) const;
private: private:
// Private Methods
// Private copy constructor and assignment operator // Private copy constructor and assignment operator
DirectoryMemory(const DirectoryMemory& obj); DirectoryMemory(const DirectoryMemory& obj);
DirectoryMemory& operator=(const DirectoryMemory& obj); DirectoryMemory& operator=(const DirectoryMemory& obj);
private: private:
const string m_name; const string m_name;
// Data Members (m_ prefix)
Directory_Entry **m_entries; Directory_Entry **m_entries;
// int m_size; // # of memory module blocks this directory is responsible for // int m_size; // # of memory module blocks this directory is
// responsible for
uint64 m_size_bytes; uint64 m_size_bytes;
uint64 m_size_bits; uint64 m_size_bits;
uint64 m_num_entries; uint64 m_num_entries;
@@ -103,18 +88,12 @@ private:
int m_map_levels; int m_map_levels;
}; };
// Output operator declaration inline ostream&
ostream& operator<<(ostream& out, const DirectoryMemory& obj); operator<<(ostream& out, const DirectoryMemory& obj)
// ******************* Definitions *******************
// Output operator definition
extern inline
ostream& operator<<(ostream& out, const DirectoryMemory& obj)
{ {
obj.print(out); obj.print(out);
out << flush; out << flush;
return out; return out;
} }
#endif //DIRECTORYMEMORY_H #endif // __MEM_RUBY_SYSTEM_DIRECTORYMEMORY_HH__

View File

@@ -26,16 +26,16 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#ifndef LRUPOLICY_H #ifndef __MEM_RUBY_SYSTEM_LRUPOLICY_HH__
#define LRUPOLICY_H #define __MEM_RUBY_SYSTEM_LRUPOLICY_HH__
#include "mem/ruby/system/AbstractReplacementPolicy.hh" #include "mem/ruby/system/AbstractReplacementPolicy.hh"
/* Simple true LRU replacement policy */ /* Simple true LRU replacement policy */
class LRUPolicy : public AbstractReplacementPolicy { class LRUPolicy : public AbstractReplacementPolicy
{
public: public:
LRUPolicy(Index num_sets, Index assoc); LRUPolicy(Index num_sets, Index assoc);
~LRUPolicy(); ~LRUPolicy();
@@ -54,16 +54,18 @@ LRUPolicy::~LRUPolicy()
{ {
} }
inline inline void
void LRUPolicy::touch(Index set, Index index, Time time){ LRUPolicy::touch(Index set, Index index, Time time)
{
assert(index >= 0 && index < m_assoc); assert(index >= 0 && index < m_assoc);
assert(set >= 0 && set < m_num_sets); assert(set >= 0 && set < m_num_sets);
m_last_ref_ptr[set][index] = time; m_last_ref_ptr[set][index] = time;
} }
inline inline Index
Index LRUPolicy::getVictim(Index set) const { LRUPolicy::getVictim(Index set) const
{
// assert(m_assoc != 0); // assert(m_assoc != 0);
Time time, smallest_time; Time time, smallest_time;
Index smallest_index; Index smallest_index;
@@ -71,9 +73,10 @@ Index LRUPolicy::getVictim(Index set) const {
smallest_index = 0; smallest_index = 0;
smallest_time = m_last_ref_ptr[set][0]; smallest_time = m_last_ref_ptr[set][0];
for (unsigned int i=0; i < m_assoc; i++) { for (unsigned i = 0; i < m_assoc; i++) {
time = m_last_ref_ptr[set][i]; time = m_last_ref_ptr[set][i];
//assert(m_cache[cacheSet][i].m_Permission != AccessPermission_NotPresent); // assert(m_cache[cacheSet][i].m_Permission !=
// AccessPermission_NotPresent);
if (time < smallest_time) { if (time < smallest_time) {
smallest_index = i; smallest_index = i;
@@ -89,4 +92,4 @@ Index LRUPolicy::getVictim(Index set) const {
return smallest_index; return smallest_index;
} }
#endif // PSEUDOLRUBITS_H #endif // __MEM_RUBY_SYSTEM_LRUPOLICY_HH__

View File

@@ -1,4 +1,3 @@
/* /*
* Copyright (c) 1999-2008 Mark D. Hill and David A. Wood * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
* All rights reserved. * All rights reserved.
@@ -27,43 +26,36 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
/* #ifndef __MEM_RUBY_SYSTEM_MACHINEID_HH__
* NodeID.hh #define __MEM_RUBY_SYSTEM_MACHINEID_HH__
*
* Description:
*
* $Id$
*
*/
#ifndef MACHINEID_H
#define MACHINEID_H
#include <iostream> #include <iostream>
#include <string> #include <string>
#include "mem/ruby/common/Global.hh"
#include "mem/gems_common/util.hh" #include "mem/gems_common/util.hh"
#include "mem/protocol/MachineType.hh" #include "mem/protocol/MachineType.hh"
#include "mem/ruby/common/Global.hh"
struct MachineID { struct MachineID
{
MachineType type; MachineType type;
int num; // range: 0 ... number of this machine's components in the system - 1 int num; // range: 0 ... number of this machine's components in system - 1
}; };
extern inline inline std::string
std::string MachineIDToString (MachineID machine) { MachineIDToString(MachineID machine)
{
return MachineType_to_string(machine.type)+"_"+int_to_string(machine.num); return MachineType_to_string(machine.type)+"_"+int_to_string(machine.num);
} }
extern inline inline bool
bool operator==(const MachineID & obj1, const MachineID & obj2) operator==(const MachineID & obj1, const MachineID & obj2)
{ {
return (obj1.type == obj2.type && obj1.num == obj2.num); return (obj1.type == obj2.type && obj1.num == obj2.num);
} }
extern inline inline bool
bool operator!=(const MachineID & obj1, const MachineID & obj2) operator!=(const MachineID & obj1, const MachineID & obj2)
{ {
return (obj1.type != obj2.type || obj1.num != obj2.num); return (obj1.type != obj2.type || obj1.num != obj2.num);
} }
@@ -71,11 +63,8 @@ bool operator!=(const MachineID & obj1, const MachineID & obj2)
// Output operator declaration // Output operator declaration
std::ostream& operator<<(std::ostream& out, const MachineID& obj); std::ostream& operator<<(std::ostream& out, const MachineID& obj);
// ******************* Definitions ******************* inline std::ostream&
operator<<(std::ostream& out, const MachineID& obj)
// Output operator definition
extern inline
std::ostream& operator<<(std::ostream& out, const MachineID& obj)
{ {
if ((obj.type < MachineType_NUM) && (obj.type >= MachineType_FIRST)) { if ((obj.type < MachineType_NUM) && (obj.type >= MachineType_FIRST)) {
out << MachineType_to_string(obj.type); out << MachineType_to_string(obj.type);
@@ -88,5 +77,4 @@ std::ostream& operator<<(std::ostream& out, const MachineID& obj)
return out; return out;
} }
#endif // __MEM_RUBY_SYSTEM_MACHINEID_HH__
#endif //MACHINEID_H

View File

@@ -1,4 +1,3 @@
/* /*
* Copyright (c) 1999-2008 Mark D. Hill and David A. Wood * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
* All rights reserved. * All rights reserved.
@@ -28,8 +27,6 @@
*/ */
/* /*
* MemoryControl.cc
*
* Description: This module simulates a basic DDR-style memory controller * Description: This module simulates a basic DDR-style memory controller
* (and can easily be extended to do FB-DIMM as well). * (and can easily be extended to do FB-DIMM as well).
* *
@@ -105,25 +102,21 @@
* then no more than four activates may happen within any 16 cycle window. * then no more than four activates may happen within any 16 cycle window.
* Refreshes are included in the activates. * Refreshes are included in the activates.
* *
*
* $Id: $
*
*/ */
#include "mem/ruby/common/Global.hh" #include <list>
#include "base/cprintf.hh"
#include "mem/gems_common/Map.hh" #include "mem/gems_common/Map.hh"
#include "mem/ruby/common/Address.hh" #include "mem/ruby/common/Address.hh"
#include "mem/ruby/profiler/Profiler.hh"
#include "mem/ruby/system/System.hh"
#include "mem/ruby/slicc_interface/RubySlicc_ComponentMapping.hh"
#include "mem/ruby/slicc_interface/NetworkMessage.hh"
#include "mem/ruby/network/Network.hh"
#include "mem/ruby/common/Consumer.hh" #include "mem/ruby/common/Consumer.hh"
#include "mem/ruby/common/Global.hh"
#include "mem/ruby/network/Network.hh"
#include "mem/ruby/profiler/Profiler.hh"
#include "mem/ruby/slicc_interface/NetworkMessage.hh"
#include "mem/ruby/slicc_interface/RubySlicc_ComponentMapping.hh"
#include "mem/ruby/system/MemoryControl.hh" #include "mem/ruby/system/MemoryControl.hh"
#include "mem/ruby/system/System.hh"
#include <list>
class Consumer; class Consumer;
@@ -140,7 +133,8 @@ class Consumer;
// Output operator definition // Output operator definition
ostream& operator<<(ostream& out, const MemoryControl& obj) ostream&
operator<<(ostream& out, const MemoryControl& obj)
{ {
obj.print(out); obj.print(out);
out << flush; out << flush;
@@ -178,7 +172,8 @@ MemoryControl::MemoryControl(const Params *p)
m_dimms_per_channel); m_dimms_per_channel);
} }
void MemoryControl::init() void
MemoryControl::init()
{ {
m_msg_counter = 0; m_msg_counter = 0;
@@ -230,22 +225,18 @@ void MemoryControl::init()
} }
} }
MemoryControl::~MemoryControl()
// DESTRUCTOR {
MemoryControl::~MemoryControl () {
delete [] m_bankQueues; delete [] m_bankQueues;
delete [] m_bankBusyCounter; delete [] m_bankBusyCounter;
delete [] m_oldRequest; delete [] m_oldRequest;
delete m_profiler_ptr; delete m_profiler_ptr;
} }
// PUBLIC METHODS
// enqueue new request from directory // enqueue new request from directory
void
void MemoryControl::enqueue (const MsgPtr& message, int latency) { MemoryControl::enqueue(const MsgPtr& message, int latency)
{
Time current_time = g_eventQueue_ptr->getTime(); Time current_time = g_eventQueue_ptr->getTime();
Time arrival_time = current_time + latency; Time arrival_time = current_time + latency;
const MemoryMsg* memMess = dynamic_cast<const MemoryMsg*>(message.ref()); const MemoryMsg* memMess = dynamic_cast<const MemoryMsg*>(message.ref());
@@ -256,9 +247,11 @@ void MemoryControl::enqueue (const MsgPtr& message, int latency) {
enqueueMemRef(thisReq); enqueueMemRef(thisReq);
} }
// Alternate entry point used when we already have a MemoryNode structure built. // Alternate entry point used when we already have a MemoryNode
// structure built.
void MemoryControl::enqueueMemRef (MemoryNode& memRef) { void
MemoryControl::enqueueMemRef(MemoryNode& memRef)
{
m_msg_counter++; m_msg_counter++;
memRef.m_msg_counter = m_msg_counter; memRef.m_msg_counter = m_msg_counter;
Time arrival_time = memRef.m_time; Time arrival_time = memRef.m_time;
@@ -267,8 +260,8 @@ void MemoryControl::enqueueMemRef (MemoryNode& memRef) {
physical_address_t addr = memRef.m_addr; physical_address_t addr = memRef.m_addr;
int bank = getBank(addr); int bank = getBank(addr);
if (m_debug) { if (m_debug) {
printf("New memory request%7d: 0x%08llx %c arrived at %10lld ", m_msg_counter, addr, is_mem_read? 'R':'W', at); cprintf("New memory request%7d: %#08x %c arrived at %10d bank = %3x\n",
printf("bank =%3x\n", bank); m_msg_counter, addr, is_mem_read? 'R':'W', at, bank);
} }
m_profiler_ptr->profileMemReq(bank); m_profiler_ptr->profileMemReq(bank);
@@ -279,61 +272,74 @@ void MemoryControl::enqueueMemRef (MemoryNode& memRef) {
} }
} }
// dequeue, peek, and isReady are used to transfer completed requests // dequeue, peek, and isReady are used to transfer completed requests
// back to the directory // back to the directory
void
void MemoryControl::dequeue () { MemoryControl::dequeue()
{
assert(isReady()); assert(isReady());
m_response_queue.pop_front(); m_response_queue.pop_front();
} }
const Message*
const Message* MemoryControl::peek () { MemoryControl::peek()
{
MemoryNode node = peekNode(); MemoryNode node = peekNode();
Message* msg_ptr = node.m_msgptr.ref(); Message* msg_ptr = node.m_msgptr.ref();
assert(msg_ptr != NULL); assert(msg_ptr != NULL);
return msg_ptr; return msg_ptr;
} }
MemoryNode
MemoryNode MemoryControl::peekNode () { MemoryControl::peekNode()
{
assert(isReady()); assert(isReady());
MemoryNode req = m_response_queue.front(); MemoryNode req = m_response_queue.front();
uint64 returnTime = req.m_time; uint64 returnTime = req.m_time;
if (m_debug) { if (m_debug) {
printf("Old memory request%7d: 0x%08llx %c peeked at %10lld\n", cprintf("Old memory request%7d: %#08x %c peeked at %10d\n",
req.m_msg_counter, req.m_addr, req.m_is_mem_read? 'R':'W', returnTime); req.m_msg_counter, req.m_addr, req.m_is_mem_read ? 'R':'W',
returnTime);
} }
return req; return req;
} }
bool
bool MemoryControl::isReady () { MemoryControl::isReady()
{
return ((!m_response_queue.empty()) && return ((!m_response_queue.empty()) &&
(m_response_queue.front().m_time <= g_eventQueue_ptr->getTime())); (m_response_queue.front().m_time <= g_eventQueue_ptr->getTime()));
} }
void MemoryControl::setConsumer (Consumer* consumer_ptr) { void
MemoryControl::setConsumer(Consumer* consumer_ptr)
{
m_consumer_ptr = consumer_ptr; m_consumer_ptr = consumer_ptr;
} }
void MemoryControl::print (ostream& out) const { void
MemoryControl::print(ostream& out) const
{
} }
void
void MemoryControl::printConfig (ostream& out) { MemoryControl::printConfig(ostream& out)
{
out << "Memory Control " << name() << ":" << endl; out << "Memory Control " << name() << ":" << endl;
out << " Ruby cycles per memory cycle: " << m_mem_bus_cycle_multiplier << endl; out << " Ruby cycles per memory cycle: " << m_mem_bus_cycle_multiplier
<< endl;
out << " Basic read latency: " << m_mem_ctl_latency << endl; out << " Basic read latency: " << m_mem_ctl_latency << endl;
if (m_mem_fixed_delay) { if (m_mem_fixed_delay) {
out << " Fixed Latency mode: Added cycles = " << m_mem_fixed_delay << endl; out << " Fixed Latency mode: Added cycles = " << m_mem_fixed_delay
<< endl;
} else { } else {
out << " Bank busy time: " << m_bank_busy_time << " memory cycles" << endl; out << " Bank busy time: " << m_bank_busy_time << " memory cycles"
<< endl;
out << " Memory channel busy time: " << m_basic_bus_busy_time << endl; out << " Memory channel busy time: " << m_basic_bus_busy_time << endl;
out << " Dead cycles between reads to different ranks: " << m_rank_rank_delay << endl; out << " Dead cycles between reads to different ranks: "
out << " Dead cycle between a read and a write: " << m_read_write_delay << endl; << m_rank_rank_delay << endl;
out << " Dead cycle between a read and a write: "
<< m_read_write_delay << endl;
out << " tFaw (four-activate) window: " << m_tFaw << endl; out << " tFaw (four-activate) window: " << m_tFaw << endl;
} }
out << " Banks per rank: " << m_banks_per_rank << endl; out << " Banks per rank: " << m_banks_per_rank << endl;
@@ -347,29 +353,28 @@ void MemoryControl::printConfig (ostream& out) {
out << " Arbitration randomness: " << m_mem_random_arbitrate << endl; out << " Arbitration randomness: " << m_mem_random_arbitrate << endl;
} }
void
void MemoryControl::setDebug (int debugFlag) { MemoryControl::setDebug(int debugFlag)
{
m_debug = debugFlag; m_debug = debugFlag;
} }
void MemoryControl::clearStats() const void
MemoryControl::clearStats() const
{ {
m_profiler_ptr->clearStats(); m_profiler_ptr->clearStats();
} }
void MemoryControl::printStats(ostream& out) const void
MemoryControl::printStats(ostream& out) const
{ {
m_profiler_ptr->printStats(out); m_profiler_ptr->printStats(out);
} }
// ****************************************************************
// PRIVATE METHODS
// Queue up a completed request to send back to directory // Queue up a completed request to send back to directory
void
void MemoryControl::enqueueToDirectory (MemoryNode req, int latency) { MemoryControl::enqueueToDirectory(MemoryNode req, int latency)
{
Time arrival_time = g_eventQueue_ptr->getTime() Time arrival_time = g_eventQueue_ptr->getTime()
+ (latency * m_mem_bus_cycle_multiplier); + (latency * m_mem_bus_cycle_multiplier);
req.m_time = arrival_time; req.m_time = arrival_time;
@@ -379,12 +384,11 @@ void MemoryControl::enqueueToDirectory (MemoryNode req, int latency) {
g_eventQueue_ptr->scheduleEventAbsolute(m_consumer_ptr, arrival_time); g_eventQueue_ptr->scheduleEventAbsolute(m_consumer_ptr, arrival_time);
} }
// getBank returns an integer that is unique for each // getBank returns an integer that is unique for each
// bank across this memory controller. // bank across this memory controller.
int
int MemoryControl::getBank (physical_address_t addr) { MemoryControl::getBank(physical_address_t addr)
{
int dimm = (addr >> m_dimm_bit_0) & (m_dimms_per_channel - 1); int dimm = (addr >> m_dimm_bit_0) & (m_dimms_per_channel - 1);
int rank = (addr >> m_rank_bit_0) & (m_ranks_per_dimm - 1); int rank = (addr >> m_rank_bit_0) & (m_ranks_per_dimm - 1);
int bank = (addr >> m_bank_bit_0) & (m_banks_per_rank - 1); int bank = (addr >> m_bank_bit_0) & (m_banks_per_rank - 1);
@@ -395,88 +399,109 @@ int MemoryControl::getBank (physical_address_t addr) {
// getRank returns an integer that is unique for each rank // getRank returns an integer that is unique for each rank
// and independent of individual bank. // and independent of individual bank.
int
int MemoryControl::getRank (int bank) { MemoryControl::getRank(int bank)
{
int rank = (bank / m_banks_per_rank); int rank = (bank / m_banks_per_rank);
assert (rank < (m_ranks_per_dimm * m_dimms_per_channel)); assert (rank < (m_ranks_per_dimm * m_dimms_per_channel));
return rank; return rank;
} }
// queueReady determines if the head item in a bank queue // queueReady determines if the head item in a bank queue
// can be issued this cycle // can be issued this cycle
bool
bool MemoryControl::queueReady (int bank) { MemoryControl::queueReady(int bank)
{
if ((m_bankBusyCounter[bank] > 0) && !m_mem_fixed_delay) { if ((m_bankBusyCounter[bank] > 0) && !m_mem_fixed_delay) {
m_profiler_ptr->profileMemBankBusy(); m_profiler_ptr->profileMemBankBusy();
//if (m_debug) printf(" bank %x busy %d\n", bank, m_bankBusyCounter[bank]); #if 0
if (m_debug)
printf(" bank %x busy %d\n", bank, m_bankBusyCounter[bank]);
#endif
return false; return false;
} }
if (m_mem_random_arbitrate >= 2) { if (m_mem_random_arbitrate >= 2) {
if ((random() % 100) < m_mem_random_arbitrate) { if ((random() % 100) < m_mem_random_arbitrate) {
m_profiler_ptr->profileMemRandBusy(); m_profiler_ptr->profileMemRandBusy();
return false; return false;
} }
} }
if (m_mem_fixed_delay) return true;
if (m_mem_fixed_delay)
return true;
if ((m_ageCounter > (2 * m_bank_busy_time)) && !m_oldRequest[bank]) { if ((m_ageCounter > (2 * m_bank_busy_time)) && !m_oldRequest[bank]) {
m_profiler_ptr->profileMemNotOld(); m_profiler_ptr->profileMemNotOld();
return false; return false;
} }
if (m_busBusyCounter_Basic == m_basic_bus_busy_time) { if (m_busBusyCounter_Basic == m_basic_bus_busy_time) {
// Another bank must have issued this same cycle. // Another bank must have issued this same cycle. For
// For profiling, we count this as an arb wait rather than // profiling, we count this as an arb wait rather than a bus
// a bus wait. This is a little inaccurate since it MIGHT // wait. This is a little inaccurate since it MIGHT have also
// have also been blocked waiting for a read-write or a // been blocked waiting for a read-write or a read-read
// read-read instead, but it's pretty close. // instead, but it's pretty close.
m_profiler_ptr->profileMemArbWait(1); m_profiler_ptr->profileMemArbWait(1);
return false; return false;
} }
if (m_busBusyCounter_Basic > 0) { if (m_busBusyCounter_Basic > 0) {
m_profiler_ptr->profileMemBusBusy(); m_profiler_ptr->profileMemBusBusy();
return false; return false;
} }
int rank = getRank(bank); int rank = getRank(bank);
if (m_tfaw_count[rank] >= ACTIVATE_PER_TFAW) { if (m_tfaw_count[rank] >= ACTIVATE_PER_TFAW) {
m_profiler_ptr->profileMemTfawBusy(); m_profiler_ptr->profileMemTfawBusy();
return false; return false;
} }
bool write = !m_bankQueues[bank].front().m_is_mem_read; bool write = !m_bankQueues[bank].front().m_is_mem_read;
if (write && (m_busBusyCounter_Write > 0)) { if (write && (m_busBusyCounter_Write > 0)) {
m_profiler_ptr->profileMemReadWriteBusy(); m_profiler_ptr->profileMemReadWriteBusy();
return false; return false;
} }
if (!write && (rank != m_busBusy_WhichRank) if (!write && (rank != m_busBusy_WhichRank)
&& (m_busBusyCounter_ReadNewRank > 0)) { && (m_busBusyCounter_ReadNewRank > 0)) {
m_profiler_ptr->profileMemDataBusBusy(); m_profiler_ptr->profileMemDataBusBusy();
return false; return false;
} }
return true; return true;
} }
// issueRefresh checks to see if this bank has a refresh scheduled // issueRefresh checks to see if this bank has a refresh scheduled
// and, if so, does the refresh and returns true // and, if so, does the refresh and returns true
bool
bool MemoryControl::issueRefresh (int bank) { MemoryControl::issueRefresh(int bank)
if (!m_need_refresh || (m_refresh_bank != bank)) return false; {
if (m_bankBusyCounter[bank] > 0) return false; if (!m_need_refresh || (m_refresh_bank != bank))
return false;
if (m_bankBusyCounter[bank] > 0)
return false;
// Note that m_busBusyCounter will prevent multiple issues during // Note that m_busBusyCounter will prevent multiple issues during
// the same cycle, as well as on different but close cycles: // the same cycle, as well as on different but close cycles:
if (m_busBusyCounter_Basic > 0) return false; if (m_busBusyCounter_Basic > 0)
return false;
int rank = getRank(bank); int rank = getRank(bank);
if (m_tfaw_count[rank] >= ACTIVATE_PER_TFAW) return false; if (m_tfaw_count[rank] >= ACTIVATE_PER_TFAW)
return false;
// Issue it: // Issue it:
#if 0
if (m_debug) {
uint64 current_time = g_eventQueue_ptr->getTime();
printf(" Refresh bank %3x at %lld\n", bank, current_time);
}
#endif
//if (m_debug) {
//uint64 current_time = g_eventQueue_ptr->getTime();
//printf(" Refresh bank %3x at %lld\n", bank, current_time);
//}
m_profiler_ptr->profileMemRefresh(); m_profiler_ptr->profileMemRefresh();
m_need_refresh--; m_need_refresh--;
m_refresh_bank++; m_refresh_bank++;
if (m_refresh_bank >= m_total_banks) m_refresh_bank = 0; if (m_refresh_bank >= m_total_banks)
m_refresh_bank = 0;
m_bankBusyCounter[bank] = m_bank_busy_time; m_bankBusyCounter[bank] = m_bank_busy_time;
m_busBusyCounter_Basic = m_basic_bus_busy_time; m_busBusyCounter_Basic = m_basic_bus_busy_time;
m_busBusyCounter_Write = m_basic_bus_busy_time; m_busBusyCounter_Write = m_basic_bus_busy_time;
@@ -485,29 +510,31 @@ bool MemoryControl::issueRefresh (int bank) {
return true; return true;
} }
// Mark the activate in the tFaw shift register // Mark the activate in the tFaw shift register
void MemoryControl::markTfaw (int rank) { void
MemoryControl::markTfaw(int rank)
{
if (m_tFaw) { if (m_tFaw) {
m_tfaw_shift[rank] |= (1 << (m_tFaw-1)); m_tfaw_shift[rank] |= (1 << (m_tFaw-1));
m_tfaw_count[rank]++; m_tfaw_count[rank]++;
} }
} }
// Issue a memory request: Activate the bank, reserve the address and
// Issue a memory request: Activate the bank, // data buses, and queue the request for return to the requesting
// reserve the address and data buses, and queue
// the request for return to the requesting
// processor after a fixed latency. // processor after a fixed latency.
void
void MemoryControl::issueRequest (int bank) { MemoryControl::issueRequest(int bank)
{
int rank = getRank(bank); int rank = getRank(bank);
MemoryNode req = m_bankQueues[bank].front(); MemoryNode req = m_bankQueues[bank].front();
m_bankQueues[bank].pop_front(); m_bankQueues[bank].pop_front();
if (m_debug) { if (m_debug) {
uint64 current_time = g_eventQueue_ptr->getTime(); uint64 current_time = g_eventQueue_ptr->getTime();
printf(" Mem issue request%7d: 0x%08llx %c at %10lld bank =%3x\n", cprintf(" Mem issue request%7d: %#08x %c at %10d "
req.m_msg_counter, req.m_addr, req.m_is_mem_read? 'R':'W', current_time, bank); "bank=%3x\n",
req.m_msg_counter, req.m_addr, req.m_is_mem_read? 'R':'W',
current_time, bank);
} }
if (req.m_msgptr.ref() != NULL) { // don't enqueue L3 writebacks if (req.m_msgptr.ref() != NULL) { // don't enqueue L3 writebacks
enqueueToDirectory(req, m_mem_ctl_latency + m_mem_fixed_delay); enqueueToDirectory(req, m_mem_ctl_latency + m_mem_fixed_delay);
@@ -520,7 +547,8 @@ void MemoryControl::issueRequest (int bank) {
m_profiler_ptr->profileMemRead(); m_profiler_ptr->profileMemRead();
m_busBusyCounter_Basic = m_basic_bus_busy_time; m_busBusyCounter_Basic = m_basic_bus_busy_time;
m_busBusyCounter_Write = m_basic_bus_busy_time + m_read_write_delay; m_busBusyCounter_Write = m_basic_bus_busy_time + m_read_write_delay;
m_busBusyCounter_ReadNewRank = m_basic_bus_busy_time + m_rank_rank_delay; m_busBusyCounter_ReadNewRank =
m_basic_bus_busy_time + m_rank_rank_delay;
} else { } else {
m_profiler_ptr->profileMemWrite(); m_profiler_ptr->profileMemWrite();
m_busBusyCounter_Basic = m_basic_bus_busy_time; m_busBusyCounter_Basic = m_basic_bus_busy_time;
@@ -529,18 +557,21 @@ void MemoryControl::issueRequest (int bank) {
} }
} }
// executeCycle: This function is called once per memory clock cycle // executeCycle: This function is called once per memory clock cycle
// to simulate all the periodic hardware. // to simulate all the periodic hardware.
void
void MemoryControl::executeCycle () { MemoryControl::executeCycle()
{
// Keep track of time by counting down the busy counters: // Keep track of time by counting down the busy counters:
for (int bank=0; bank < m_total_banks; bank++) { for (int bank=0; bank < m_total_banks; bank++) {
if (m_bankBusyCounter[bank] > 0) m_bankBusyCounter[bank]--; if (m_bankBusyCounter[bank] > 0) m_bankBusyCounter[bank]--;
} }
if (m_busBusyCounter_Write > 0) m_busBusyCounter_Write--; if (m_busBusyCounter_Write > 0)
if (m_busBusyCounter_ReadNewRank > 0) m_busBusyCounter_ReadNewRank--; m_busBusyCounter_Write--;
if (m_busBusyCounter_Basic > 0) m_busBusyCounter_Basic--; if (m_busBusyCounter_ReadNewRank > 0)
m_busBusyCounter_ReadNewRank--;
if (m_busBusyCounter_Basic > 0)
m_busBusyCounter_Basic--;
// Count down the tFAW shift registers: // Count down the tFAW shift registers:
for (int rank=0; rank < m_total_ranks; rank++) { for (int rank=0; rank < m_total_ranks; rank++) {
@@ -553,7 +584,9 @@ void MemoryControl::executeCycle () {
if (!m_mem_fixed_delay) m_refresh_count--; if (!m_mem_fixed_delay) m_refresh_count--;
if (m_refresh_count == 0) { if (m_refresh_count == 0) {
m_refresh_count = m_refresh_period_system; m_refresh_count = m_refresh_period_system;
assert (m_need_refresh < 10); // Are we overrunning our ability to refresh?
// Are we overrunning our ability to refresh?
assert(m_need_refresh < 10);
m_need_refresh++; m_need_refresh++;
} }
@@ -575,14 +608,12 @@ void MemoryControl::executeCycle () {
m_roundRobin = random() % m_total_banks; m_roundRobin = random() % m_total_banks;
} }
// For each channel, scan round-robin, and pick an old, ready // For each channel, scan round-robin, and pick an old, ready
// request and issue it. Treat a refresh request as if it // request and issue it. Treat a refresh request as if it were at
// were at the head of its bank queue. After we issue something, // the head of its bank queue. After we issue something, keep
// keep scanning the queues just to gather statistics about // scanning the queues just to gather statistics about how many
// how many are waiting. If in mem_fixed_delay mode, we can issue // are waiting. If in mem_fixed_delay mode, we can issue more
// more than one request per cycle. // than one request per cycle.
int queueHeads = 0; int queueHeads = 0;
int banksIssued = 0; int banksIssued = 0;
for (int i = 0; i < m_total_banks; i++) { for (int i = 0; i < m_total_banks; i++) {
@@ -594,7 +625,8 @@ void MemoryControl::executeCycle () {
m_profiler_ptr->profileMemBankQ(qs-1); m_profiler_ptr->profileMemBankQ(qs-1);
} }
if (qs > 0) { if (qs > 0) {
m_idleCount = IDLECOUNT_MAX_VALUE; // we're not idle if anything is queued // we're not idle if anything is queued
m_idleCount = IDLECOUNT_MAX_VALUE;
queueHeads++; queueHeads++;
if (queueReady(m_roundRobin)) { if (queueReady(m_roundRobin)) {
issueRequest(m_roundRobin); issueRequest(m_roundRobin);
@@ -606,18 +638,19 @@ void MemoryControl::executeCycle () {
} }
} }
// memWaitCycles is a redundant catch-all for the specific counters in queueReady // memWaitCycles is a redundant catch-all for the specific
// counters in queueReady
m_profiler_ptr->profileMemWaitCycles(queueHeads - banksIssued); m_profiler_ptr->profileMemWaitCycles(queueHeads - banksIssued);
// Check input queue and move anything to bank queues if not full. // Check input queue and move anything to bank queues if not full.
// Since this is done here at the end of the cycle, there will always // Since this is done here at the end of the cycle, there will
// be at least one cycle of latency in the bank queue. // always be at least one cycle of latency in the bank queue. We
// We deliberately move at most one request per cycle (to simulate // deliberately move at most one request per cycle (to simulate
// typical hardware). Note that if one bank queue fills up, other // typical hardware). Note that if one bank queue fills up, other
// requests can get stuck behind it here. // requests can get stuck behind it here.
if (!m_input_queue.empty()) { if (!m_input_queue.empty()) {
m_idleCount = IDLECOUNT_MAX_VALUE; // we're not idle if anything is pending // we're not idle if anything is pending
m_idleCount = IDLECOUNT_MAX_VALUE;
MemoryNode req = m_input_queue.front(); MemoryNode req = m_input_queue.front();
int bank = getBank(req.m_addr); int bank = getBank(req.m_addr);
if (m_bankQueues[bank].size() < m_bank_queue_size) { if (m_bankQueues[bank].size() < m_bank_queue_size) {
@@ -628,11 +661,10 @@ void MemoryControl::executeCycle () {
} }
} }
// wakeup: This function is called once per memory controller clock cycle. // wakeup: This function is called once per memory controller clock cycle.
void
void MemoryControl::wakeup () { MemoryControl::wakeup()
{
// execute everything // execute everything
executeCycle(); executeCycle();

View File

@@ -1,4 +1,3 @@
/* /*
* Copyright (c) 1999-2008 Mark D. Hill and David A. Wood * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
* All rights reserved. * All rights reserved.
@@ -27,35 +26,25 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
/* #ifndef __MEM_RUBY_SYSTEM_MEMORY_CONTROL_HH__
* MemoryControl.hh #define __MEM_RUBY_SYSTEM_MEMORY_CONTROL_HH__
*
* Description: See MemoryControl.cc
*
* $Id: $
*
*/
#ifndef MEMORY_CONTROL_H
#define MEMORY_CONTROL_H
#include "mem/ruby/common/Global.hh"
#include "mem/gems_common/Map.hh"
#include "mem/ruby/common/Address.hh"
#include "mem/ruby/profiler/MemCntrlProfiler.hh"
#include "mem/ruby/system/System.hh"
#include "mem/ruby/slicc_interface/Message.hh"
#include "mem/gems_common/util.hh"
#include "mem/ruby/system/MemoryNode.hh"
// Note that "MemoryMsg" is in the "generated" directory:
#include "mem/protocol/MemoryMsg.hh"
#include "mem/ruby/common/Consumer.hh"
#include "mem/ruby/system/AbstractMemOrCache.hh"
#include "sim/sim_object.hh"
#include "params/RubyMemoryControl.hh"
#include <list> #include <list>
#include "mem/gems_common/Map.hh"
#include "mem/gems_common/util.hh"
#include "mem/protocol/MemoryMsg.hh"
#include "mem/ruby/common/Address.hh"
#include "mem/ruby/common/Consumer.hh"
#include "mem/ruby/common/Global.hh"
#include "mem/ruby/profiler/MemCntrlProfiler.hh"
#include "mem/ruby/slicc_interface/Message.hh"
#include "mem/ruby/system/AbstractMemOrCache.hh"
#include "mem/ruby/system/MemoryNode.hh"
#include "mem/ruby/system/System.hh"
#include "params/RubyMemoryControl.hh"
#include "sim/sim_object.hh"
// This constant is part of the definition of tFAW; see // This constant is part of the definition of tFAW; see
// the comments in header to MemoryControl.cc // the comments in header to MemoryControl.cc
#define ACTIVATE_PER_TFAW 4 #define ACTIVATE_PER_TFAW 4
@@ -64,19 +53,16 @@
class Consumer; class Consumer;
class MemoryControl : public SimObject, public Consumer, public AbstractMemOrCache { class MemoryControl :
public SimObject, public Consumer, public AbstractMemOrCache
{
public: public:
// Constructors
typedef RubyMemoryControlParams Params; typedef RubyMemoryControlParams Params;
MemoryControl(const Params *p); MemoryControl(const Params *p);
void init(); void init();
// Destructor
~MemoryControl(); ~MemoryControl();
// Public Methods
void wakeup(); void wakeup();
void setConsumer(Consumer* consumer_ptr); void setConsumer(Consumer* consumer_ptr);
@@ -102,14 +88,12 @@ public:
void clearStats() const; void clearStats() const;
void printStats(ostream& out) const; void printStats(ostream& out) const;
//added by SS //added by SS
int getBanksPerRank() { return m_banks_per_rank; }; int getBanksPerRank() { return m_banks_per_rank; };
int getRanksPerDimm() { return m_ranks_per_dimm; }; int getRanksPerDimm() { return m_ranks_per_dimm; };
int getDimmsPerChannel() { return m_dimms_per_channel; } int getDimmsPerChannel() { return m_dimms_per_channel; }
private: private:
void enqueueToDirectory(MemoryNode req, int latency); void enqueueToDirectory(MemoryNode req, int latency);
int getBank(physical_address_t addr); int getBank(physical_address_t addr);
int getRank(int bank); int getRank(int bank);
@@ -152,7 +136,6 @@ private:
int m_refresh_period_system; int m_refresh_period_system;
// queues where memory requests live // queues where memory requests live
list<MemoryNode> m_response_queue; list<MemoryNode> m_response_queue;
list<MemoryNode> m_input_queue; list<MemoryNode> m_input_queue;
list<MemoryNode>* m_bankQueues; list<MemoryNode>* m_bankQueues;
@@ -183,5 +166,4 @@ private:
MemCntrlProfiler* m_profiler_ptr; MemCntrlProfiler* m_profiler_ptr;
}; };
#endif // MEMORY_CONTROL_H #endif // __MEM_RUBY_SYSTEM_MEMORY_CONTROL_HH__

View File

@@ -30,7 +30,8 @@
using namespace std; using namespace std;
void MemoryNode::print(ostream& out) const void
MemoryNode::print(ostream& out) const
{ {
out << "["; out << "[";
out << m_time << ", "; out << m_time << ", ";

View File

@@ -35,22 +35,22 @@
* message is enqueued to be sent back to the directory. * message is enqueued to be sent back to the directory.
*/ */
#ifndef MEMORYNODE_H #ifndef __MEM_RUBY_SYSTEM_MEMORYNODE_HH__
#define MEMORYNODE_H #define __MEM_RUBY_SYSTEM_MEMORYNODE_HH__
#include <iostream> #include <iostream>
#include "mem/protocol/MemoryRequestType.hh"
#include "mem/ruby/common/Global.hh" #include "mem/ruby/common/Global.hh"
#include "mem/ruby/slicc_interface/Message.hh" #include "mem/ruby/slicc_interface/Message.hh"
#include "mem/protocol/MemoryRequestType.hh"
class MemoryNode {
class MemoryNode
{
public: public:
// Constructors // old constructor
MemoryNode(const Time& time, int counter, const MsgPtr& msgptr,
// old one: const physical_address_t addr, const bool is_mem_read)
MemoryNode(const Time& time, int counter, const MsgPtr& msgptr, const physical_address_t addr, const bool is_mem_read) { {
m_time = time; m_time = time;
m_msg_counter = counter; m_msg_counter = counter;
m_msgptr = msgptr; m_msgptr = msgptr;
@@ -59,8 +59,11 @@ public:
m_is_dirty_wb = !is_mem_read; m_is_dirty_wb = !is_mem_read;
} }
// new one: // new constructor
MemoryNode(const Time& time, const MsgPtr& msgptr, const physical_address_t addr, const bool is_mem_read, const bool is_dirty_wb) { MemoryNode(const Time& time, const MsgPtr& msgptr,
const physical_address_t addr, const bool is_mem_read,
const bool is_dirty_wb)
{
m_time = time; m_time = time;
m_msg_counter = 0; m_msg_counter = 0;
m_msgptr = msgptr; m_msgptr = msgptr;
@@ -69,14 +72,8 @@ public:
m_is_dirty_wb = is_dirty_wb; m_is_dirty_wb = is_dirty_wb;
} }
// Destructor
~MemoryNode() {};
// Public Methods
void print(std::ostream& out) const; void print(std::ostream& out) const;
// Data Members (m_ prefix) (all public -- this is really more a struct)
Time m_time; Time m_time;
int m_msg_counter; int m_msg_counter;
MsgPtr m_msgptr; MsgPtr m_msgptr;
@@ -85,18 +82,12 @@ public:
bool m_is_dirty_wb; bool m_is_dirty_wb;
}; };
// Output operator declaration inline std::ostream&
std::ostream& operator<<(std::ostream& out, const MemoryNode& obj); operator<<(std::ostream& out, const MemoryNode& obj)
// ******************* Definitions *******************
// Output operator definition
extern inline
std::ostream& operator<<(std::ostream& out, const MemoryNode& obj)
{ {
obj.print(out); obj.print(out);
out << std::flush; out << std::flush;
return out; return out;
} }
#endif //MEMORYNODE_H #endif // __MEM_RUBY_SYSTEM_MEMORYNODE_HH__

View File

@@ -26,8 +26,8 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#ifndef MEMORYVECTOR_H #ifndef __MEM_RUBY_SYSTEM_MEMORYVECTOR_HH__
#define MEMORYVECTOR_H #define __MEM_RUBY_SYSTEM_MEMORYVECTOR_HH__
#include "mem/ruby/common/Address.hh" #include "mem/ruby/common/Address.hh"
@@ -36,7 +36,8 @@ class DirectoryMemory;
/** /**
* MemoryVector holds memory data (DRAM only) * MemoryVector holds memory data (DRAM only)
*/ */
class MemoryVector { class MemoryVector
{
public: public:
MemoryVector(); MemoryVector();
MemoryVector(uint32 size); MemoryVector(uint32 size);
@@ -84,8 +85,8 @@ MemoryVector::~MemoryVector()
delete [] m_pages; delete [] m_pages;
} }
inline inline void
void MemoryVector::setSize(uint32 size) MemoryVector::setSize(uint32 size)
{ {
if (m_pages != NULL){ if (m_pages != NULL){
for (int i = 0; i < m_num_pages; i++) { for (int i = 0; i < m_num_pages; i++) {
@@ -102,8 +103,8 @@ void MemoryVector::setSize(uint32 size)
memset(m_pages, 0, m_num_pages * sizeof(uint8*)); memset(m_pages, 0, m_num_pages * sizeof(uint8*));
} }
inline inline void
void MemoryVector::write(const Address & paddr, uint8* data, int len) MemoryVector::write(const Address & paddr, uint8* data, int len)
{ {
assert(paddr.getAddress() + len <= m_size); assert(paddr.getAddress() + len <= m_size);
uint32 page_num = paddr.getAddress() >> 12; uint32 page_num = paddr.getAddress() >> 12;
@@ -115,31 +116,34 @@ void MemoryVector::write(const Address & paddr, uint8* data, int len)
break; break;
} }
} }
if (all_zeros) return; if (all_zeros)
return;
m_pages[page_num] = new uint8[4096]; m_pages[page_num] = new uint8[4096];
memset(m_pages[page_num], 0, 4096); memset(m_pages[page_num], 0, 4096);
uint32 offset = paddr.getAddress() & m_page_offset_mask; uint32 offset = paddr.getAddress() & m_page_offset_mask;
memcpy(&m_pages[page_num][offset], data, len); memcpy(&m_pages[page_num][offset], data, len);
} else { } else {
memcpy(&m_pages[page_num][paddr.getAddress()&m_page_offset_mask], data, len); memcpy(&m_pages[page_num][paddr.getAddress()&m_page_offset_mask],
data, len);
} }
} }
inline inline uint8*
uint8* MemoryVector::read(const Address & paddr, uint8* data, int len) MemoryVector::read(const Address & paddr, uint8* data, int len)
{ {
assert(paddr.getAddress() + len <= m_size); assert(paddr.getAddress() + len <= m_size);
uint32 page_num = paddr.getAddress() >> 12; uint32 page_num = paddr.getAddress() >> 12;
if (m_pages[page_num] == 0) { if (m_pages[page_num] == 0) {
memset(data, 0, len); memset(data, 0, len);
} else { } else {
memcpy(data, &m_pages[page_num][paddr.getAddress()&m_page_offset_mask], len); memcpy(data, &m_pages[page_num][paddr.getAddress()&m_page_offset_mask],
len);
} }
return data; return data;
} }
inline inline uint8*
uint8* MemoryVector::getBlockPtr(const PhysAddress & paddr) MemoryVector::getBlockPtr(const PhysAddress & paddr)
{ {
uint32 page_num = paddr.getAddress() >> 12; uint32 page_num = paddr.getAddress() >> 12;
if (m_pages[page_num] == 0) { if (m_pages[page_num] == 0) {
@@ -149,4 +153,4 @@ uint8* MemoryVector::getBlockPtr(const PhysAddress & paddr)
return &m_pages[page_num][paddr.getAddress()&m_page_offset_mask]; return &m_pages[page_num][paddr.getAddress()&m_page_offset_mask];
} }
#endif // MEMORYVECTOR_H #endif // __MEM_RUBY_SYSTEM_MEMORYVECTOR_HH__

View File

@@ -1,4 +1,3 @@
/* /*
* Copyright (c) 1999-2008 Mark D. Hill and David A. Wood * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
* All rights reserved. * All rights reserved.
@@ -27,26 +26,20 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
/* #ifndef __MEM_RUBY_SYSTEM_NODEID_HH__
* NodeID.hh #define __MEM_RUBY_SYSTEM_NODEID_HH__
*
* Description:
*
* $Id: NodeID.hh,v 3.3 2003/12/04 15:01:39 xu Exp $
*
*/
#ifndef NODEID_H
#define NODEID_H
#include <string> #include <string>
#include "mem/ruby/common/Global.hh"
#include "mem/gems_common/util.hh" #include "mem/gems_common/util.hh"
#include "mem/ruby/common/Global.hh"
typedef int NodeID; typedef int NodeID;
extern inline inline std::string
std::string NodeIDToString (NodeID node) { return int_to_string(node); } NodeIDToString(NodeID node)
{
return int_to_string(node);
}
#endif //NODEID_H #endif // __MEM_RUBY_SYSTEM_NODEID_HH__

View File

@@ -1,4 +1,3 @@
/* /*
* Copyright (c) 1999-2008 Mark D. Hill and David A. Wood * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
* All rights reserved. * All rights reserved.
@@ -27,54 +26,39 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
/* #ifndef __MEM_RUBY_SYSTEM_PERFECTCACHEMEMORY_HH__
* PerfectCacheMemory.hh #define __MEM_RUBY_SYSTEM_PERFECTCACHEMEMORY_HH__
*
* Description:
*
* $Id$
*
*/
#ifndef PERFECTCACHEMEMORY_H
#define PERFECTCACHEMEMORY_H
#include "mem/ruby/common/Global.hh"
#include "mem/gems_common/Map.hh" #include "mem/gems_common/Map.hh"
#include "mem/protocol/AccessPermission.hh" #include "mem/protocol/AccessPermission.hh"
#include "mem/ruby/common/Address.hh" #include "mem/ruby/common/Address.hh"
#include "mem/ruby/common/Global.hh"
template<class ENTRY> template<class ENTRY>
class PerfectCacheLineState { struct PerfectCacheLineState
public: {
PerfectCacheLineState() { m_permission = AccessPermission_NUM; } PerfectCacheLineState() { m_permission = AccessPermission_NUM; }
AccessPermission m_permission; AccessPermission m_permission;
ENTRY m_entry; ENTRY m_entry;
}; };
template<class ENTRY> template<class ENTRY>
extern inline inline ostream&
ostream& operator<<(ostream& out, const PerfectCacheLineState<ENTRY>& obj) operator<<(ostream& out, const PerfectCacheLineState<ENTRY>& obj)
{ {
return out; return out;
} }
template<class ENTRY> template<class ENTRY>
class PerfectCacheMemory { class PerfectCacheMemory
{
public: public:
// Constructors
PerfectCacheMemory(); PerfectCacheMemory();
// Destructor
//~PerfectCacheMemory();
// Public Methods
static void printConfig(ostream& out); static void printConfig(ostream& out);
// perform a cache access and see if we hit or not. Return true on // perform a cache access and see if we hit or not. Return true
// a hit. // on a hit.
bool tryCacheAccess(const CacheMsg& msg, bool& block_stc, ENTRY*& entry); bool tryCacheAccess(const CacheMsg& msg, bool& block_stc, ENTRY*& entry);
// tests to see if an address is present in the cache // tests to see if an address is present in the cache
@@ -103,9 +87,8 @@ public:
// Print cache contents // Print cache contents
void print(ostream& out) const; void print(ostream& out) const;
private:
// Private Methods
private:
// Private copy constructor and assignment operator // Private copy constructor and assignment operator
PerfectCacheMemory(const PerfectCacheMemory& obj); PerfectCacheMemory(const PerfectCacheMemory& obj);
PerfectCacheMemory& operator=(const PerfectCacheMemory& obj); PerfectCacheMemory& operator=(const PerfectCacheMemory& obj);
@@ -114,58 +97,46 @@ private:
Map<Address, PerfectCacheLineState<ENTRY> > m_map; Map<Address, PerfectCacheLineState<ENTRY> > m_map;
}; };
// Output operator declaration
//ostream& operator<<(ostream& out, const PerfectCacheMemory<ENTRY>& obj);
// ******************* Definitions *******************
// Output operator definition
template<class ENTRY> template<class ENTRY>
extern inline inline ostream&
ostream& operator<<(ostream& out, const PerfectCacheMemory<ENTRY>& obj) operator<<(ostream& out, const PerfectCacheMemory<ENTRY>& obj)
{ {
obj.print(out); obj.print(out);
out << flush; out << flush;
return out; return out;
} }
// ****************************************************************
template<class ENTRY> template<class ENTRY>
extern inline inline
PerfectCacheMemory<ENTRY>::PerfectCacheMemory() PerfectCacheMemory<ENTRY>::PerfectCacheMemory()
{ {
} }
// STATIC METHODS
template<class ENTRY> template<class ENTRY>
extern inline inline void
void PerfectCacheMemory<ENTRY>::printConfig(ostream& out) PerfectCacheMemory<ENTRY>::printConfig(ostream& out)
{ {
} }
// PUBLIC METHODS
template<class ENTRY> template<class ENTRY>
extern inline inline bool
bool PerfectCacheMemory<ENTRY>::tryCacheAccess(const CacheMsg& msg, bool& block_stc, ENTRY*& entry) PerfectCacheMemory<ENTRY>::tryCacheAccess(const CacheMsg& msg,
bool& block_stc, ENTRY*& entry)
{ {
ERROR_MSG("not implemented"); ERROR_MSG("not implemented");
} }
// tests to see if an address is present in the cache // tests to see if an address is present in the cache
template<class ENTRY> template<class ENTRY>
extern inline inline bool
bool PerfectCacheMemory<ENTRY>::isTagPresent(const Address& address) const PerfectCacheMemory<ENTRY>::isTagPresent(const Address& address) const
{ {
return m_map.exist(line_address(address)); return m_map.exist(line_address(address));
} }
template<class ENTRY> template<class ENTRY>
extern inline inline bool
bool PerfectCacheMemory<ENTRY>::cacheAvail(const Address& address) const PerfectCacheMemory<ENTRY>::cacheAvail(const Address& address) const
{ {
return true; return true;
} }
@@ -173,8 +144,8 @@ bool PerfectCacheMemory<ENTRY>::cacheAvail(const Address& address) const
// find an Invalid or already allocated entry and sets the tag // find an Invalid or already allocated entry and sets the tag
// appropriate for the address // appropriate for the address
template<class ENTRY> template<class ENTRY>
extern inline inline void
void PerfectCacheMemory<ENTRY>::allocate(const Address& address) PerfectCacheMemory<ENTRY>::allocate(const Address& address)
{ {
PerfectCacheLineState<ENTRY> line_state; PerfectCacheLineState<ENTRY> line_state;
line_state.m_permission = AccessPermission_Busy; line_state.m_permission = AccessPermission_Busy;
@@ -184,46 +155,47 @@ void PerfectCacheMemory<ENTRY>::allocate(const Address& address)
// deallocate entry // deallocate entry
template<class ENTRY> template<class ENTRY>
extern inline inline void
void PerfectCacheMemory<ENTRY>::deallocate(const Address& address) PerfectCacheMemory<ENTRY>::deallocate(const Address& address)
{ {
m_map.erase(line_address(address)); m_map.erase(line_address(address));
} }
// Returns with the physical address of the conflicting cache line // Returns with the physical address of the conflicting cache line
template<class ENTRY> template<class ENTRY>
extern inline inline Address
Address PerfectCacheMemory<ENTRY>::cacheProbe(const Address& newAddress) const PerfectCacheMemory<ENTRY>::cacheProbe(const Address& newAddress) const
{ {
ERROR_MSG("cacheProbe called in perfect cache"); ERROR_MSG("cacheProbe called in perfect cache");
} }
// looks an address up in the cache // looks an address up in the cache
template<class ENTRY> template<class ENTRY>
extern inline inline ENTRY&
ENTRY& PerfectCacheMemory<ENTRY>::lookup(const Address& address) PerfectCacheMemory<ENTRY>::lookup(const Address& address)
{ {
return m_map.lookup(line_address(address)).m_entry; return m_map.lookup(line_address(address)).m_entry;
} }
// looks an address up in the cache // looks an address up in the cache
template<class ENTRY> template<class ENTRY>
extern inline inline const ENTRY&
const ENTRY& PerfectCacheMemory<ENTRY>::lookup(const Address& address) const PerfectCacheMemory<ENTRY>::lookup(const Address& address) const
{ {
return m_map.lookup(line_address(address)).m_entry; return m_map.lookup(line_address(address)).m_entry;
} }
template<class ENTRY> template<class ENTRY>
extern inline inline AccessPermission
AccessPermission PerfectCacheMemory<ENTRY>::getPermission(const Address& address) const PerfectCacheMemory<ENTRY>::getPermission(const Address& address) const
{ {
return m_map.lookup(line_address(address)).m_permission; return m_map.lookup(line_address(address)).m_permission;
} }
template<class ENTRY> template<class ENTRY>
extern inline inline void
void PerfectCacheMemory<ENTRY>::changePermission(const Address& address, AccessPermission new_perm) PerfectCacheMemory<ENTRY>::changePermission(const Address& address,
AccessPermission new_perm)
{ {
Address line_address = address; Address line_address = address;
line_address.makeLineAddress(); line_address.makeLineAddress();
@@ -233,9 +205,9 @@ void PerfectCacheMemory<ENTRY>::changePermission(const Address& address, AccessP
} }
template<class ENTRY> template<class ENTRY>
extern inline inline void
void PerfectCacheMemory<ENTRY>::print(ostream& out) const PerfectCacheMemory<ENTRY>::print(ostream& out) const
{ {
} }
#endif //PERFECTCACHEMEMORY_H #endif // __MEM_RUBY_SYSTEM_PERFECTCACHEMEMORY_HH__

View File

@@ -1,4 +1,3 @@
/* /*
* Copyright (c) 1999-2008 Mark D. Hill and David A. Wood * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
* All rights reserved. * All rights reserved.
@@ -27,13 +26,16 @@
* 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/ruby/system/PersistentTable.hh"
#include "mem/gems_common/util.hh" #include "mem/gems_common/util.hh"
#include "mem/ruby/system/PersistentTable.hh"
// randomize so that handoffs are not locality-aware // randomize so that handoffs are not locality-aware
// int persistent_randomize[] = {0, 4, 8, 12, 1, 5, 9, 13, 2, 6, 10, 14, 3, 7, 11, 15}; #if 0
// int persistent_randomize[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}; int persistent_randomize[] = {0, 4, 8, 12, 1, 5, 9, 13, 2, 6,
10, 14, 3, 7, 11, 15};
int persistent_randomize[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
10, 11, 12, 13, 14, 15};
#endif
PersistentTable::PersistentTable() PersistentTable::PersistentTable()
{ {
@@ -46,16 +48,18 @@ PersistentTable::~PersistentTable()
m_map_ptr = NULL; m_map_ptr = NULL;
} }
void PersistentTable::persistentRequestLock(const Address& address, void
PersistentTable::persistentRequestLock(const Address& address,
MachineID locker, MachineID locker,
AccessType type) AccessType type)
{ {
#if 0
if (locker == m_chip_ptr->getID())
cout << "Chip " << m_chip_ptr->getID() << ": " << llocker
<< " requesting lock for " << address << endl;
// if (locker == m_chip_ptr->getID() ) MachineID locker = (MachineID) persistent_randomize[llocker];
// cout << "Chip " << m_chip_ptr->getID() << ": " << llocker #endif
// << " requesting lock for " << address << endl;
// MachineID locker = (MachineID) persistent_randomize[llocker];
assert(address == line_address(address)); assert(address == line_address(address));
if (!m_map_ptr->exist(address)) { if (!m_map_ptr->exist(address)) {
@@ -82,14 +86,17 @@ void PersistentTable::persistentRequestLock(const Address& address,
} }
} }
void PersistentTable::persistentRequestUnlock(const Address& address, void
PersistentTable::persistentRequestUnlock(const Address& address,
MachineID unlocker) MachineID unlocker)
{ {
// if (unlocker == m_chip_ptr->getID() ) #if 0
// cout << "Chip " << m_chip_ptr->getID() << ": " << uunlocker if (unlocker == m_chip_ptr->getID())
// << " requesting unlock for " << address << endl; cout << "Chip " << m_chip_ptr->getID() << ": " << uunlocker
<< " requesting unlock for " << address << endl;
// MachineID unlocker = (MachineID) persistent_randomize[uunlocker]; MachineID unlocker = (MachineID) persistent_randomize[uunlocker];
#endif
assert(address == line_address(address)); assert(address == line_address(address));
assert(m_map_ptr->exist(address)); assert(m_map_ptr->exist(address));
@@ -112,26 +119,25 @@ void PersistentTable::persistentRequestUnlock(const Address& address,
} }
} }
bool PersistentTable::okToIssueStarving(const Address& address, bool
PersistentTable::okToIssueStarving(const Address& address,
MachineID machId) const MachineID machId) const
{ {
assert(address == line_address(address)); assert(address == line_address(address));
if (!m_map_ptr->exist(address)) { if (!m_map_ptr->exist(address)) {
//
// No entry present // No entry present
//
return true; return true;
} else if (m_map_ptr->lookup(address).m_starving.isElement(machId)) { } else if (m_map_ptr->lookup(address).m_starving.isElement(machId)) {
// // We can't issue another lockdown until are previous unlock
// We can't issue another lockdown until are previous unlock has occurred // has occurred
//
return false; return false;
} else { } else {
return (m_map_ptr->lookup(address).m_marked.isEmpty()); return m_map_ptr->lookup(address).m_marked.isEmpty();
} }
} }
MachineID PersistentTable::findSmallest(const Address& address) const MachineID
PersistentTable::findSmallest(const Address& address) const
{ {
assert(address == line_address(address)); assert(address == line_address(address));
assert(m_map_ptr->exist(address)); assert(m_map_ptr->exist(address));
@@ -139,66 +145,68 @@ MachineID PersistentTable::findSmallest(const Address& address) const
return entry.m_starving.smallestElement(); return entry.m_starving.smallestElement();
} }
AccessType PersistentTable::typeOfSmallest(const Address& address) const AccessType
PersistentTable::typeOfSmallest(const Address& address) const
{ {
assert(address == line_address(address)); assert(address == line_address(address));
assert(m_map_ptr->exist(address)); assert(m_map_ptr->exist(address));
const PersistentTableEntry& entry = m_map_ptr->lookup(address); const PersistentTableEntry& entry = m_map_ptr->lookup(address);
if (entry.m_request_to_write.isElement(entry.m_starving.smallestElement())) { if (entry.m_request_to_write.
isElement(entry.m_starving.smallestElement())) {
return AccessType_Write; return AccessType_Write;
} else { } else {
return AccessType_Read; return AccessType_Read;
} }
} }
void PersistentTable::markEntries(const Address& address) void
PersistentTable::markEntries(const Address& address)
{ {
assert(address == line_address(address)); assert(address == line_address(address));
if (m_map_ptr->exist(address)) { if (m_map_ptr->exist(address)) {
PersistentTableEntry& entry = m_map_ptr->lookup(address); PersistentTableEntry& entry = m_map_ptr->lookup(address);
//
// None should be marked // None should be marked
//
assert(entry.m_marked.isEmpty()); assert(entry.m_marked.isEmpty());
//
// Mark all the nodes currently in the table // Mark all the nodes currently in the table
//
entry.m_marked = entry.m_starving; entry.m_marked = entry.m_starving;
} }
} }
bool PersistentTable::isLocked(const Address& address) const bool
PersistentTable::isLocked(const Address& address) const
{ {
assert(address == line_address(address)); assert(address == line_address(address));
// If an entry is present, it must be locked // If an entry is present, it must be locked
return (m_map_ptr->exist(address)); return m_map_ptr->exist(address);
} }
int PersistentTable::countStarvingForAddress(const Address& address) const int
PersistentTable::countStarvingForAddress(const Address& address) const
{ {
if (m_map_ptr->exist(address)) { if (m_map_ptr->exist(address)) {
PersistentTableEntry& entry = m_map_ptr->lookup(address); PersistentTableEntry& entry = m_map_ptr->lookup(address);
return (entry.m_starving.count()); return (entry.m_starving.count());
} } else {
else {
return 0; return 0;
} }
} }
int PersistentTable::countReadStarvingForAddress(const Address& address) const int
PersistentTable::countReadStarvingForAddress(const Address& address) const
{ {
if (m_map_ptr->exist(address)) { if (m_map_ptr->exist(address)) {
PersistentTableEntry& entry = m_map_ptr->lookup(address); PersistentTableEntry& entry = m_map_ptr->lookup(address);
return (entry.m_starving.count() - entry.m_request_to_write.count()); return (entry.m_starving.count() - entry.m_request_to_write.count());
} } else {
else {
return 0; return 0;
} }
} }
void PersistentTable::print(ostream& out) const void
PersistentTable::print(ostream& out) const
{ {
} }

View File

@@ -1,4 +1,3 @@
/* /*
* Copyright (c) 1999-2008 Mark D. Hill and David A. Wood * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
* All rights reserved. * All rights reserved.
@@ -27,17 +26,18 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#ifndef PersistentTable_H #ifndef __MEM_RUBY_SYSTEM_PERSISTENTTABLE_HH__
#define PersistentTable_H #define __MEM_RUBY_SYSTEM_PERSISTENTTABLE_HH__
#include "mem/ruby/common/Global.hh"
#include "mem/gems_common/Map.hh" #include "mem/gems_common/Map.hh"
#include "mem/ruby/common/Address.hh"
#include "mem/ruby/system/MachineID.hh"
#include "mem/protocol/AccessType.hh" #include "mem/protocol/AccessType.hh"
#include "mem/ruby/common/Address.hh"
#include "mem/ruby/common/Global.hh"
#include "mem/ruby/common/NetDest.hh" #include "mem/ruby/common/NetDest.hh"
#include "mem/ruby/system/MachineID.hh"
class PersistentTableEntry { class PersistentTableEntry
{
public: public:
void print(ostream& out) const {} void print(ostream& out) const {}
@@ -46,7 +46,8 @@ public:
NetDest m_request_to_write; NetDest m_request_to_write;
}; };
class PersistentTable { class PersistentTable
{
public: public:
// Constructors // Constructors
PersistentTable(); PersistentTable();
@@ -55,7 +56,8 @@ public:
~PersistentTable(); ~PersistentTable();
// Public Methods // Public Methods
void persistentRequestLock(const Address& address, MachineID locker, AccessType type); void persistentRequestLock(const Address& address, MachineID locker,
AccessType type);
void persistentRequestUnlock(const Address& address, MachineID unlocker); void persistentRequestUnlock(const Address& address, MachineID unlocker);
bool okToIssueStarving(const Address& address, MachineID machID) const; bool okToIssueStarving(const Address& address, MachineID machID) const;
MachineID findSmallest(const Address& address) const; MachineID findSmallest(const Address& address) const;
@@ -68,9 +70,8 @@ public:
static void printConfig(ostream& out) {} static void printConfig(ostream& out) {}
void print(ostream& out) const; void print(ostream& out) const;
private:
// Private Methods
private:
// Private copy constructor and assignment operator // Private copy constructor and assignment operator
PersistentTable(const PersistentTable& obj); PersistentTable(const PersistentTable& obj);
PersistentTable& operator=(const PersistentTable& obj); PersistentTable& operator=(const PersistentTable& obj);
@@ -79,24 +80,20 @@ private:
Map<Address, PersistentTableEntry>* m_map_ptr; Map<Address, PersistentTableEntry>* m_map_ptr;
}; };
// ******************* Definitions ******************* inline ostream&
operator<<(ostream& out, const PersistentTable& obj)
// Output operator definition
extern inline
ostream& operator<<(ostream& out, const PersistentTable& obj)
{ {
obj.print(out); obj.print(out);
out << flush; out << flush;
return out; return out;
} }
// Output operator definition inline ostream&
extern inline operator<<(ostream& out, const PersistentTableEntry& obj)
ostream& operator<<(ostream& out, const PersistentTableEntry& obj)
{ {
obj.print(out); obj.print(out);
out << flush; out << flush;
return out; return out;
} }
#endif //PersistentTable_H #endif // __MEM_RUBY_SYSTEM_PERSISTENTTABLE_HH__

View File

@@ -26,8 +26,8 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#ifndef PSEUDOLRUPOLICY_H #ifndef __MEM_RUBY_SYSTEM_PSEUDOLRUPOLICY_HH__
#define PSEUDOLRUPOLICY_H #define __MEM_RUBY_SYSTEM_PSEUDOLRUPOLICY_HH__
#include "mem/ruby/system/AbstractReplacementPolicy.hh" #include "mem/ruby/system/AbstractReplacementPolicy.hh"
@@ -44,9 +44,9 @@
* 2 is one below the associativy, and most fair when it is one above. * 2 is one below the associativy, and most fair when it is one above.
*/ */
class PseudoLRUPolicy : public AbstractReplacementPolicy { class PseudoLRUPolicy : public AbstractReplacementPolicy
{
public: public:
PseudoLRUPolicy(Index num_sets, Index assoc); PseudoLRUPolicy(Index num_sets, Index assoc);
~PseudoLRUPolicy(); ~PseudoLRUPolicy();
@@ -56,7 +56,8 @@ class PseudoLRUPolicy : public AbstractReplacementPolicy {
private: private:
unsigned int m_effective_assoc; /** nearest (to ceiling) power of 2 */ unsigned int m_effective_assoc; /** nearest (to ceiling) power of 2 */
unsigned int m_num_levels; /** number of levels in the tree */ unsigned int m_num_levels; /** number of levels in the tree */
uint64* m_trees; /** bit representation of the trees, one for each set */ uint64* m_trees; /** bit representation of the
* trees, one for each set */
}; };
inline inline
@@ -73,7 +74,8 @@ PseudoLRUPolicy::PseudoLRUPolicy(Index num_sets, Index assoc)
m_effective_assoc = 1; m_effective_assoc = 1;
while (m_effective_assoc < assoc) { while (m_effective_assoc < assoc) {
m_effective_assoc <<= 1; // effective associativity is ceiling power of 2 // effective associativity is ceiling power of 2
m_effective_assoc <<= 1;
} }
assoc = m_effective_assoc; assoc = m_effective_assoc;
while (true) { while (true) {
@@ -84,7 +86,7 @@ PseudoLRUPolicy::PseudoLRUPolicy(Index num_sets, Index assoc)
assert(m_num_levels < sizeof(unsigned int)*4); assert(m_num_levels < sizeof(unsigned int)*4);
num_tree_nodes = (1 << m_num_levels) - 1; num_tree_nodes = (1 << m_num_levels) - 1;
m_trees = new uint64[m_num_sets]; m_trees = new uint64[m_num_sets];
for(unsigned int i=0; i< m_num_sets; i++){ for (unsigned i = 0; i < m_num_sets; i++) {
m_trees[i] = 0; m_trees[i] = 0;
} }
} }
@@ -96,8 +98,9 @@ PseudoLRUPolicy::~PseudoLRUPolicy()
delete[] m_trees; delete[] m_trees;
} }
inline inline void
void PseudoLRUPolicy::touch(Index set, Index index, Time time){ PseudoLRUPolicy::touch(Index set, Index index, Time time)
{
assert(index >= 0 && index < m_assoc); assert(index >= 0 && index < m_assoc);
assert(set >= 0 && set < m_num_sets); assert(set >= 0 && set < m_num_sets);
@@ -114,15 +117,15 @@ void PseudoLRUPolicy::touch(Index set, Index index, Time time){
m_last_ref_ptr[set][index] = time; m_last_ref_ptr[set][index] = time;
} }
inline inline Index
Index PseudoLRUPolicy::getVictim(Index set) const { PseudoLRUPolicy::getVictim(Index set) const
{
// assert(m_assoc != 0); // assert(m_assoc != 0);
Index index = 0; Index index = 0;
int tree_index = 0; int tree_index = 0;
int node_val; int node_val;
for(unsigned int i=0;i<m_num_levels;i++){ for (unsigned i = 0; i < m_num_levels; i++){
node_val = (m_trees[set] >> tree_index) & 1; node_val = (m_trees[set] >> tree_index) & 1;
index += node_val ? 0 : (m_effective_assoc >> (i + 1)); index += node_val ? 0 : (m_effective_assoc >> (i + 1));
tree_index = node_val ? (tree_index * 2) + 1 : (tree_index * 2) + 2; tree_index = node_val ? (tree_index * 2) + 1 : (tree_index * 2) + 2;
@@ -134,4 +137,4 @@ Index PseudoLRUPolicy::getVictim(Index set) const {
return (index > (m_assoc - 1)) ? m_assoc - 1 : index; return (index > (m_assoc - 1)) ? m_assoc - 1 : index;
} }
#endif // PSEUDOLRUPOLICY_H #endif // __MEM_RUBY_SYSTEM_PSEUDOLRUPOLICY_HH__

View File

@@ -1,4 +1,3 @@
/* /*
* Copyright (c) 2009 Advanced Micro Devices, Inc. * Copyright (c) 2009 Advanced Micro Devices, Inc.
* All rights reserved. * All rights reserved.
@@ -27,10 +26,10 @@
* 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/physical.hh"
#include "mem/ruby/system/RubyPort.hh"
#include "mem/ruby/slicc_interface/AbstractController.hh"
#include "cpu/rubytest/RubyTester.hh" #include "cpu/rubytest/RubyTester.hh"
#include "mem/physical.hh"
#include "mem/ruby/slicc_interface/AbstractController.hh"
#include "mem/ruby/system/RubyPort.hh"
RubyPort::RubyPort(const Params *p) RubyPort::RubyPort(const Params *p)
: MemObject(p) : MemObject(p)
@@ -48,7 +47,8 @@ RubyPort::RubyPort(const Params *p)
physMemPort = NULL; physMemPort = NULL;
} }
void RubyPort::init() void
RubyPort::init()
{ {
assert(m_controller != NULL); assert(m_controller != NULL);
m_mandatory_q_ptr = m_controller->getMandatoryQueue(); m_mandatory_q_ptr = m_controller->getMandatoryQueue();
@@ -59,34 +59,34 @@ RubyPort::getPort(const std::string &if_name, int idx)
{ {
if (if_name == "port") { if (if_name == "port") {
return new M5Port(csprintf("%s-port%d", name(), idx), this); return new M5Port(csprintf("%s-port%d", name(), idx), this);
} else if (if_name == "pio_port") { }
//
if (if_name == "pio_port") {
// ensure there is only one pio port // ensure there is only one pio port
//
assert(pio_port == NULL); assert(pio_port == NULL);
pio_port = new PioPort(csprintf("%s-pio-port%d", name(), idx), pio_port = new PioPort(csprintf("%s-pio-port%d", name(), idx), this);
this);
return pio_port; return pio_port;
} else if (if_name == "physMemPort") { }
//
if (if_name == "physMemPort") {
// RubyPort should only have one port to physical memory // RubyPort should only have one port to physical memory
//
assert (physMemPort == NULL); assert (physMemPort == NULL);
physMemPort = new M5Port(csprintf("%s-physMemPort", name()), physMemPort = new M5Port(csprintf("%s-physMemPort", name()), this);
this);
return physMemPort; return physMemPort;
} else if (if_name == "functional") { }
//
// Calls for the functional port only want to access functional memory. if (if_name == "functional") {
// Therefore, directly pass these calls ports to physmem. // Calls for the functional port only want to access
// // functional memory. Therefore, directly pass these calls
// ports to physmem.
assert(physmem != NULL); assert(physmem != NULL);
return physmem->getPort(if_name, idx); return physmem->getPort(if_name, idx);
} }
return NULL; return NULL;
} }
@@ -113,7 +113,6 @@ RubyPort::PioPort::recvAtomic(PacketPtr pkt)
return 0; return 0;
} }
Tick Tick
RubyPort::M5Port::recvAtomic(PacketPtr pkt) RubyPort::M5Port::recvAtomic(PacketPtr pkt)
{ {
@@ -125,19 +124,13 @@ RubyPort::M5Port::recvAtomic(PacketPtr pkt)
bool bool
RubyPort::PioPort::recvTiming(PacketPtr pkt) RubyPort::PioPort::recvTiming(PacketPtr pkt)
{ {
// // In FS mode, ruby memory will receive pio responses from devices
// In FS mode, ruby memory will receive pio responses from devices and // and it must forward these responses back to the particular CPU.
// it must forward these responses back to the particular CPU. DPRINTF(MemoryAccess, "Pio response for address %#x\n", pkt->getAddr());
//
DPRINTF(MemoryAccess,
"Pio response for address %#x\n",
pkt->getAddr());
assert(pkt->isResponse()); assert(pkt->isResponse());
//
// First we must retrieve the request port from the sender State // First we must retrieve the request port from the sender State
//
RubyPort::SenderState *senderState = RubyPort::SenderState *senderState =
safe_cast<RubyPort::SenderState *>(pkt->senderState); safe_cast<RubyPort::SenderState *>(pkt->senderState);
M5Port *port = senderState->port; M5Port *port = senderState->port;
@@ -156,17 +149,14 @@ bool
RubyPort::M5Port::recvTiming(PacketPtr pkt) RubyPort::M5Port::recvTiming(PacketPtr pkt)
{ {
DPRINTF(MemoryAccess, DPRINTF(MemoryAccess,
"Timing access caught for address %#x\n", "Timing access caught for address %#x\n", pkt->getAddr());
pkt->getAddr());
//dsm: based on SimpleTimingPort::recvTiming(pkt); //dsm: based on SimpleTimingPort::recvTiming(pkt);
//
// The received packets should only be M5 requests, which should never // The received packets should only be M5 requests, which should never
// get nacked. There used to be code to hanldle nacks here, but // get nacked. There used to be code to hanldle nacks here, but
// I'm pretty sure it didn't work correctly with the drain code, // I'm pretty sure it didn't work correctly with the drain code,
// so that would need to be fixed if we ever added it back. // so that would need to be fixed if we ever added it back.
//
assert(pkt->isRequest()); assert(pkt->isRequest());
if (pkt->memInhibitAsserted()) { if (pkt->memInhibitAsserted()) {
@@ -177,16 +167,12 @@ RubyPort::M5Port::recvTiming(PacketPtr pkt)
return true; return true;
} }
//
// Save the port in the sender state object to be used later to // Save the port in the sender state object to be used later to
// route the response // route the response
//
pkt->senderState = new SenderState(this, pkt->senderState); pkt->senderState = new SenderState(this, pkt->senderState);
//
// Check for pio requests and directly send them to the dedicated // Check for pio requests and directly send them to the dedicated
// pio port. // pio port.
//
if (!isPhysMemAddress(pkt->getAddr())) { if (!isPhysMemAddress(pkt->getAddr())) {
assert(ruby_port->pio_port != NULL); assert(ruby_port->pio_port != NULL);
DPRINTF(MemoryAccess, DPRINTF(MemoryAccess,
@@ -196,15 +182,11 @@ RubyPort::M5Port::recvTiming(PacketPtr pkt)
return ruby_port->pio_port->sendTiming(pkt); return ruby_port->pio_port->sendTiming(pkt);
} }
//
// For DMA and CPU requests, translate them to ruby requests before // For DMA and CPU requests, translate them to ruby requests before
// sending them to our assigned ruby port. // sending them to our assigned ruby port.
//
RubyRequestType type = RubyRequestType_NULL; RubyRequestType type = RubyRequestType_NULL;
//
// If valid, copy the pc to the ruby request // If valid, copy the pc to the ruby request
//
Addr pc = 0; Addr pc = 0;
if (pkt->req->hasPC()) { if (pkt->req->hasPC()) {
pc = pkt->req->getPC(); pc = pkt->req->getPC();
@@ -229,42 +211,33 @@ RubyPort::M5Port::recvTiming(PacketPtr pkt)
} else if (pkt->isWrite()) { } else if (pkt->isWrite()) {
type = RubyRequestType_ST; type = RubyRequestType_ST;
} else if (pkt->isReadWrite()) { } else if (pkt->isReadWrite()) {
// // Fix me. This conditional will never be executed
// Fix me. This conditional will never be executed because // because isReadWrite() is just an OR of isRead() and
// isReadWrite() is just an OR of isRead() and isWrite(). // isWrite(). Furthermore, just because the packet is a
// Furthermore, just because the packet is a read/write request does // read/write request does not necessary mean it is a
// not necessary mean it is a read-modify-write atomic operation. // read-modify-write atomic operation.
//
type = RubyRequestType_RMW_Write; type = RubyRequestType_RMW_Write;
} else { } else {
panic("Unsupported ruby packet type\n"); panic("Unsupported ruby packet type\n");
} }
} }
RubyRequest ruby_request(pkt->getAddr(), RubyRequest ruby_request(pkt->getAddr(), pkt->getPtr<uint8_t>(),
pkt->getPtr<uint8_t>(), pkt->getSize(), pc, type,
pkt->getSize(), RubyAccessMode_Supervisor, pkt);
pc,
type,
RubyAccessMode_Supervisor,
pkt);
// Submit the ruby request // Submit the ruby request
RequestStatus requestStatus = ruby_port->makeRequest(ruby_request); RequestStatus requestStatus = ruby_port->makeRequest(ruby_request);
//
// If the request successfully issued or the SC request completed because // If the request successfully issued or the SC request completed because
// exclusive permission was lost, then we should return true. // exclusive permission was lost, then we should return true.
// Otherwise, we need to delete the senderStatus we just created and return // Otherwise, we need to delete the senderStatus we just created and return
// false. // false.
//
if ((requestStatus == RequestStatus_Issued) || if ((requestStatus == RequestStatus_Issued) ||
(requestStatus == RequestStatus_LlscFailed)) { (requestStatus == RequestStatus_LlscFailed)) {
//
// The communicate to M5 whether the SC command succeeded by seting the // The communicate to M5 whether the SC command succeeded by seting the
// packet's extra data. // packet's extra data.
//
if (pkt->isLLSC() && pkt->isWrite()) { if (pkt->isLLSC() && pkt->isWrite()) {
if (requestStatus == RequestStatus_LlscFailed) { if (requestStatus == RequestStatus_LlscFailed) {
DPRINTF(MemoryAccess, "SC failed and request completed\n"); DPRINTF(MemoryAccess, "SC failed and request completed\n");
@@ -278,8 +251,7 @@ RubyPort::M5Port::recvTiming(PacketPtr pkt)
DPRINTF(MemoryAccess, DPRINTF(MemoryAccess,
"Request for address #x did not issue because %s\n", "Request for address #x did not issue because %s\n",
pkt->getAddr(), pkt->getAddr(), RequestStatus_to_string(requestStatus));
RequestStatus_to_string(requestStatus));
SenderState* senderState = safe_cast<SenderState*>(pkt->senderState); SenderState* senderState = safe_cast<SenderState*>(pkt->senderState);
pkt->senderState = senderState->saved; pkt->senderState = senderState->saved;
@@ -290,9 +262,7 @@ RubyPort::M5Port::recvTiming(PacketPtr pkt)
void void
RubyPort::ruby_hit_callback(PacketPtr pkt) RubyPort::ruby_hit_callback(PacketPtr pkt)
{ {
//
// Retrieve the request port from the sender State // Retrieve the request port from the sender State
//
RubyPort::SenderState *senderState = RubyPort::SenderState *senderState =
safe_cast<RubyPort::SenderState *>(pkt->senderState); safe_cast<RubyPort::SenderState *>(pkt->senderState);
M5Port *port = senderState->port; M5Port *port = senderState->port;
@@ -308,11 +278,9 @@ RubyPort::ruby_hit_callback(PacketPtr pkt)
void void
RubyPort::M5Port::hitCallback(PacketPtr pkt) RubyPort::M5Port::hitCallback(PacketPtr pkt)
{ {
bool needsResponse = pkt->needsResponse(); bool needsResponse = pkt->needsResponse();
DPRINTF(MemoryAccess, "Hit callback needs response %d\n", DPRINTF(MemoryAccess, "Hit callback needs response %d\n", needsResponse);
needsResponse);
ruby_port->physMemPort->sendAtomic(pkt); ruby_port->physMemPort->sendAtomic(pkt);

View File

@@ -1,4 +1,3 @@
/* /*
* Copyright (c) 2009 Advanced Micro Devices, Inc. * Copyright (c) 2009 Advanced Micro Devices, Inc.
* All rights reserved. * All rights reserved.
@@ -27,18 +26,17 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#ifndef RUBYPORT_H #ifndef __MEM_RUBY_SYSTEM_RUBYPORT_HH__
#define RUBYPORT_H #define __MEM_RUBY_SYSTEM_RUBYPORT_HH__
#include "mem/ruby/libruby.hh" #include <cassert>
#include <string> #include <string>
#include <assert.h>
#include "mem/mem_object.hh" #include "mem/mem_object.hh"
#include "mem/tport.hh"
#include "mem/physical.hh" #include "mem/physical.hh"
#include "mem/protocol/RequestStatus.hh" #include "mem/protocol/RequestStatus.hh"
#include "mem/ruby/libruby.hh"
#include "mem/tport.hh"
#include "params/RubyPort.hh" #include "params/RubyPort.hh"
using namespace std; using namespace std;
@@ -46,17 +44,16 @@ using namespace std;
class MessageBuffer; class MessageBuffer;
class AbstractController; class AbstractController;
class RubyPort : public MemObject { class RubyPort : public MemObject
{
public: public:
class M5Port : public SimpleTimingPort class M5Port : public SimpleTimingPort
{ {
private:
RubyPort *ruby_port; RubyPort *ruby_port;
public: public:
M5Port(const std::string &_name, M5Port(const std::string &_name, RubyPort *_port);
RubyPort *_port);
bool sendTiming(PacketPtr pkt); bool sendTiming(PacketPtr pkt);
void hitCallback(PacketPtr pkt); void hitCallback(PacketPtr pkt);
@@ -72,12 +69,11 @@ public:
class PioPort : public SimpleTimingPort class PioPort : public SimpleTimingPort
{ {
private:
RubyPort *ruby_port; RubyPort *ruby_port;
public: public:
PioPort(const std::string &_name, PioPort(const std::string &_name, RubyPort *_port);
RubyPort *_port);
bool sendTiming(PacketPtr pkt); bool sendTiming(PacketPtr pkt);
protected: protected:
@@ -92,8 +88,7 @@ public:
M5Port* port; M5Port* port;
Packet::SenderState *saved; Packet::SenderState *saved;
SenderState(M5Port* _port, SenderState(M5Port* _port, Packet::SenderState *sender_state = NULL)
Packet::SenderState *sender_state = NULL)
: port(_port), saved(sender_state) : port(_port), saved(sender_state)
{} {}
}; };
@@ -133,4 +128,4 @@ private:
PhysicalMemory* physmem; PhysicalMemory* physmem;
}; };
#endif #endif // __MEM_RUBY_SYSTEM_RUBYPORT_HH__

View File

@@ -1,4 +1,3 @@
/* /*
* Copyright (c) 1999-2008 Mark D. Hill and David A. Wood * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
* All rights reserved. * All rights reserved.
@@ -27,22 +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 "mem/ruby/libruby.hh" #include "cpu/rubytest/RubyTester.hh"
#include "mem/gems_common/Map.hh"
#include "mem/protocol/CacheMsg.hh"
#include "mem/protocol/Protocol.hh"
#include "mem/protocol/Protocol.hh"
#include "mem/ruby/buffers/MessageBuffer.hh"
#include "mem/ruby/common/Global.hh" #include "mem/ruby/common/Global.hh"
#include "mem/ruby/common/SubBlock.hh"
#include "mem/ruby/libruby.hh"
#include "mem/ruby/profiler/Profiler.hh"
#include "mem/ruby/recorder/Tracer.hh"
#include "mem/ruby/slicc_interface/AbstractController.hh"
#include "mem/ruby/system/CacheMemory.hh"
#include "mem/ruby/system/Sequencer.hh" #include "mem/ruby/system/Sequencer.hh"
#include "mem/ruby/system/System.hh" #include "mem/ruby/system/System.hh"
#include "mem/protocol/Protocol.hh"
#include "mem/ruby/profiler/Profiler.hh"
#include "mem/ruby/system/CacheMemory.hh"
#include "mem/protocol/CacheMsg.hh"
#include "mem/ruby/recorder/Tracer.hh"
#include "mem/ruby/common/SubBlock.hh"
#include "mem/protocol/Protocol.hh"
#include "mem/gems_common/Map.hh"
#include "mem/ruby/buffers/MessageBuffer.hh"
#include "mem/ruby/slicc_interface/AbstractController.hh"
#include "cpu/rubytest/RubyTester.hh"
#include "params/RubySequencer.hh" #include "params/RubySequencer.hh"
Sequencer * Sequencer *
@@ -78,11 +76,13 @@ Sequencer::Sequencer(const Params *p)
assert(m_dataCache_ptr != NULL); assert(m_dataCache_ptr != NULL);
} }
Sequencer::~Sequencer() { Sequencer::~Sequencer()
{
} }
void Sequencer::wakeup() { void
Sequencer::wakeup()
{
// Check for deadlock of any of the requests // Check for deadlock of any of the requests
Time current_time = g_eventQueue_ptr->getTime(); Time current_time = g_eventQueue_ptr->getTime();
@@ -119,26 +119,38 @@ void Sequencer::wakeup() {
ERROR_MSG("Aborting"); ERROR_MSG("Aborting");
} }
} }
total_outstanding += m_writeRequestTable.size() + m_readRequestTable.size();
total_outstanding += m_writeRequestTable.size();
total_outstanding += m_readRequestTable.size();
assert(m_outstanding_count == total_outstanding); assert(m_outstanding_count == total_outstanding);
if (m_outstanding_count > 0) { // If there are still outstanding requests, keep checking if (m_outstanding_count > 0) {
// If there are still outstanding requests, keep checking
schedule(deadlockCheckEvent, schedule(deadlockCheckEvent,
(m_deadlock_threshold * g_eventQueue_ptr->getClock()) + curTick); m_deadlock_threshold * g_eventQueue_ptr->getClock() +
curTick);
} }
} }
void Sequencer::printStats(ostream & out) const { void
out << "Sequencer: " << m_name << endl; Sequencer::printStats(ostream & out) const
out << " store_waiting_on_load_cycles: " << m_store_waiting_on_load_cycles << endl; {
out << " store_waiting_on_store_cycles: " << m_store_waiting_on_store_cycles << endl; out << "Sequencer: " << m_name << endl
out << " load_waiting_on_load_cycles: " << m_load_waiting_on_load_cycles << endl; << " store_waiting_on_load_cycles: "
out << " load_waiting_on_store_cycles: " << m_load_waiting_on_store_cycles << endl; << m_store_waiting_on_load_cycles << endl
<< " store_waiting_on_store_cycles: "
<< m_store_waiting_on_store_cycles << endl
<< " load_waiting_on_load_cycles: "
<< m_load_waiting_on_load_cycles << endl
<< " load_waiting_on_store_cycles: "
<< m_load_waiting_on_store_cycles << endl;
} }
void Sequencer::printProgress(ostream& out) const{ void
/* Sequencer::printProgress(ostream& out) const
{
#if 0
int total_demand = 0; int total_demand = 0;
out << "Sequencer Stats Version " << m_version << endl; out << "Sequencer Stats Version " << m_version << endl;
out << "Current time = " << g_eventQueue_ptr->getTime() << endl; out << "Current time = " << g_eventQueue_ptr->getTime() << endl;
@@ -148,20 +160,28 @@ void Sequencer::printProgress(ostream& out) const{
Vector<Address> rkeys = m_readRequestTable.keys(); Vector<Address> rkeys = m_readRequestTable.keys();
int read_size = rkeys.size(); int read_size = rkeys.size();
out << "proc " << m_version << " Read Requests = " << read_size << endl; out << "proc " << m_version << " Read Requests = " << read_size << endl;
// print the request table // print the request table
for (int i = 0; i < read_size; ++i) { for (int i = 0; i < read_size; ++i) {
SequencerRequest *request = m_readRequestTable.lookup(rkeys[i]); SequencerRequest *request = m_readRequestTable.lookup(rkeys[i]);
out << "\tRequest[ " << i << " ] = " << request->type << " Address " << rkeys[i] << " Posted " << request->issue_time << " PF " << PrefetchBit_No << endl; out << "\tRequest[ " << i << " ] = " << request->type
<< " Address " << rkeys[i]
<< " Posted " << request->issue_time
<< " PF " << PrefetchBit_No << endl;
total_demand++; total_demand++;
} }
Vector<Address> wkeys = m_writeRequestTable.keys(); Vector<Address> wkeys = m_writeRequestTable.keys();
int write_size = wkeys.size(); int write_size = wkeys.size();
out << "proc " << m_version << " Write Requests = " << write_size << endl; out << "proc " << m_version << " Write Requests = " << write_size << endl;
// print the request table // print the request table
for (int i = 0; i < write_size; ++i){ for (int i = 0; i < write_size; ++i){
CacheMsg &request = m_writeRequestTable.lookup(wkeys[i]); CacheMsg &request = m_writeRequestTable.lookup(wkeys[i]);
out << "\tRequest[ " << i << " ] = " << request.getType() << " Address " << wkeys[i] << " Posted " << request.getTime() << " PF " << request.getPrefetch() << endl; out << "\tRequest[ " << i << " ] = " << request.getType()
<< " Address " << wkeys[i]
<< " Posted " << request.getTime()
<< " PF " << request.getPrefetch() << endl;
if (request.getPrefetch() == PrefetchBit_No) { if (request.getPrefetch() == PrefetchBit_No) {
total_demand++; total_demand++;
} }
@@ -169,26 +189,30 @@ void Sequencer::printProgress(ostream& out) const{
out << endl; out << endl;
out << "Total Number Outstanding: " << m_outstanding_count << endl; out << "Total Number Outstanding: " << m_outstanding_count << endl
out << "Total Number Demand : " << total_demand << endl; << "Total Number Demand : " << total_demand << endl
out << "Total Number Prefetches : " << m_outstanding_count - total_demand << endl; << "Total Number Prefetches : " << m_outstanding_count - total_demand
out << endl; << endl << endl << endl;
out << endl; #endif
*/
} }
void Sequencer::printConfig(ostream& out) const { void
out << "Seqeuncer config: " << m_name << endl; Sequencer::printConfig(ostream& out) const
out << " controller: " << m_controller->getName() << endl; {
out << " version: " << m_version << endl; out << "Seqeuncer config: " << m_name << endl
out << " max_outstanding_requests: " << m_max_outstanding_requests << endl; << " controller: " << m_controller->getName() << endl
out << " deadlock_threshold: " << m_deadlock_threshold << endl; << " version: " << m_version << endl
<< " max_outstanding_requests: " << m_max_outstanding_requests << endl
<< " deadlock_threshold: " << m_deadlock_threshold << endl;
} }
// Insert the request on the correct request table. Return true if // Insert the request on the correct request table. Return true if
// the entry was already present. // the entry was already present.
bool Sequencer::insertRequest(SequencerRequest* request) { bool
int total_outstanding = m_writeRequestTable.size() + m_readRequestTable.size(); Sequencer::insertRequest(SequencerRequest* request)
{
int total_outstanding =
m_writeRequestTable.size() + m_readRequestTable.size();
assert(m_outstanding_count == total_outstanding); assert(m_outstanding_count == total_outstanding);
@@ -207,7 +231,9 @@ bool Sequencer::insertRequest(SequencerRequest* request) {
if (m_writeRequestTable.exist(line_addr)) { if (m_writeRequestTable.exist(line_addr)) {
m_writeRequestTable.lookup(line_addr) = request; m_writeRequestTable.lookup(line_addr) = request;
// return true; // return true;
assert(0); // drh5: isn't this an error? do you lose the initial request?
// drh5: isn't this an error? do you lose the initial request?
assert(0);
} }
m_writeRequestTable.allocate(line_addr); m_writeRequestTable.allocate(line_addr);
m_writeRequestTable.lookup(line_addr) = request; m_writeRequestTable.lookup(line_addr) = request;
@@ -216,7 +242,9 @@ bool Sequencer::insertRequest(SequencerRequest* request) {
if (m_readRequestTable.exist(line_addr)) { if (m_readRequestTable.exist(line_addr)) {
m_readRequestTable.lookup(line_addr) = request; m_readRequestTable.lookup(line_addr) = request;
// return true; // return true;
assert(0); // drh5: isn't this an error? do you lose the initial request?
// drh5: isn't this an error? do you lose the initial request?
assert(0);
} }
m_readRequestTable.allocate(line_addr); m_readRequestTable.allocate(line_addr);
m_readRequestTable.lookup(line_addr) = request; m_readRequestTable.lookup(line_addr) = request;
@@ -231,9 +259,11 @@ bool Sequencer::insertRequest(SequencerRequest* request) {
return false; return false;
} }
void Sequencer::removeRequest(SequencerRequest* srequest) { void
Sequencer::removeRequest(SequencerRequest* srequest)
assert(m_outstanding_count == m_writeRequestTable.size() + m_readRequestTable.size()); {
assert(m_outstanding_count ==
m_writeRequestTable.size() + m_readRequestTable.size());
const RubyRequest & ruby_request = srequest->ruby_request; const RubyRequest & ruby_request = srequest->ruby_request;
Address line_addr(ruby_request.paddr); Address line_addr(ruby_request.paddr);
@@ -252,8 +282,9 @@ void Sequencer::removeRequest(SequencerRequest* srequest) {
assert(m_outstanding_count == m_writeRequestTable.size() + m_readRequestTable.size()); assert(m_outstanding_count == m_writeRequestTable.size() + m_readRequestTable.size());
} }
void Sequencer::writeCallback(const Address& address, DataBlock& data) { void
Sequencer::writeCallback(const Address& address, DataBlock& data)
{
assert(address == line_address(address)); assert(address == line_address(address));
assert(m_writeRequestTable.exist(line_address(address))); assert(m_writeRequestTable.exist(line_address(address)));
@@ -269,19 +300,18 @@ void Sequencer::writeCallback(const Address& address, DataBlock& data) {
if (request->ruby_request.type == RubyRequestType_Locked_Read) { if (request->ruby_request.type == RubyRequestType_Locked_Read) {
m_dataCache_ptr->setLocked(address, m_version); m_dataCache_ptr->setLocked(address, m_version);
} } else if (request->ruby_request.type == RubyRequestType_RMW_Read) {
else if (request->ruby_request.type == RubyRequestType_RMW_Read) {
m_controller->blockOnQueue(address, m_mandatory_q_ptr); m_controller->blockOnQueue(address, m_mandatory_q_ptr);
} } else if (request->ruby_request.type == RubyRequestType_RMW_Write) {
else if (request->ruby_request.type == RubyRequestType_RMW_Write) {
m_controller->unblock(address); m_controller->unblock(address);
} }
hitCallback(request, data); hitCallback(request, data);
} }
void Sequencer::readCallback(const Address& address, DataBlock& data) { void
Sequencer::readCallback(const Address& address, DataBlock& data)
{
assert(address == line_address(address)); assert(address == line_address(address));
assert(m_readRequestTable.exist(line_address(address))); assert(m_readRequestTable.exist(line_address(address)));
@@ -295,7 +325,9 @@ void Sequencer::readCallback(const Address& address, DataBlock& data) {
hitCallback(request, data); hitCallback(request, data);
} }
void Sequencer::hitCallback(SequencerRequest* srequest, DataBlock& data) { void
Sequencer::hitCallback(SequencerRequest* srequest, DataBlock& data)
{
const RubyRequest & ruby_request = srequest->ruby_request; const RubyRequest & ruby_request = srequest->ruby_request;
Address request_address(ruby_request.paddr); Address request_address(ruby_request.paddr);
Address request_line_address(ruby_request.paddr); Address request_line_address(ruby_request.paddr);
@@ -320,15 +352,17 @@ void Sequencer::hitCallback(SequencerRequest* srequest, DataBlock& data) {
g_system_ptr->getProfiler()->missLatency(miss_latency, type); g_system_ptr->getProfiler()->missLatency(miss_latency, type);
if (Debug::getProtocolTrace()) { if (Debug::getProtocolTrace()) {
g_system_ptr->getProfiler()->profileTransition("Seq", m_version, Address(ruby_request.paddr), g_system_ptr->getProfiler()->
"", "Done", "", int_to_string(miss_latency)+" cycles"); profileTransition("Seq", m_version,
Address(ruby_request.paddr), "", "Done", "",
csprintf("%d cycles", miss_latency));
} }
} }
/* #if 0
if (request.getPrefetch() == PrefetchBit_Yes) { if (request.getPrefetch() == PrefetchBit_Yes) {
return; // Ignore the prefetch return; // Ignore the prefetch
} }
*/ #endif
// update the data // update the data
if (ruby_request.data != NULL) { if (ruby_request.data != NULL) {
@@ -340,13 +374,9 @@ void Sequencer::hitCallback(SequencerRequest* srequest, DataBlock& data) {
memcpy(ruby_request.data, memcpy(ruby_request.data,
data.getData(request_address.getOffset(), ruby_request.len), data.getData(request_address.getOffset(), ruby_request.len),
ruby_request.len); ruby_request.len);
} else { } else {
data.setData(ruby_request.data, request_address.getOffset(),
data.setData(ruby_request.data,
request_address.getOffset(),
ruby_request.len); ruby_request.len);
} }
} else { } else {
DPRINTF(MemoryAccess, DPRINTF(MemoryAccess,
@@ -354,15 +384,16 @@ void Sequencer::hitCallback(SequencerRequest* srequest, DataBlock& data) {
RubyRequestType_to_string(type)); RubyRequestType_to_string(type));
} }
// // If using the RubyTester, update the RubyTester sender state's
// If using the RubyTester, update the RubyTester sender state's subBlock // subBlock with the recieved data. The tester will later access
// with the recieved data. The tester will later access this state. // this state.
// Note: RubyPort will access it's sender state before the RubyTester. // Note: RubyPort will access it's sender state before the
// // RubyTester.
if (m_usingRubyTester) { if (m_usingRubyTester) {
RubyTester::SenderState* testerSenderState; RubyPort::SenderState *requestSenderState =
testerSenderState = safe_cast<RubyTester::SenderState*>( \ safe_cast<RubyPort::SenderState*>(ruby_request.pkt->senderState);
safe_cast<RubyPort::SenderState*>(ruby_request.pkt->senderState)->saved); RubyTester::SenderState* testerSenderState =
safe_cast<RubyTester::SenderState*>(requestSenderState->saved);
testerSenderState->subBlock->mergeFrom(data); testerSenderState->subBlock->mergeFrom(data);
} }
@@ -371,9 +402,13 @@ void Sequencer::hitCallback(SequencerRequest* srequest, DataBlock& data) {
} }
// Returns true if the sequencer already has a load or store outstanding // Returns true if the sequencer already has a load or store outstanding
RequestStatus Sequencer::getRequestStatus(const RubyRequest& request) { RequestStatus
bool is_outstanding_store = m_writeRequestTable.exist(line_address(Address(request.paddr))); Sequencer::getRequestStatus(const RubyRequest& request)
bool is_outstanding_load = m_readRequestTable.exist(line_address(Address(request.paddr))); {
bool is_outstanding_store =
m_writeRequestTable.exist(line_address(Address(request.paddr)));
bool is_outstanding_load =
m_readRequestTable.exist(line_address(Address(request.paddr)));
if (is_outstanding_store) { if (is_outstanding_store) {
if ((request.type == RubyRequestType_LD) || if ((request.type == RubyRequestType_LD) ||
(request.type == RubyRequestType_IFETCH) || (request.type == RubyRequestType_IFETCH) ||
@@ -400,45 +435,48 @@ RequestStatus Sequencer::getRequestStatus(const RubyRequest& request) {
return RequestStatus_Ready; return RequestStatus_Ready;
} }
bool Sequencer::empty() const { bool
return (m_writeRequestTable.size() == 0) && (m_readRequestTable.size() == 0); Sequencer::empty() const
{
return m_writeRequestTable.size() == 0 && m_readRequestTable.size() == 0;
} }
RequestStatus
RequestStatus Sequencer::makeRequest(const RubyRequest & request) Sequencer::makeRequest(const RubyRequest &request)
{ {
assert(Address(request.paddr).getOffset() + request.len <= assert(Address(request.paddr).getOffset() + request.len <=
RubySystem::getBlockSizeBytes()); RubySystem::getBlockSizeBytes());
RequestStatus status = getRequestStatus(request); RequestStatus status = getRequestStatus(request);
if (status == RequestStatus_Ready) { if (status != RequestStatus_Ready)
SequencerRequest *srequest = new SequencerRequest(request, return status;
g_eventQueue_ptr->getTime());
SequencerRequest *srequest =
new SequencerRequest(request, g_eventQueue_ptr->getTime());
bool found = insertRequest(srequest); bool found = insertRequest(srequest);
if (!found) { if (found) {
panic("Sequencer::makeRequest should never be called if the "
"request is already outstanding\n");
return RequestStatus_NULL;
}
if (request.type == RubyRequestType_Locked_Write) { if (request.type == RubyRequestType_Locked_Write) {
// // NOTE: it is OK to check the locked flag here as the
// NOTE: it is OK to check the locked flag here as the mandatory queue // mandatory queue will be checked first ensuring that nothing
// will be checked first ensuring that nothing comes between checking // comes between checking the flag and servicing the store.
// the flag and servicing the store.
// Address line_addr = line_address(Address(request.paddr));
if (!m_dataCache_ptr->isLocked(line_address(Address(request.paddr)), if (!m_dataCache_ptr->isLocked(line_addr, m_version)) {
m_version)) {
removeRequest(srequest); removeRequest(srequest);
if (Debug::getProtocolTrace()) { if (Debug::getProtocolTrace()) {
g_system_ptr->getProfiler()->
g_system_ptr->getProfiler()->profileTransition("Seq", profileTransition("Seq", m_version,
m_version,
Address(request.paddr), Address(request.paddr),
"", "", "SC Fail", "",
"SC Fail",
"",
RubyRequestType_to_string(request.type)); RubyRequestType_to_string(request.type));
} }
return RequestStatus_LlscFailed; return RequestStatus_LlscFailed;
} } else {
else { m_dataCache_ptr->clearLocked(line_addr);
m_dataCache_ptr->clearLocked(line_address(Address(request.paddr)));
} }
} }
issueRequest(request); issueRequest(request);
@@ -446,19 +484,13 @@ RequestStatus Sequencer::makeRequest(const RubyRequest & request)
// TODO: issue hardware prefetches here // TODO: issue hardware prefetches here
return RequestStatus_Issued; return RequestStatus_Issued;
} }
else {
panic("Sequencer::makeRequest should never be called if the request"\
"is already outstanding\n");
return RequestStatus_NULL;
}
} else {
return status;
}
}
void Sequencer::issueRequest(const RubyRequest& request) { void
Sequencer::issueRequest(const RubyRequest& request)
// TODO: get rid of CacheMsg, CacheRequestType, and AccessModeTYpe, & have SLICC use RubyRequest and subtypes natively {
// TODO: get rid of CacheMsg, CacheRequestType, and
// AccessModeTYpe, & have SLICC use RubyRequest and subtypes
// natively
CacheRequestType ctype; CacheRequestType ctype;
switch(request.type) { switch(request.type) {
case RubyRequestType_IFETCH: case RubyRequestType_IFETCH:
@@ -483,6 +515,7 @@ void Sequencer::issueRequest(const RubyRequest& request) {
default: default:
assert(0); assert(0);
} }
AccessModeType amtype; AccessModeType amtype;
switch(request.access_mode){ switch(request.access_mode){
case RubyAccessMode_User: case RubyAccessMode_User:
@@ -497,17 +530,23 @@ void Sequencer::issueRequest(const RubyRequest& request) {
default: default:
assert(0); assert(0);
} }
Address line_addr(request.paddr); Address line_addr(request.paddr);
line_addr.makeLineAddress(); line_addr.makeLineAddress();
CacheMsg msg(line_addr, Address(request.paddr), ctype, Address(request.pc), amtype, request.len, PrefetchBit_No, request.proc_id); CacheMsg msg(line_addr, Address(request.paddr), ctype,
Address(request.pc), amtype, request.len, PrefetchBit_No,
request.proc_id);
if (Debug::getProtocolTrace()) { if (Debug::getProtocolTrace()) {
g_system_ptr->getProfiler()->profileTransition("Seq", m_version, Address(request.paddr), g_system_ptr->getProfiler()->
"", "Begin", "", RubyRequestType_to_string(request.type)); profileTransition("Seq", m_version, Address(request.paddr),
"", "Begin", "",
RubyRequestType_to_string(request.type));
} }
if (g_system_ptr->getTracer()->traceEnabled()) { if (g_system_ptr->getTracer()->traceEnabled()) {
g_system_ptr->getTracer()->traceRequest(this, line_addr, Address(request.pc), g_system_ptr->getTracer()->
traceRequest(this, line_addr, Address(request.pc),
request.type, g_eventQueue_ptr->getTime()); request.type, g_eventQueue_ptr->getTime());
} }
@@ -524,32 +563,37 @@ void Sequencer::issueRequest(const RubyRequest& request) {
assert(m_mandatory_q_ptr != NULL); assert(m_mandatory_q_ptr != NULL);
m_mandatory_q_ptr->enqueue(msg, latency); m_mandatory_q_ptr->enqueue(msg, latency);
} }
/*
bool Sequencer::tryCacheAccess(const Address& addr, CacheRequestType type, #if 0
bool
Sequencer::tryCacheAccess(const Address& addr, CacheRequestType type,
AccessModeType access_mode, AccessModeType access_mode,
int size, DataBlock*& data_ptr) { int size, DataBlock*& data_ptr)
if (type == CacheRequestType_IFETCH) { {
return m_instCache_ptr->tryCacheAccess(line_address(addr), type, data_ptr); CacheMemory *cache =
} else { (type == CacheRequestType_IFETCH) ? m_instCache_ptr : m_dataCache_ptr;
return m_dataCache_ptr->tryCacheAccess(line_address(addr), type, data_ptr);
}
}
*/
void Sequencer::print(ostream& out) const { return cache->tryCacheAccess(line_address(addr), type, data_ptr);
}
#endif
void
Sequencer::print(ostream& out) const
{
out << "[Sequencer: " << m_version out << "[Sequencer: " << m_version
<< ", outstanding requests: " << m_outstanding_count; << ", outstanding requests: " << m_outstanding_count
<< ", read request table: " << m_readRequestTable
out << ", read request table: " << m_readRequestTable << ", write request table: " << m_writeRequestTable
<< ", write request table: " << m_writeRequestTable; << "]";
out << "]";
} }
// this can be called from setState whenever coherence permissions are upgraded // this can be called from setState whenever coherence permissions are
// when invoked, coherence violations will be checked for the given block // upgraded when invoked, coherence violations will be checked for the
void Sequencer::checkCoherence(const Address& addr) { // given block
void
Sequencer::checkCoherence(const Address& addr)
{
#ifdef CHECK_COHERENCE #ifdef CHECK_COHERENCE
g_system_ptr->checkGlobalCoherenceInvariant(addr); g_system_ptr->checkGlobalCoherenceInvariant(addr);
#endif #endif
} }

View File

@@ -1,4 +1,3 @@
/* /*
* Copyright (c) 1999-2008 Mark D. Hill and David A. Wood * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
* All rights reserved. * All rights reserved.
@@ -27,25 +26,18 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
/* #ifndef __MEM_RUBY_SYSTEM_SEQUENCER_HH__
* $Id: Sequencer.hh 1.70 2006/09/27 14:56:41-05:00 bobba@s1-01.cs.wisc.edu $ #define __MEM_RUBY_SYSTEM_SEQUENCER_HH__
*
* Description:
*
*/
#ifndef SEQUENCER_H #include "mem/gems_common/Map.hh"
#define SEQUENCER_H
#include "mem/ruby/common/Global.hh"
#include "mem/ruby/common/Consumer.hh"
#include "mem/protocol/CacheRequestType.hh"
#include "mem/protocol/AccessModeType.hh" #include "mem/protocol/AccessModeType.hh"
#include "mem/protocol/CacheRequestType.hh"
#include "mem/protocol/GenericMachineType.hh" #include "mem/protocol/GenericMachineType.hh"
#include "mem/protocol/PrefetchBit.hh" #include "mem/protocol/PrefetchBit.hh"
#include "mem/ruby/system/RubyPort.hh"
#include "mem/gems_common/Map.hh"
#include "mem/ruby/common/Address.hh" #include "mem/ruby/common/Address.hh"
#include "mem/ruby/common/Consumer.hh"
#include "mem/ruby/common/Global.hh"
#include "mem/ruby/system/RubyPort.hh"
class DataBlock; class DataBlock;
class CacheMsg; class CacheMsg;
@@ -54,26 +46,23 @@ class CacheMemory;
class RubySequencerParams; class RubySequencerParams;
struct SequencerRequest { struct SequencerRequest
{
RubyRequest ruby_request; RubyRequest ruby_request;
Time issue_time; Time issue_time;
SequencerRequest(const RubyRequest & _ruby_request, SequencerRequest(const RubyRequest & _ruby_request, Time _issue_time)
Time _issue_time) : ruby_request(_ruby_request), issue_time(_issue_time)
: ruby_request(_ruby_request),
issue_time(_issue_time)
{} {}
}; };
std::ostream& operator<<(std::ostream& out, const SequencerRequest& obj); std::ostream& operator<<(std::ostream& out, const SequencerRequest& obj);
class Sequencer : public RubyPort, public Consumer { class Sequencer : public RubyPort, public Consumer
{
public: public:
typedef RubySequencerParams Params; typedef RubySequencerParams Params;
// Constructors
Sequencer(const Params *); Sequencer(const Params *);
// Destructor
~Sequencer(); ~Sequencer();
// Public Methods // Public Methods
@@ -94,13 +83,12 @@ public:
void printStats(ostream & out) const; void printStats(ostream & out) const;
void checkCoherence(const Address& address); void checkCoherence(const Address& address);
// bool getRubyMemoryValue(const Address& addr, char* value, unsigned int size_in_bytes);
// bool setRubyMemoryValue(const Address& addr, char *value, unsigned int size_in_bytes);
void removeRequest(SequencerRequest* request); void removeRequest(SequencerRequest* request);
private: private:
// Private Methods bool tryCacheAccess(const Address& addr, CacheRequestType type,
bool tryCacheAccess(const Address& addr, CacheRequestType type, const Address& pc, AccessModeType access_mode, int size, DataBlock*& data_ptr); const Address& pc, AccessModeType access_mode,
int size, DataBlock*& data_ptr);
void issueRequest(const RubyRequest& request); void issueRequest(const RubyRequest& request);
void hitCallback(SequencerRequest* request, DataBlock& data); void hitCallback(SequencerRequest* request, DataBlock& data);
@@ -133,6 +121,7 @@ private:
class SequencerWakeupEvent : public Event class SequencerWakeupEvent : public Event
{ {
private:
Sequencer *m_sequencer_ptr; Sequencer *m_sequencer_ptr;
public: public:
@@ -144,19 +133,13 @@ private:
SequencerWakeupEvent deadlockCheckEvent; SequencerWakeupEvent deadlockCheckEvent;
}; };
// Output operator declaration inline ostream&
ostream& operator<<(ostream& out, const Sequencer& obj); operator<<(ostream& out, const Sequencer& obj)
// ******************* Definitions *******************
// Output operator definition
extern inline
ostream& operator<<(ostream& out, const Sequencer& obj)
{ {
obj.print(out); obj.print(out);
out << flush; out << flush;
return out; return out;
} }
#endif //SEQUENCER_H #endif // __MEM_RUBY_SYSTEM_SEQUENCER_HH__

View File

@@ -1,4 +1,3 @@
/* /*
* Copyright (c) 2009 Advanced Micro Devices, Inc. * Copyright (c) 2009 Advanced Micro Devices, Inc.
* All rights reserved. * All rights reserved.
@@ -29,10 +28,6 @@
#include "mem/ruby/system/SparseMemory.hh" #include "mem/ruby/system/SparseMemory.hh"
// ****************************************************************
SparseMemory::SparseMemory(int number_of_bits, int number_of_levels) SparseMemory::SparseMemory(int number_of_bits, int number_of_levels)
{ {
int even_level_bits; int even_level_bits;
@@ -81,22 +76,16 @@ SparseMemory::recursivelyRemoveTables(SparseMapType* curTable, int curLevel)
SparseMapType::iterator iter; SparseMapType::iterator iter;
for (iter = curTable->begin(); iter != curTable->end(); iter++) { for (iter = curTable->begin(); iter != curTable->end(); iter++) {
SparseMemEntry_t* entryStruct = &((*iter).second); SparseMemEntry* entryStruct = &((*iter).second);
if (curLevel != (m_number_of_levels - 1)) { if (curLevel != (m_number_of_levels - 1)) {
// // If the not at the last level, analyze those lower level
// If the not at the last level, analyze those lower level tables first, // tables first, then delete those next tables
// then delete those next tables SparseMapType* nextTable = (SparseMapType*)(entryStruct->entry);
//
SparseMapType* nextTable;
nextTable = (SparseMapType*)(entryStruct->entry);
recursivelyRemoveTables(nextTable, (curLevel + 1)); recursivelyRemoveTables(nextTable, (curLevel + 1));
delete nextTable; delete nextTable;
} else { } else {
//
// If at the last level, delete the directory entry // If at the last level, delete the directory entry
//
Directory_Entry* dirEntry; Directory_Entry* dirEntry;
dirEntry = (Directory_Entry*)(entryStruct->entry); dirEntry = (Directory_Entry*)(entryStruct->entry);
delete dirEntry; delete dirEntry;
@@ -104,15 +93,10 @@ SparseMemory::recursivelyRemoveTables(SparseMapType* curTable, int curLevel)
entryStruct->entry = NULL; entryStruct->entry = NULL;
} }
//
// Once all entries have been deleted, erase the entries // Once all entries have been deleted, erase the entries
//
curTable->erase(curTable->begin(), curTable->end()); curTable->erase(curTable->begin(), curTable->end());
} }
// PUBLIC METHODS
// tests to see if an address is present in the memory // tests to see if an address is present in the memory
bool bool
SparseMemory::exist(const Address& address) const SparseMemory::exist(const Address& address) const
@@ -120,22 +104,19 @@ SparseMemory::exist(const Address& address) const
SparseMapType* curTable = m_map_head; SparseMapType* curTable = m_map_head;
Address curAddress; Address curAddress;
// // Initiallize the high bit to be the total number of bits plus
// Initiallize the high bit to be the total number of bits plus the block // the block offset. However the highest bit index is one less
// offset. However the highest bit index is one less than this value. // than this value.
//
int highBit = m_total_number_of_bits + RubySystem::getBlockSizeBits(); int highBit = m_total_number_of_bits + RubySystem::getBlockSizeBits();
int lowBit; int lowBit;
assert(address == line_address(address)); assert(address == line_address(address));
DEBUG_EXPR(CACHE_COMP, HighPrio, address); DEBUG_EXPR(CACHE_COMP, HighPrio, address);
for (int level = 0; level < m_number_of_levels; level++) { for (int level = 0; level < m_number_of_levels; level++) {
//
// Create the appropriate sub address for this level // Create the appropriate sub address for this level
// Note: that set Address is inclusive of the specified range, thus the // Note: that set Address is inclusive of the specified range,
// high bit is one less than the total number of bits used to create the // thus the high bit is one less than the total number of bits
// address. // used to create the address.
//
lowBit = highBit - m_number_of_bits_per_level[level]; lowBit = highBit - m_number_of_bits_per_level[level];
curAddress.setAddress(address.bitSelect(lowBit, highBit - 1)); curAddress.setAddress(address.bitSelect(lowBit, highBit - 1));
@@ -144,15 +125,11 @@ SparseMemory::exist(const Address& address) const
DEBUG_EXPR(CACHE_COMP, HighPrio, highBit - 1); DEBUG_EXPR(CACHE_COMP, HighPrio, highBit - 1);
DEBUG_EXPR(CACHE_COMP, HighPrio, curAddress); DEBUG_EXPR(CACHE_COMP, HighPrio, curAddress);
//
// Adjust the highBit value for the next level // Adjust the highBit value for the next level
//
highBit -= m_number_of_bits_per_level[level]; highBit -= m_number_of_bits_per_level[level];
// // If the address is found, move on to the next level.
// If the address is found, move on to the next level. Otherwise, // Otherwise, return not found
// return not found
//
if (curTable->count(curAddress) != 0) { if (curTable->count(curAddress) != 0) {
curTable = (SparseMapType*)(((*curTable)[curAddress]).entry); curTable = (SparseMapType*)(((*curTable)[curAddress]).entry);
} else { } else {
@@ -176,43 +153,34 @@ SparseMemory::add(const Address& address)
Address curAddress; Address curAddress;
SparseMapType* curTable = m_map_head; SparseMapType* curTable = m_map_head;
SparseMemEntry_t* entryStruct = NULL; SparseMemEntry* entryStruct = NULL;
// // Initiallize the high bit to be the total number of bits plus
// Initiallize the high bit to be the total number of bits plus the block // the block offset. However the highest bit index is one less
// offset. However the highest bit index is one less than this value. // than this value.
//
int highBit = m_total_number_of_bits + RubySystem::getBlockSizeBits(); int highBit = m_total_number_of_bits + RubySystem::getBlockSizeBits();
int lowBit; int lowBit;
void* newEntry = NULL; void* newEntry = NULL;
for (int level = 0; level < m_number_of_levels; level++) { for (int level = 0; level < m_number_of_levels; level++) {
//
// create the appropriate address for this level // create the appropriate address for this level
// Note: that set Address is inclusive of the specified range, thus the // Note: that set Address is inclusive of the specified range,
// high bit is one less than the total number of bits used to create the // thus the high bit is one less than the total number of bits
// address. // used to create the address.
//
lowBit = highBit - m_number_of_bits_per_level[level]; lowBit = highBit - m_number_of_bits_per_level[level];
curAddress.setAddress(address.bitSelect(lowBit, highBit - 1)); curAddress.setAddress(address.bitSelect(lowBit, highBit - 1));
//
// Adjust the highBit value for the next level // Adjust the highBit value for the next level
//
highBit -= m_number_of_bits_per_level[level]; highBit -= m_number_of_bits_per_level[level];
//
// if the address exists in the cur table, move on. Otherwise // if the address exists in the cur table, move on. Otherwise
// create a new table. // create a new table.
//
if (curTable->count(curAddress) != 0) { if (curTable->count(curAddress) != 0) {
curTable = (SparseMapType*)(((*curTable)[curAddress]).entry); curTable = (SparseMapType*)(((*curTable)[curAddress]).entry);
} else { } else {
m_adds_per_level[level]++; m_adds_per_level[level]++;
//
// if the last level, add a directory entry. Otherwise add a map. // if the last level, add a directory entry. Otherwise add a map.
//
if (level == (m_number_of_levels - 1)) { if (level == (m_number_of_levels - 1)) {
Directory_Entry* tempDirEntry = new Directory_Entry(); Directory_Entry* tempDirEntry = new Directory_Entry();
tempDirEntry->getDataBlk().clear(); tempDirEntry->getDataBlk().clear();
@@ -222,17 +190,13 @@ SparseMemory::add(const Address& address)
newEntry = (void*)(tempMap); newEntry = (void*)(tempMap);
} }
// // Create the pointer container SparseMemEntry and add it
// Create the pointer container SparseMemEntry_t and add it to the // to the table.
// table. entryStruct = new SparseMemEntry;
//
entryStruct = new SparseMemEntry_t;
entryStruct->entry = newEntry; entryStruct->entry = newEntry;
(*curTable)[curAddress] = *entryStruct; (*curTable)[curAddress] = *entryStruct;
//
// Move to the next level of the heirarchy // Move to the next level of the heirarchy
//
curTable = (SparseMapType*)newEntry; curTable = (SparseMapType*)newEntry;
} }
} }
@@ -244,20 +208,17 @@ SparseMemory::add(const Address& address)
// recursively search table hierarchy for the lowest level table. // recursively search table hierarchy for the lowest level table.
// remove the lowest entry and any empty tables above it. // remove the lowest entry and any empty tables above it.
int int
SparseMemory::recursivelyRemoveLevels( SparseMemory::recursivelyRemoveLevels(const Address& address,
const Address& address, CurNextInfo& curInfo)
curNextInfo& curInfo)
{ {
Address curAddress; Address curAddress;
curNextInfo nextInfo; CurNextInfo nextInfo;
SparseMemEntry_t* entryStruct; SparseMemEntry* entryStruct;
//
// create the appropriate address for this level // create the appropriate address for this level
// Note: that set Address is inclusive of the specified range, thus the // Note: that set Address is inclusive of the specified range,
// high bit is one less than the total number of bits used to create the // thus the high bit is one less than the total number of bits
// address. // used to create the address.
//
curAddress.setAddress(address.bitSelect(curInfo.lowBit, curAddress.setAddress(address.bitSelect(curInfo.lowBit,
curInfo.highBit - 1)); curInfo.highBit - 1));
@@ -272,9 +233,7 @@ SparseMemory::recursivelyRemoveLevels(
entryStruct = &((*(curInfo.curTable))[curAddress]); entryStruct = &((*(curInfo.curTable))[curAddress]);
if (curInfo.level < (m_number_of_levels - 1)) { if (curInfo.level < (m_number_of_levels - 1)) {
//
// set up next level's info // set up next level's info
//
nextInfo.curTable = (SparseMapType*)(entryStruct->entry); nextInfo.curTable = (SparseMapType*)(entryStruct->entry);
nextInfo.level = curInfo.level + 1; nextInfo.level = curInfo.level + 1;
@@ -284,15 +243,11 @@ SparseMemory::recursivelyRemoveLevels(
nextInfo.lowBit = curInfo.lowBit - nextInfo.lowBit = curInfo.lowBit -
m_number_of_bits_per_level[curInfo.level + 1]; m_number_of_bits_per_level[curInfo.level + 1];
//
// recursively search the table hierarchy // recursively search the table hierarchy
//
int tableSize = recursivelyRemoveLevels(address, nextInfo); int tableSize = recursivelyRemoveLevels(address, nextInfo);
// // If this table below is now empty, we must delete it and
// If this table below is now empty, we must delete it and erase it from // erase it from our table.
// our table.
//
if (tableSize == 0) { if (tableSize == 0) {
m_removes_per_level[curInfo.level]++; m_removes_per_level[curInfo.level]++;
delete nextInfo.curTable; delete nextInfo.curTable;
@@ -300,10 +255,9 @@ SparseMemory::recursivelyRemoveLevels(
curInfo.curTable->erase(curAddress); curInfo.curTable->erase(curAddress);
} }
} else { } else {
// // if this is the last level, we have reached the Directory
// if this is the last level, we have reached the Directory Entry and thus // Entry and thus we should delete it including the
// we should delete it including the SparseMemEntry container struct. // SparseMemEntry container struct.
//
Directory_Entry* dirEntry; Directory_Entry* dirEntry;
dirEntry = (Directory_Entry*)(entryStruct->entry); dirEntry = (Directory_Entry*)(entryStruct->entry);
entryStruct->entry = NULL; entryStruct->entry = NULL;
@@ -323,26 +277,21 @@ SparseMemory::remove(const Address& address)
m_total_removes++; m_total_removes++;
curNextInfo nextInfo; CurNextInfo nextInfo;
//
// Initialize table pointer and level value // Initialize table pointer and level value
//
nextInfo.curTable = m_map_head; nextInfo.curTable = m_map_head;
nextInfo.level = 0; nextInfo.level = 0;
// // Initiallize the high bit to be the total number of bits plus
// Initiallize the high bit to be the total number of bits plus the block // the block offset. However the highest bit index is one less
// offset. However the highest bit index is one less than this value. // than this value.
//
nextInfo.highBit = m_total_number_of_bits + RubySystem::getBlockSizeBits(); nextInfo.highBit = m_total_number_of_bits + RubySystem::getBlockSizeBits();
nextInfo.lowBit = nextInfo.highBit - m_number_of_bits_per_level[0];; nextInfo.lowBit = nextInfo.highBit - m_number_of_bits_per_level[0];;
// // recursively search the table hierarchy for empty tables
// recursively search the table hierarchy for empty tables starting from the // starting from the level 0. Note we do not check the return
// level 0. Note we do not check the return value because the head table is // value because the head table is never deleted;
// never deleted;
//
recursivelyRemoveLevels(address, nextInfo); recursivelyRemoveLevels(address, nextInfo);
assert(!exist(address)); assert(!exist(address));
@@ -362,20 +311,17 @@ SparseMemory::lookup(const Address& address)
SparseMapType* curTable = m_map_head; SparseMapType* curTable = m_map_head;
Directory_Entry* entry = NULL; Directory_Entry* entry = NULL;
// // Initiallize the high bit to be the total number of bits plus
// Initiallize the high bit to be the total number of bits plus the block // the block offset. However the highest bit index is one less
// offset. However the highest bit index is one less than this value. // than this value.
//
int highBit = m_total_number_of_bits + RubySystem::getBlockSizeBits(); int highBit = m_total_number_of_bits + RubySystem::getBlockSizeBits();
int lowBit; int lowBit;
for (int level = 0; level < m_number_of_levels; level++) { for (int level = 0; level < m_number_of_levels; level++) {
//
// create the appropriate address for this level // create the appropriate address for this level
// Note: that set Address is inclusive of the specified range, thus the // Note: that set Address is inclusive of the specified range,
// high bit is one less than the total number of bits used to create the // thus the high bit is one less than the total number of bits
// address. // used to create the address.
//
lowBit = highBit - m_number_of_bits_per_level[level]; lowBit = highBit - m_number_of_bits_per_level[level];
curAddress.setAddress(address.bitSelect(lowBit, highBit - 1)); curAddress.setAddress(address.bitSelect(lowBit, highBit - 1));
@@ -384,21 +330,15 @@ SparseMemory::lookup(const Address& address)
DEBUG_EXPR(CACHE_COMP, HighPrio, highBit - 1); DEBUG_EXPR(CACHE_COMP, HighPrio, highBit - 1);
DEBUG_EXPR(CACHE_COMP, HighPrio, curAddress); DEBUG_EXPR(CACHE_COMP, HighPrio, curAddress);
//
// Adjust the highBit value for the next level // Adjust the highBit value for the next level
//
highBit -= m_number_of_bits_per_level[level]; highBit -= m_number_of_bits_per_level[level];
//
// The entry should be in the table and valid // The entry should be in the table and valid
//
curTable = (SparseMapType*)(((*curTable)[curAddress]).entry); curTable = (SparseMapType*)(((*curTable)[curAddress]).entry);
assert(curTable != NULL); assert(curTable != NULL);
} }
//
// The last entry actually points to the Directory entry not a table // The last entry actually points to the Directory entry not a table
//
entry = (Directory_Entry*)curTable; entry = (Directory_Entry*)curTable;
return entry; return entry;

View File

@@ -1,4 +1,3 @@
/* /*
* Copyright (c) 2009 Advanced Micro Devices, Inc. * Copyright (c) 2009 Advanced Micro Devices, Inc.
* All rights reserved. * All rights reserved.
@@ -27,39 +26,35 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#ifndef __MEM_RUBY_SYSTEM_SPARSEMEMORY_HH__
#define __MEM_RUBY_SYSTEM_SPARSEMEMORY_HH__
#ifndef SPARSEMEMORY_H
#define SPARSEMEMORY_H
#include "mem/ruby/common/Global.hh"
#include "base/hashmap.hh" #include "base/hashmap.hh"
#include "mem/ruby/common/Address.hh"
#include "mem/protocol/Directory_Entry.hh" #include "mem/protocol/Directory_Entry.hh"
#include "mem/ruby/common/Address.hh"
#include "mem/ruby/common/Global.hh"
typedef struct SparseMemEntry { struct SparseMemEntry
{
void* entry; void* entry;
} SparseMemEntry_t; };
typedef m5::hash_map<Address, SparseMemEntry_t> SparseMapType; typedef m5::hash_map<Address, SparseMemEntry> SparseMapType;
typedef struct curNextInfo { struct CurNextInfo
{
SparseMapType* curTable; SparseMapType* curTable;
int level; int level;
int highBit; int highBit;
int lowBit; int lowBit;
}; };
class SparseMemory { class SparseMemory
{
public: public:
// Constructors
SparseMemory(int number_of_bits, int number_of_levels); SparseMemory(int number_of_bits, int number_of_levels);
// Destructor
~SparseMemory(); ~SparseMemory();
// Public Methods
void printConfig(ostream& out) { } void printConfig(ostream& out) { }
bool exist(const Address& address) const; bool exist(const Address& address) const;
@@ -83,7 +78,7 @@ class SparseMemory {
void recursivelyRemoveTables(SparseMapType* currentTable, int level); void recursivelyRemoveTables(SparseMapType* currentTable, int level);
// recursive search for address and remove associated entries // recursive search for address and remove associated entries
int recursivelyRemoveLevels(const Address& address, curNextInfo& curInfo); int recursivelyRemoveLevels(const Address& address, CurNextInfo& curInfo);
// Data Members (m_prefix) // Data Members (m_prefix)
SparseMapType* m_map_head; SparseMapType* m_map_head;
@@ -98,17 +93,12 @@ class SparseMemory {
uint64_t* m_removes_per_level; uint64_t* m_removes_per_level;
}; };
// Output operator declaration inline ostream&
ostream& operator<<(ostream& out, const SparseMemEntry& obj); operator<<(ostream& out, const SparseMemEntry& obj)
// Output operator definition
extern inline
ostream& operator<<(ostream& out, const SparseMemEntry& obj)
{ {
out << "SparseMemEntry"; out << "SparseMemEntry";
out << flush; out << flush;
return out; return out;
} }
#endif // __MEM_RUBY_SYSTEM_SPARSEMEMORY_HH__
#endif //SPARSEMEMORY_H

View File

@@ -1,4 +1,3 @@
/* /*
* Copyright (c) 1999-2008 Mark D. Hill and David A. Wood * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
* All rights reserved. * All rights reserved.
@@ -27,25 +26,15 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
/*
* RubySystem.cc
*
* Description: See System.hh
*
* $Id$
*
*/
#include "mem/ruby/system/System.hh"
#include "mem/ruby/common/Address.hh"
#include "mem/ruby/profiler/Profiler.hh"
#include "mem/ruby/network/Network.hh"
#include "mem/ruby/recorder/Tracer.hh"
#include "mem/ruby/buffers/MessageBuffer.hh"
#include "mem/ruby/system/MemoryVector.hh"
#include "mem/ruby/slicc_interface/AbstractController.hh"
#include "base/output.hh" #include "base/output.hh"
#include "mem/ruby/buffers/MessageBuffer.hh"
#include "mem/ruby/common/Address.hh"
#include "mem/ruby/network/Network.hh"
#include "mem/ruby/profiler/Profiler.hh"
#include "mem/ruby/recorder/Tracer.hh"
#include "mem/ruby/slicc_interface/AbstractController.hh"
#include "mem/ruby/system/MemoryVector.hh"
#include "mem/ruby/system/System.hh"
int RubySystem::m_random_seed; int RubySystem::m_random_seed;
bool RubySystem::m_randomization; bool RubySystem::m_randomization;
@@ -103,37 +92,36 @@ RubySystem::RubySystem(const Params *p)
registerExitCallback(rubyExitCB); registerExitCallback(rubyExitCB);
} }
void
void RubySystem::init() RubySystem::init()
{ {
m_profiler_ptr->clearStats(); m_profiler_ptr->clearStats();
} }
RubySystem::~RubySystem() RubySystem::~RubySystem()
{ {
delete m_network_ptr; delete m_network_ptr;
delete m_profiler_ptr; delete m_profiler_ptr;
delete m_tracer_ptr; delete m_tracer_ptr;
if (m_mem_vec_ptr != NULL) { if (m_mem_vec_ptr)
delete m_mem_vec_ptr; delete m_mem_vec_ptr;
} }
}
void RubySystem::printSystemConfig(ostream & out) void
RubySystem::printSystemConfig(ostream & out)
{ {
out << "RubySystem config:" << endl; out << "RubySystem config:" << endl
out << " random_seed: " << m_random_seed << endl; << " random_seed: " << m_random_seed << endl
out << " randomization: " << m_randomization << endl; << " randomization: " << m_randomization << endl
out << " cycle_period: " << m_clock << endl; << " cycle_period: " << m_clock << endl
out << " block_size_bytes: " << m_block_size_bytes << endl; << " block_size_bytes: " << m_block_size_bytes << endl
out << " block_size_bits: " << m_block_size_bits << endl; << " block_size_bits: " << m_block_size_bits << endl
out << " memory_size_bytes: " << m_memory_size_bytes << endl; << " memory_size_bytes: " << m_memory_size_bytes << endl
out << " memory_size_bits: " << m_memory_size_bits << endl; << " memory_size_bits: " << m_memory_size_bits << endl;
} }
void RubySystem::printConfig(ostream& out) void
RubySystem::printConfig(ostream& out)
{ {
out << "\n================ Begin RubySystem Configuration Print ================\n\n"; out << "\n================ Begin RubySystem Configuration Print ================\n\n";
printSystemConfig(out); printSystemConfig(out);
@@ -142,9 +130,9 @@ void RubySystem::printConfig(ostream& out)
out << "\n================ End RubySystem Configuration Print ================\n\n"; out << "\n================ End RubySystem Configuration Print ================\n\n";
} }
void RubySystem::printStats(ostream& out) void
RubySystem::printStats(ostream& out)
{ {
const time_t T = time(NULL); const time_t T = time(NULL);
tm *localTime = localtime(&T); tm *localTime = localtime(&T);
char buf[100]; char buf[100];
@@ -156,15 +144,16 @@ void RubySystem::printStats(ostream& out)
m_network_ptr->printStats(out); m_network_ptr->printStats(out);
} }
void RubySystem::clearStats() const void
RubySystem::clearStats() const
{ {
m_profiler_ptr->clearStats(); m_profiler_ptr->clearStats();
m_network_ptr->clearStats(); m_network_ptr->clearStats();
} }
void RubySystem::recordCacheContents(CacheRecorder& tr) const void
RubySystem::recordCacheContents(CacheRecorder& tr) const
{ {
} }
#ifdef CHECK_COHERENCE #ifdef CHECK_COHERENCE
@@ -176,14 +165,15 @@ void RubySystem::recordCacheContents(CacheRecorder& tr) const
// in setState. The SLICC spec must also define methods "isBlockShared" // in setState. The SLICC spec must also define methods "isBlockShared"
// and "isBlockExclusive" that are specific to that protocol // and "isBlockExclusive" that are specific to that protocol
// //
void RubySystem::checkGlobalCoherenceInvariant(const Address& addr ) { void
/* RubySystem::checkGlobalCoherenceInvariant(const Address& addr)
{
#if 0
NodeID exclusive = -1; NodeID exclusive = -1;
bool sharedDetected = false; bool sharedDetected = false;
NodeID lastShared = -1; NodeID lastShared = -1;
for (int i = 0; i < m_chip_vector.size(); i++) { for (int i = 0; i < m_chip_vector.size(); i++) {
if (m_chip_vector[i]->isBlockExclusive(addr)) { if (m_chip_vector[i]->isBlockExclusive(addr)) {
if (exclusive != -1) { if (exclusive != -1) {
// coherence violation // coherence violation
@@ -192,19 +182,16 @@ void RubySystem::checkGlobalCoherenceInvariant(const Address& addr ) {
WARN_EXPR(addr); WARN_EXPR(addr);
WARN_EXPR(g_eventQueue_ptr->getTime()); WARN_EXPR(g_eventQueue_ptr->getTime());
ERROR_MSG("Coherence Violation Detected -- 2 exclusive chips"); ERROR_MSG("Coherence Violation Detected -- 2 exclusive chips");
} } else if (sharedDetected) {
else if (sharedDetected) {
WARN_EXPR(lastShared); WARN_EXPR(lastShared);
WARN_EXPR(m_chip_vector[i]->getID()); WARN_EXPR(m_chip_vector[i]->getID());
WARN_EXPR(addr); WARN_EXPR(addr);
WARN_EXPR(g_eventQueue_ptr->getTime()); WARN_EXPR(g_eventQueue_ptr->getTime());
ERROR_MSG("Coherence Violation Detected -- exclusive chip with >=1 shared"); ERROR_MSG("Coherence Violation Detected -- exclusive chip with >=1 shared");
} } else {
else {
exclusive = m_chip_vector[i]->getID(); exclusive = m_chip_vector[i]->getID();
} }
} } else if (m_chip_vector[i]->isBlockShared(addr)) {
else if (m_chip_vector[i]->isBlockShared(addr)) {
sharedDetected = true; sharedDetected = true;
lastShared = m_chip_vector[i]->getID(); lastShared = m_chip_vector[i]->getID();
@@ -217,7 +204,7 @@ void RubySystem::checkGlobalCoherenceInvariant(const Address& addr ) {
} }
} }
} }
*/ #endif
} }
#endif #endif
@@ -231,7 +218,8 @@ RubySystemParams::create()
* virtual process function that is invoked when the callback * virtual process function that is invoked when the callback
* queue is executed. * queue is executed.
*/ */
void RubyExitCallback::process() void
RubyExitCallback::process()
{ {
std::ostream *os = simout.create(stats_filename); std::ostream *os = simout.create(stats_filename);
RubySystem::printConfig(*os); RubySystem::printConfig(*os);

View File

@@ -1,4 +1,3 @@
/* /*
* Copyright (c) 1999-2008 Mark D. Hill and David A. Wood * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
* All rights reserved. * All rights reserved.
@@ -28,32 +27,27 @@
*/ */
/* /*
* System.hh * Contains all of the various parts of the system we are simulating.
* * Performs allocation, deallocation, and setup of all the major
* Description: Contains all of the various parts of the system we are * components of the system
* simulating. Performs allocation, deallocation, and setup of all
* the major components of the system
*
* $Id$
*
*/ */
#ifndef SYSTEM_H #ifndef __MEM_RUBY_SYSTEM_SYSTEM_HH__
#define SYSTEM_H #define __MEM_RUBY_SYSTEM_SYSTEM_HH__
#include "mem/ruby/system/RubyPort.hh"
#include "mem/ruby/common/Global.hh"
#include "mem/gems_common/Vector.hh"
#include "mem/ruby/eventqueue/RubyEventQueue.hh"
#include "sim/sim_object.hh"
#include "params/RubySystem.hh"
#include "base/callback.hh" #include "base/callback.hh"
#include "mem/gems_common/Vector.hh"
#include "mem/ruby/common/Global.hh"
#include "mem/ruby/eventqueue/RubyEventQueue.hh"
#include "mem/ruby/system/RubyPort.hh"
#include "params/RubySystem.hh"
#include "sim/sim_object.hh"
class Profiler;
class Network;
class CacheRecorder; class CacheRecorder;
class Tracer;
class MemoryVector; class MemoryVector;
class Network;
class Profiler;
class Tracer;
/* /*
* This defines the number of longs (32-bits on 32 bit machines, * This defines the number of longs (32-bits on 32 bit machines,
@@ -68,11 +62,11 @@ class MemoryVector;
*/ */
const int NUMBER_WORDS_PER_SET = 1; const int NUMBER_WORDS_PER_SET = 1;
class RubySystem : public SimObject { class RubySystem : public SimObject
{
public: public:
typedef RubySystemParams Params; typedef RubySystemParams Params;
RubySystem(const Params *p); RubySystem(const Params *p);
// Destructor
~RubySystem(); ~RubySystem();
// config accessors // config accessors
@@ -84,11 +78,39 @@ public:
static int getMemorySizeBits() { return m_memory_size_bits; } static int getMemorySizeBits() { return m_memory_size_bits; }
// Public Methods // Public Methods
static Network* getNetwork() { assert(m_network_ptr != NULL); return m_network_ptr; } static Network*
static RubyEventQueue* getEventQueue() { return g_eventQueue_ptr; } getNetwork()
Profiler* getProfiler() {assert(m_profiler_ptr != NULL); return m_profiler_ptr; } {
static Tracer* getTracer() { assert(m_tracer_ptr != NULL); return m_tracer_ptr; } assert(m_network_ptr != NULL);
static MemoryVector* getMemoryVector() { assert(m_mem_vec_ptr != NULL); return m_mem_vec_ptr;} return m_network_ptr;
}
static RubyEventQueue*
getEventQueue()
{
return g_eventQueue_ptr;
}
Profiler*
getProfiler()
{
assert(m_profiler_ptr != NULL);
return m_profiler_ptr;
}
static Tracer*
getTracer()
{
assert(m_tracer_ptr != NULL);
return m_tracer_ptr;
}
static MemoryVector*
getMemoryVector()
{
assert(m_mem_vec_ptr != NULL);
return m_mem_vec_ptr;
}
void recordCacheContents(CacheRecorder& tr) const; void recordCacheContents(CacheRecorder& tr) const;
static void printConfig(ostream& out); static void printConfig(ostream& out);
@@ -96,14 +118,13 @@ public:
void clearStats() const; void clearStats() const;
uint64 getInstructionCount(int thread) { return 1; } uint64 getInstructionCount(int thread) { return 1; }
static uint64 getCycleCount(int thread) { return g_eventQueue_ptr->getTime(); } static uint64
getCycleCount(int thread)
{
return g_eventQueue_ptr->getTime();
}
void print(ostream& out) const; void print(ostream& out) const;
/*
#ifdef CHECK_COHERENCE
void checkGlobalCoherenceInvariant(const Address& addr);
#endif
*/
private: private:
// Private copy constructor and assignment operator // Private copy constructor and assignment operator
@@ -124,7 +145,6 @@ private:
static uint64 m_memory_size_bytes; static uint64 m_memory_size_bytes;
static int m_memory_size_bits; static int m_memory_size_bits;
// Data Members (m_ prefix)
static Network* m_network_ptr; static Network* m_network_ptr;
public: public:
@@ -133,14 +153,8 @@ public:
static MemoryVector* m_mem_vec_ptr; static MemoryVector* m_mem_vec_ptr;
}; };
// Output operator declaration inline ostream&
ostream& operator<<(ostream& out, const RubySystem& obj); operator<<(ostream& out, const RubySystem& obj)
// ******************* Definitions *******************
// Output operator definition
inline
ostream& operator<<(ostream& out, const RubySystem& obj)
{ {
//obj.print(out); //obj.print(out);
out << flush; out << flush;
@@ -153,11 +167,6 @@ class RubyExitCallback : public Callback
string stats_filename; string stats_filename;
public: public:
/**
* virtualize the destructor to make sure that the correct one
* gets called.
*/
virtual ~RubyExitCallback() {} virtual ~RubyExitCallback() {}
RubyExitCallback(const string& _stats_filename) RubyExitCallback(const string& _stats_filename)
@@ -168,7 +177,7 @@ class RubyExitCallback : public Callback
virtual void process(); virtual void process();
}; };
#endif //SYSTEM_H #endif // __MEM_RUBY_SYSTEM_SYSTEM_HH__

View File

@@ -1,4 +1,3 @@
/* /*
* Copyright (c) 1999-2008 Mark D. Hill and David A. Wood * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
* All rights reserved. * All rights reserved.
@@ -27,52 +26,46 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
/* #ifndef __MEM_RUBY_SYSTEM_TBETABLE_HH__
* TBETable.hh #define __MEM_RUBY_SYSTEM_TBETABLE_HH__
*
* Description:
*
* $Id$
*
*/
#ifndef TBETABLE_H
#define TBETABLE_H
#include "mem/ruby/common/Global.hh"
#include "mem/gems_common/Map.hh" #include "mem/gems_common/Map.hh"
#include "mem/ruby/common/Address.hh" #include "mem/ruby/common/Address.hh"
#include "mem/ruby/common/Global.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"
template<class ENTRY> template<class ENTRY>
class TBETable { class TBETable
{
public: public:
TBETable(int number_of_TBEs)
: m_number_of_TBEs(number_of_TBEs)
{
}
// Constructors void
TBETable(int number_of_TBEs); printConfig(ostream& out)
{
out << "TBEs_per_TBETable: " << m_number_of_TBEs << endl;
// Destructor }
//~TBETable();
// Public Methods
void printConfig(ostream& out) { out << "TBEs_per_TBETable: " << m_number_of_TBEs << endl; }
bool isPresent(const Address& address) const; bool isPresent(const Address& address) const;
void allocate(const Address& address); void allocate(const Address& address);
void deallocate(const Address& address); void deallocate(const Address& address);
bool areNSlotsAvailable(int n) const { return (m_number_of_TBEs - m_map.size()) >= n; } bool
areNSlotsAvailable(int n) const
{
return (m_number_of_TBEs - m_map.size()) >= n;
}
ENTRY& lookup(const Address& address); ENTRY& lookup(const Address& address);
const ENTRY& lookup(const Address& address) const; const ENTRY& lookup(const Address& address) const;
// Print cache contents // Print cache contents
void print(ostream& out) const; void print(ostream& out) const;
private:
// Private Methods
private:
// Private copy constructor and assignment operator // Private copy constructor and assignment operator
TBETable(const TBETable& obj); TBETable(const TBETable& obj);
TBETable& operator=(const TBETable& obj); TBETable& operator=(const TBETable& obj);
@@ -84,38 +77,18 @@ private:
int m_number_of_TBEs; int m_number_of_TBEs;
}; };
// Output operator declaration
//ostream& operator<<(ostream& out, const TBETable<ENTRY>& obj);
// ******************* Definitions *******************
// Output operator definition
template<class ENTRY> template<class ENTRY>
extern inline inline ostream&
ostream& operator<<(ostream& out, const TBETable<ENTRY>& obj) operator<<(ostream& out, const TBETable<ENTRY>& obj)
{ {
obj.print(out); obj.print(out);
out << flush; out << flush;
return out; return out;
} }
// ****************************************************************
template<class ENTRY> template<class ENTRY>
extern inline inline bool
TBETable<ENTRY>::TBETable(int number_of_TBEs) TBETable<ENTRY>::isPresent(const Address& address) const
{
m_number_of_TBEs = number_of_TBEs;
}
// PUBLIC METHODS
// tests to see if an address is present in the cache
template<class ENTRY>
extern inline
bool TBETable<ENTRY>::isPresent(const Address& address) const
{ {
assert(address == line_address(address)); assert(address == line_address(address));
assert(m_map.size() <= m_number_of_TBEs); assert(m_map.size() <= m_number_of_TBEs);
@@ -123,8 +96,8 @@ bool TBETable<ENTRY>::isPresent(const Address& address) const
} }
template<class ENTRY> template<class ENTRY>
extern inline inline void
void TBETable<ENTRY>::allocate(const Address& address) TBETable<ENTRY>::allocate(const Address& address)
{ {
assert(isPresent(address) == false); assert(isPresent(address) == false);
assert(m_map.size() < m_number_of_TBEs); assert(m_map.size() < m_number_of_TBEs);
@@ -132,8 +105,8 @@ void TBETable<ENTRY>::allocate(const Address& address)
} }
template<class ENTRY> template<class ENTRY>
extern inline inline void
void TBETable<ENTRY>::deallocate(const Address& address) TBETable<ENTRY>::deallocate(const Address& address)
{ {
assert(isPresent(address) == true); assert(isPresent(address) == true);
assert(m_map.size() > 0); assert(m_map.size() > 0);
@@ -142,8 +115,8 @@ void TBETable<ENTRY>::deallocate(const Address& address)
// looks an address up in the cache // looks an address up in the cache
template<class ENTRY> template<class ENTRY>
extern inline inline ENTRY&
ENTRY& TBETable<ENTRY>::lookup(const Address& address) TBETable<ENTRY>::lookup(const Address& address)
{ {
assert(isPresent(address) == true); assert(isPresent(address) == true);
return m_map.lookup(address); return m_map.lookup(address);
@@ -151,17 +124,17 @@ ENTRY& TBETable<ENTRY>::lookup(const Address& address)
// looks an address up in the cache // looks an address up in the cache
template<class ENTRY> template<class ENTRY>
extern inline inline const ENTRY&
const ENTRY& TBETable<ENTRY>::lookup(const Address& address) const TBETable<ENTRY>::lookup(const Address& address) const
{ {
assert(isPresent(address) == true); assert(isPresent(address) == true);
return m_map.lookup(address); return m_map.lookup(address);
} }
template<class ENTRY> template<class ENTRY>
extern inline inline void
void TBETable<ENTRY>::print(ostream& out) const TBETable<ENTRY>::print(ostream& out) const
{ {
} }
#endif //TBETABLE_H #endif // __MEM_RUBY_SYSTEM_TBETABLE_HH__

View File

@@ -1,4 +1,3 @@
/* /*
* Copyright (c) 1999-2008 Mark D. Hill and David A. Wood * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
* All rights reserved. * All rights reserved.
@@ -27,13 +26,9 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
/*
* $Id$
*/
#include "mem/ruby/common/Global.hh" #include "mem/ruby/common/Global.hh"
#include "mem/ruby/system/TimerTable.hh"
#include "mem/ruby/eventqueue/RubyEventQueue.hh" #include "mem/ruby/eventqueue/RubyEventQueue.hh"
#include "mem/ruby/system/TimerTable.hh"
TimerTable::TimerTable() TimerTable::TimerTable()
{ {
@@ -43,8 +38,8 @@ TimerTable::TimerTable()
m_next_time = 0; m_next_time = 0;
} }
bool
bool TimerTable::isReady() const TimerTable::isReady() const
{ {
if (m_map.size() == 0) { if (m_map.size() == 0) {
return false; return false;
@@ -57,7 +52,8 @@ bool TimerTable::isReady() const
return (g_eventQueue_ptr->getTime() >= m_next_time); return (g_eventQueue_ptr->getTime() >= m_next_time);
} }
const Address& TimerTable::readyAddress() const const Address&
TimerTable::readyAddress() const
{ {
assert(isReady()); assert(isReady());
@@ -68,7 +64,8 @@ const Address& TimerTable::readyAddress() const
return m_next_address; return m_next_address;
} }
void TimerTable::set(const Address& address, Time relative_latency) void
TimerTable::set(const Address& address, Time relative_latency)
{ {
assert(address == line_address(address)); assert(address == line_address(address));
assert(relative_latency > 0); assert(relative_latency > 0);
@@ -85,7 +82,8 @@ void TimerTable::set(const Address& address, Time relative_latency)
} }
} }
void TimerTable::unset(const Address& address) void
TimerTable::unset(const Address& address)
{ {
assert(address == line_address(address)); assert(address == line_address(address));
assert(m_map.exist(address) == true); assert(m_map.exist(address) == true);
@@ -97,12 +95,13 @@ void TimerTable::unset(const Address& address)
} }
} }
void TimerTable::print(ostream& out) const void
TimerTable::print(ostream& out) const
{ {
} }
void
void TimerTable::updateNext() const TimerTable::updateNext() const
{ {
if (m_map.size() == 0) { if (m_map.size() == 0) {
assert(m_next_valid == false); assert(m_next_valid == false);

View File

@@ -1,4 +1,3 @@
/* /*
* Copyright (c) 1999-2008 Mark D. Hill and David A. Wood * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
* All rights reserved. * All rights reserved.
@@ -27,38 +26,36 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
/* #ifndef __MEM_RUBY_SYSTEM_TIMERTABLE_HH__
* TimerTable.hh #define __MEM_RUBY_SYSTEM_TIMERTABLE_HH__
*
* Description:
*
* $Id$
*
*/
#ifndef TIMERTABLE_H #include <cassert>
#define TIMERTABLE_H
#include "mem/ruby/common/Global.hh"
#include "mem/gems_common/Map.hh" #include "mem/gems_common/Map.hh"
#include "mem/ruby/common/Address.hh" #include "mem/ruby/common/Address.hh"
#include "mem/ruby/common/Global.hh"
class Consumer; class Consumer;
class TimerTable { class TimerTable
{
public: public:
// Constructors
TimerTable(); TimerTable();
// Destructor
//~TimerTable();
// Class Methods
static void printConfig(ostream& out) {} static void printConfig(ostream& out) {}
// Public Methods void
void setConsumer(Consumer* consumer_ptr) { ASSERT(m_consumer_ptr==NULL); m_consumer_ptr = consumer_ptr; } setConsumer(Consumer* consumer_ptr)
void setDescription(const string& name) { m_name = name; } {
assert(m_consumer_ptr == NULL);
m_consumer_ptr = consumer_ptr;
}
void
setDescription(const string& name)
{
m_name = name;
}
bool isReady() const; bool isReady() const;
const Address& readyAddress() const; const Address& readyAddress() const;
@@ -66,8 +63,8 @@ public:
void set(const Address& address, Time relative_latency); void set(const Address& address, Time relative_latency);
void unset(const Address& address); void unset(const Address& address);
void print(ostream& out) const; void print(ostream& out) const;
private: private:
// Private Methods
void updateNext() const; void updateNext() const;
// Private copy constructor and assignment operator // Private copy constructor and assignment operator
@@ -86,11 +83,12 @@ private:
// ******************* Definitions ******************* // ******************* Definitions *******************
// Output operator definition // Output operator definition
extern inline inline ostream&
ostream& operator<<(ostream& out, const TimerTable& obj) operator<<(ostream& out, const TimerTable& obj)
{ {
obj.print(out); obj.print(out);
out << flush; out << flush;
return out; return out;
} }
#endif //TIMERTABLE_H
#endif // __MEM_RUBY_SYSTEM_TIMERTABLE_HH__