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()); + m_prio_heap.push_back(message); + push_heap(m_prio_heap.begin(), m_prio_heap.end(), greater()); 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()); + greater()); 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()); + MsgPtr node = m_prio_heap.front(); + pop_heap(m_prio_heap.begin(), m_prio_heap.end(), greater()); - 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()); + push_heap(m_prio_heap.begin(), m_prio_heap.end(), greater()); m_consumer-> scheduleEventAbsolute(m_receiver->clockEdge(m_recycle_latency)); } @@ -282,11 +279,13 @@ MessageBuffer::reanalyzeList(list <, 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()); + greater()); 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 copy(m_prio_heap); - sort_heap(copy.begin(), copy.end(), greater()); + vector copy(m_prio_heap); + sort_heap(copy.begin(), copy.end(), greater()); 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()); + std::greater()); 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 m_prio_heap; + std::vector 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 - -#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()); + greater()); 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()); + MsgPtr node = m_message_queue.front(); + pop_heap(m_message_queue.begin(), m_message_queue.end(), greater()); - 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()); + greater()); 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 #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 m_message_queue; + std::vector m_message_queue; };