ruby: style pass
This commit is contained in:
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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__
|
||||||
|
|||||||
@@ -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.
|
||||||
|
|||||||
@@ -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__
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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__
|
||||||
|
|
||||||
|
|||||||
@@ -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__
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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__
|
||||||
|
|||||||
@@ -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()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -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__
|
||||||
|
|
||||||
|
|||||||
@@ -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);
|
||||||
|
}
|
||||||
|
|||||||
@@ -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__
|
||||||
|
|||||||
@@ -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.
|
||||||
|
|||||||
@@ -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
|
|
||||||
|
|
||||||
|
|||||||
@@ -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());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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__
|
||||||
|
|||||||
@@ -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"
|
|
||||||
@@ -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() << ") ";
|
||||||
|
|
||||||
|
|||||||
@@ -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__
|
||||||
|
|
||||||
|
|||||||
@@ -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')
|
||||||
|
|||||||
@@ -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 << "]";
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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__
|
||||||
|
|||||||
@@ -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
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -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__
|
||||||
|
|||||||
@@ -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) {
|
||||||
|
|||||||
@@ -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__
|
||||||
|
|||||||
@@ -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
|
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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
|
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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
|
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
@@ -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
|
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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__
|
||||||
|
|||||||
@@ -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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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__
|
||||||
|
|||||||
@@ -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__
|
||||||
|
|||||||
@@ -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() {
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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__
|
||||||
|
|
||||||
|
|||||||
@@ -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__
|
||||||
|
|||||||
@@ -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()
|
||||||
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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__
|
||||||
|
|
||||||
|
|||||||
@@ -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__
|
||||||
|
|
||||||
|
|||||||
@@ -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__
|
||||||
|
|||||||
@@ -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__
|
||||||
|
|||||||
@@ -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"
|
||||||
|
|
||||||
|
|||||||
@@ -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__
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -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__
|
||||||
|
|||||||
@@ -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__
|
||||||
|
|||||||
@@ -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__
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
|
||||||
|
|
||||||
|
|||||||
@@ -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__
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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__
|
||||||
|
|
||||||
|
|||||||
@@ -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()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -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__
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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__
|
||||||
|
|||||||
@@ -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__
|
||||||
|
|||||||
@@ -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
|
|
||||||
|
|||||||
@@ -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();
|
||||||
|
|
||||||
|
|||||||
@@ -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__
|
||||||
|
|
||||||
|
|||||||
@@ -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 << ", ";
|
||||||
|
|||||||
@@ -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__
|
||||||
|
|||||||
@@ -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__
|
||||||
|
|||||||
@@ -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__
|
||||||
|
|||||||
@@ -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__
|
||||||
|
|||||||
@@ -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
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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__
|
||||||
|
|||||||
@@ -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__
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|
||||||
|
|||||||
@@ -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__
|
||||||
|
|||||||
@@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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__
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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
|
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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__
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -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__
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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__
|
||||||
|
|||||||
Reference in New Issue
Block a user