summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNilay Vaish <nilay@cs.wisc.edu>2015-07-04 10:43:46 -0500
committerNilay Vaish <nilay@cs.wisc.edu>2015-07-04 10:43:46 -0500
commitb4efb48a71c42085134e57840aa9562884404d11 (patch)
tree0626bf3d54745737f3553fcf0a6a931813e441e6
parent25e1b1c1f5f4e0ad3976c88998161700135f4aae (diff)
downloadgem5-b4efb48a71c42085134e57840aa9562884404d11.tar.xz
ruby: remove message buffer node
This structure's only purpose was to provide a comparison function for ordering messages in the MessageBuffer. The comparison function is now being moved to the Message class itself. So we no longer require this structure.
-rw-r--r--src/mem/ruby/network/MessageBuffer.cc43
-rw-r--r--src/mem/ruby/network/MessageBuffer.hh11
-rw-r--r--src/mem/ruby/network/MessageBufferNode.cc39
-rw-r--r--src/mem/ruby/network/MessageBufferNode.hh75
-rw-r--r--src/mem/ruby/network/SConscript1
-rw-r--r--src/mem/ruby/slicc_interface/Message.hh26
-rw-r--r--src/mem/ruby/structures/WireBuffer.cc33
-rw-r--r--src/mem/ruby/structures/WireBuffer.hh5
8 files changed, 60 insertions, 173 deletions
diff --git a/src/mem/ruby/network/MessageBuffer.cc b/src/mem/ruby/network/MessageBuffer.cc
index 99879a1b6..7353c51c5 100644
--- a/src/mem/ruby/network/MessageBuffer.cc
+++ b/src/mem/ruby/network/MessageBuffer.cc
@@ -122,7 +122,7 @@ MessageBuffer::peek() const
DPRINTF(RubyQueue, "Peeking at head of queue.\n");
assert(isReady());
- const Message* msg_ptr = m_prio_heap.front().m_msgptr.get();
+ const Message* msg_ptr = m_prio_heap.front().get();
assert(msg_ptr);
DPRINTF(RubyQueue, "Message: %s\n", (*msg_ptr));
@@ -204,12 +204,11 @@ MessageBuffer::enqueue(MsgPtr message, Cycles delta)
msg_ptr->updateDelayedTicks(m_sender->clockEdge());
msg_ptr->setLastEnqueueTime(arrival_time);
+ msg_ptr->setMsgCounter(m_msg_counter);
// Insert the message into the priority heap
- MessageBufferNode thisNode(arrival_time, m_msg_counter, message);
- m_prio_heap.push_back(thisNode);
- push_heap(m_prio_heap.begin(), m_prio_heap.end(),
- greater<MessageBufferNode>());
+ m_prio_heap.push_back(message);
+ push_heap(m_prio_heap.begin(), m_prio_heap.end(), greater<MsgPtr>());
DPRINTF(RubyQueue, "Enqueue arrival_time: %lld, Message: %s\n",
arrival_time, *(message.get()));
@@ -227,7 +226,7 @@ MessageBuffer::dequeue()
assert(isReady());
// get MsgPtr of the message about to be dequeued
- MsgPtr message = m_prio_heap.front().m_msgptr;
+ MsgPtr message = m_prio_heap.front();
// get the delay cycles
message->updateDelayedTicks(m_receiver->clockEdge());
@@ -242,7 +241,7 @@ MessageBuffer::dequeue()
}
pop_heap(m_prio_heap.begin(), m_prio_heap.end(),
- greater<MessageBufferNode>());
+ greater<MsgPtr>());
m_prio_heap.pop_back();
return delayCycles;
@@ -265,14 +264,12 @@ MessageBuffer::recycle()
{
DPRINTF(RubyQueue, "Recycling.\n");
assert(isReady());
- MessageBufferNode node = m_prio_heap.front();
- pop_heap(m_prio_heap.begin(), m_prio_heap.end(),
- greater<MessageBufferNode>());
+ MsgPtr node = m_prio_heap.front();
+ pop_heap(m_prio_heap.begin(), m_prio_heap.end(), greater<MsgPtr>());
- node.m_time = m_receiver->clockEdge(m_recycle_latency);
+ node->setLastEnqueueTime(m_receiver->clockEdge(m_recycle_latency));
m_prio_heap.back() = node;
- push_heap(m_prio_heap.begin(), m_prio_heap.end(),
- greater<MessageBufferNode>());
+ push_heap(m_prio_heap.begin(), m_prio_heap.end(), greater<MsgPtr>());
m_consumer->
scheduleEventAbsolute(m_receiver->clockEdge(m_recycle_latency));
}
@@ -282,11 +279,13 @@ MessageBuffer::reanalyzeList(list<MsgPtr> &lt, Tick nextTick)
{
while(!lt.empty()) {
m_msg_counter++;
- MessageBufferNode msgNode(nextTick, m_msg_counter, lt.front());
+ MsgPtr m = lt.front();
+ m->setLastEnqueueTime(nextTick);
+ m->setMsgCounter(m_msg_counter);
- m_prio_heap.push_back(msgNode);
+ m_prio_heap.push_back(m);
push_heap(m_prio_heap.begin(), m_prio_heap.end(),
- greater<MessageBufferNode>());
+ greater<MsgPtr>());
m_consumer->scheduleEventAbsolute(nextTick);
lt.pop_front();
@@ -331,7 +330,7 @@ MessageBuffer::stallMessage(const Address& addr)
DPRINTF(RubyQueue, "Stalling due to %s\n", addr);
assert(isReady());
assert(addr.getOffset() == 0);
- MsgPtr message = m_prio_heap.front().m_msgptr;
+ MsgPtr message = m_prio_heap.front();
dequeue();
@@ -351,8 +350,8 @@ MessageBuffer::print(ostream& out) const
ccprintf(out, " consumer-yes ");
}
- vector<MessageBufferNode> copy(m_prio_heap);
- sort_heap(copy.begin(), copy.end(), greater<MessageBufferNode>());
+ vector<MsgPtr> copy(m_prio_heap);
+ sort_heap(copy.begin(), copy.end(), greater<MsgPtr>());
ccprintf(out, "%s] %s", copy, m_name);
}
@@ -360,7 +359,7 @@ bool
MessageBuffer::isReady() const
{
return ((m_prio_heap.size() > 0) &&
- (m_prio_heap.front().m_time <= m_receiver->clockEdge()));
+ (m_prio_heap.front()->getLastEnqueueTime() <= m_receiver->clockEdge()));
}
bool
@@ -369,7 +368,7 @@ MessageBuffer::functionalRead(Packet *pkt)
// Check the priority heap and read any messages that may
// correspond to the address in the packet.
for (unsigned int i = 0; i < m_prio_heap.size(); ++i) {
- Message *msg = m_prio_heap[i].m_msgptr.get();
+ Message *msg = m_prio_heap[i].get();
if (msg->functionalRead(pkt)) return true;
}
@@ -397,7 +396,7 @@ MessageBuffer::functionalWrite(Packet *pkt)
// Check the priority heap and write any messages that may
// correspond to the address in the packet.
for (unsigned int i = 0; i < m_prio_heap.size(); ++i) {
- Message *msg = m_prio_heap[i].m_msgptr.get();
+ Message *msg = m_prio_heap[i].get();
if (msg->functionalWrite(pkt)) {
num_functional_writes++;
}
diff --git a/src/mem/ruby/network/MessageBuffer.hh b/src/mem/ruby/network/MessageBuffer.hh
index 6d51eade9..b5d2b9eca 100644
--- a/src/mem/ruby/network/MessageBuffer.hh
+++ b/src/mem/ruby/network/MessageBuffer.hh
@@ -43,7 +43,6 @@
#include "mem/ruby/common/Address.hh"
#include "mem/ruby/common/Consumer.hh"
-#include "mem/ruby/network/MessageBufferNode.hh"
#include "mem/ruby/slicc_interface/Message.hh"
#include "mem/packet.hh"
@@ -67,11 +66,11 @@ class MessageBuffer
void
delayHead()
{
- MessageBufferNode node = m_prio_heap.front();
+ MsgPtr m = m_prio_heap.front();
std::pop_heap(m_prio_heap.begin(), m_prio_heap.end(),
- std::greater<MessageBufferNode>());
+ std::greater<MsgPtr>());
m_prio_heap.pop_back();
- enqueue(node.m_msgptr, Cycles(1));
+ enqueue(m, Cycles(1));
}
bool areNSlotsAvailable(unsigned int n);
@@ -112,7 +111,7 @@ class MessageBuffer
peekMsgPtr() const
{
assert(isReady());
- return m_prio_heap.front().m_msgptr;
+ return m_prio_heap.front();
}
void enqueue(MsgPtr message) { enqueue(message, Cycles(1)); }
@@ -168,7 +167,7 @@ class MessageBuffer
//! Consumer to signal a wakeup(), can be NULL
Consumer* m_consumer;
- std::vector<MessageBufferNode> m_prio_heap;
+ std::vector<MsgPtr> m_prio_heap;
// use a std::map for the stalled messages as this container is
// sorted and ensures a well-defined iteration order
diff --git a/src/mem/ruby/network/MessageBufferNode.cc b/src/mem/ruby/network/MessageBufferNode.cc
deleted file mode 100644
index 2e682b096..000000000
--- a/src/mem/ruby/network/MessageBufferNode.cc
+++ /dev/null
@@ -1,39 +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.
- */
-
-#include "mem/ruby/network/MessageBufferNode.hh"
-
-void
-MessageBufferNode::print(std::ostream& out) const
-{
- out << "[";
- out << m_time << ", ";
- out << m_msg_counter << ", ";
- out << *m_msgptr << "; ";
- out << "]";
-}
diff --git a/src/mem/ruby/network/MessageBufferNode.hh b/src/mem/ruby/network/MessageBufferNode.hh
deleted file mode 100644
index 16aec8a1b..000000000
--- a/src/mem/ruby/network/MessageBufferNode.hh
+++ /dev/null
@@ -1,75 +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.
- */
-
-#ifndef __MEM_RUBY_BUFFERS_MESSAGEBUFFERNODE_HH__
-#define __MEM_RUBY_BUFFERS_MESSAGEBUFFERNODE_HH__
-
-#include <iostream>
-
-#include "mem/ruby/slicc_interface/Message.hh"
-
-class MessageBufferNode
-{
- public:
- MessageBufferNode()
- : m_time(0), m_msg_counter(0)
- {}
-
- MessageBufferNode(const Tick time, uint64_t counter,
- const MsgPtr& msgptr)
- : m_time(time), m_msg_counter(counter), m_msgptr(msgptr)
- {}
-
- void print(std::ostream& out) const;
-
- public:
- Tick m_time;
- uint64_t m_msg_counter; // FIXME, should this be a 64-bit value?
- MsgPtr m_msgptr;
-};
-
-inline bool
-operator>(const MessageBufferNode& n1, const MessageBufferNode& n2)
-{
- if (n1.m_time == n2.m_time) {
- assert(n1.m_msg_counter != n2.m_msg_counter);
- return n1.m_msg_counter > n2.m_msg_counter;
- } else {
- return n1.m_time > n2.m_time;
- }
-}
-
-inline std::ostream&
-operator<<(std::ostream& out, const MessageBufferNode& obj)
-{
- obj.print(out);
- out << std::flush;
- return out;
-}
-
-#endif // __MEM_RUBY_BUFFERS_MESSAGEBUFFERNODE_HH__
diff --git a/src/mem/ruby/network/SConscript b/src/mem/ruby/network/SConscript
index 1b0b1c94b..282d47647 100644
--- a/src/mem/ruby/network/SConscript
+++ b/src/mem/ruby/network/SConscript
@@ -40,6 +40,5 @@ SimObject('Network.py')
Source('BasicLink.cc')
Source('BasicRouter.cc')
Source('MessageBuffer.cc')
-Source('MessageBufferNode.cc')
Source('Network.cc')
Source('Topology.cc')
diff --git a/src/mem/ruby/slicc_interface/Message.hh b/src/mem/ruby/slicc_interface/Message.hh
index fb60c3ca9..ea33c1340 100644
--- a/src/mem/ruby/slicc_interface/Message.hh
+++ b/src/mem/ruby/slicc_interface/Message.hh
@@ -44,13 +44,14 @@ class Message
Message(Tick curTime)
: m_time(curTime),
m_LastEnqueueTime(curTime),
- m_DelayedTicks(0)
+ m_DelayedTicks(0), m_msg_counter(0)
{ }
Message(const Message &other)
: m_time(other.m_time),
m_LastEnqueueTime(other.m_LastEnqueueTime),
- m_DelayedTicks(other.m_DelayedTicks)
+ m_DelayedTicks(other.m_DelayedTicks),
+ m_msg_counter(other.m_msg_counter)
{ }
virtual ~Message() { }
@@ -68,9 +69,7 @@ class Message
* implement these methods.
*/
virtual bool functionalRead(Packet *pkt) = 0;
- //{ fatal("Read functional access not implemented!"); }
virtual bool functionalWrite(Packet *pkt) = 0;
- //{ fatal("Write functional access not implemented!"); }
//! Update the delay this message has experienced so far.
void updateDelayedTicks(Tick curTime)
@@ -85,14 +84,29 @@ class Message
const Tick getLastEnqueueTime() const {return m_LastEnqueueTime;}
const Tick& getTime() const { return m_time; }
- void setTime(const Tick& new_time) { m_time = new_time; }
+ void setMsgCounter(uint64_t c) { m_msg_counter = c; }
+ uint64_t getMsgCounter() const { return m_msg_counter; }
private:
- Tick m_time;
+ const Tick m_time;
Tick m_LastEnqueueTime; // my last enqueue time
Tick m_DelayedTicks; // my delayed cycles
+ uint64_t m_msg_counter; // FIXME, should this be a 64-bit value?
};
+inline bool
+operator>(const MsgPtr &lhs, const MsgPtr &rhs)
+{
+ const Message *l = lhs.get();
+ const Message *r = rhs.get();
+
+ if (l->getLastEnqueueTime() == r->getLastEnqueueTime()) {
+ assert(l->getMsgCounter() != r->getMsgCounter());
+ return l->getMsgCounter() > r->getMsgCounter();
+ }
+ return l->getLastEnqueueTime() > r->getLastEnqueueTime();
+}
+
inline std::ostream&
operator<<(std::ostream& out, const Message& obj)
{
diff --git a/src/mem/ruby/structures/WireBuffer.cc b/src/mem/ruby/structures/WireBuffer.cc
index 702a53f16..3308dbe8e 100644
--- a/src/mem/ruby/structures/WireBuffer.cc
+++ b/src/mem/ruby/structures/WireBuffer.cc
@@ -77,8 +77,9 @@ WireBuffer::enqueue(MsgPtr message, Cycles latency)
Cycles arrival_time = current_time + latency;
assert(arrival_time > current_time);
- MessageBufferNode thisNode(arrival_time, m_msg_counter, message);
- m_message_queue.push_back(thisNode);
+ Message* msg_ptr = message.get();
+ msg_ptr->setLastEnqueueTime(arrival_time);
+ m_message_queue.push_back(message);
if (m_consumer_ptr != NULL) {
m_consumer_ptr->
scheduleEventAbsolute(g_system_ptr->clockPeriod() * arrival_time);
@@ -92,27 +93,18 @@ WireBuffer::dequeue()
{
assert(isReady());
pop_heap(m_message_queue.begin(), m_message_queue.end(),
- greater<MessageBufferNode>());
+ greater<MsgPtr>());
m_message_queue.pop_back();
}
const Message*
WireBuffer::peek()
{
- MessageBufferNode node = peekNode();
- Message* msg_ptr = node.m_msgptr.get();
+ Message* msg_ptr = m_message_queue.front().get();
assert(msg_ptr != NULL);
return msg_ptr;
}
-MessageBufferNode
-WireBuffer::peekNode()
-{
- assert(isReady());
- MessageBufferNode req = m_message_queue.front();
- return req;
-}
-
void
WireBuffer::recycle()
{
@@ -121,23 +113,23 @@ WireBuffer::recycle()
// Wire-like situations because you don't want to deadlock as a result of
// being stuck behind something if you're not actually supposed to.
assert(isReady());
- MessageBufferNode node = m_message_queue.front();
- pop_heap(m_message_queue.begin(), m_message_queue.end(),
- greater<MessageBufferNode>());
+ MsgPtr node = m_message_queue.front();
+ pop_heap(m_message_queue.begin(), m_message_queue.end(), greater<MsgPtr>());
- node.m_time = g_system_ptr->curCycle() + Cycles(1);
+ node->setLastEnqueueTime(g_system_ptr->curCycle() + Cycles(1));
m_message_queue.back() = node;
push_heap(m_message_queue.begin(), m_message_queue.end(),
- greater<MessageBufferNode>());
+ greater<MsgPtr>());
m_consumer_ptr->
- scheduleEventAbsolute(g_system_ptr->clockPeriod() * node.m_time);
+ scheduleEventAbsolute(g_system_ptr->curCycle() + Cycles(1));
}
bool
WireBuffer::isReady()
{
return ((!m_message_queue.empty()) &&
- (m_message_queue.front().m_time <= g_system_ptr->curCycle()));
+ (m_message_queue.front()->getLastEnqueueTime() <=
+ g_system_ptr->curCycle()));
}
void
@@ -155,4 +147,3 @@ RubyWireBufferParams::create()
{
return new WireBuffer(this);
}
-
diff --git a/src/mem/ruby/structures/WireBuffer.hh b/src/mem/ruby/structures/WireBuffer.hh
index a362d524e..a724f1381 100644
--- a/src/mem/ruby/structures/WireBuffer.hh
+++ b/src/mem/ruby/structures/WireBuffer.hh
@@ -37,7 +37,7 @@
#include <vector>
#include "mem/ruby/common/Consumer.hh"
-#include "mem/ruby/network/MessageBufferNode.hh"
+#include "mem/ruby/slicc_interface/Message.hh"
#include "params/RubyWireBuffer.hh"
#include "sim/sim_object.hh"
@@ -75,7 +75,6 @@ class WireBuffer : public SimObject
void enqueue(MsgPtr message, Cycles latency);
void dequeue();
const Message* peek();
- MessageBufferNode peekNode();
void recycle();
bool isReady();
bool areNSlotsAvailable(int n) { return true; }; // infinite queue length
@@ -93,7 +92,7 @@ class WireBuffer : public SimObject
std::string m_description;
// queues where memory requests live
- std::vector<MessageBufferNode> m_message_queue;
+ std::vector<MsgPtr> m_message_queue;
};