MessageBuffer.hh revision 10301
16145SN/A/* 26145SN/A * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood 36145SN/A * All rights reserved. 46145SN/A * 56145SN/A * Redistribution and use in source and binary forms, with or without 66145SN/A * modification, are permitted provided that the following conditions are 76145SN/A * met: redistributions of source code must retain the above copyright 86145SN/A * notice, this list of conditions and the following disclaimer; 96145SN/A * redistributions in binary form must reproduce the above copyright 106145SN/A * notice, this list of conditions and the following disclaimer in the 116145SN/A * documentation and/or other materials provided with the distribution; 126145SN/A * neither the name of the copyright holders nor the names of its 136145SN/A * contributors may be used to endorse or promote products derived from 146145SN/A * this software without specific prior written permission. 156145SN/A * 166145SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 176145SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 186145SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 196145SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 206145SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 216145SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 226145SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 236145SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 246145SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 256145SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 266145SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 276145SN/A */ 286145SN/A 296145SN/A/* 307039SN/A * Unordered buffer of messages that can be inserted such 316145SN/A * that they can be dequeued after a given delta time has expired. 326145SN/A */ 336145SN/A 347039SN/A#ifndef __MEM_RUBY_BUFFERS_MESSAGEBUFFER_HH__ 357039SN/A#define __MEM_RUBY_BUFFERS_MESSAGEBUFFER_HH__ 366145SN/A 377456SN/A#include <algorithm> 387832SN/A#include <cassert> 397456SN/A#include <functional> 407002SN/A#include <iostream> 418229SN/A#include <string> 427456SN/A#include <vector> 437002SN/A 448229SN/A#include "mem/ruby/common/Address.hh" 456154SN/A#include "mem/ruby/common/Consumer.hh" 4610301Snilay@cs.wisc.edu#include "mem/ruby/network/MessageBufferNode.hh" 476154SN/A#include "mem/ruby/slicc_interface/Message.hh" 4810301Snilay@cs.wisc.edu#include "mem/packet.hh" 496145SN/A 507039SN/Aclass MessageBuffer 517039SN/A{ 527039SN/A public: 537039SN/A MessageBuffer(const std::string &name = ""); 546145SN/A 558054SN/A std::string name() const { return m_name; } 568054SN/A 579499SN/A void setRecycleLatency(Cycles recycle_latency) 589499SN/A { m_recycle_latency = recycle_latency; } 596145SN/A 607567SN/A void reanalyzeMessages(const Address& addr); 617922SN/A void reanalyzeAllMessages(); 627567SN/A void stallMessage(const Address& addr); 637567SN/A 647039SN/A // TRUE if head of queue timestamp <= SystemTime 659302SN/A bool isReady() const; 666145SN/A 677039SN/A void 687039SN/A delayHead() 697039SN/A { 707456SN/A MessageBufferNode node = m_prio_heap.front(); 717456SN/A std::pop_heap(m_prio_heap.begin(), m_prio_heap.end(), 727456SN/A std::greater<MessageBufferNode>()); 737456SN/A m_prio_heap.pop_back(); 749499SN/A enqueue(node.m_msgptr, Cycles(1)); 757039SN/A } 766145SN/A 7710074SN/A bool areNSlotsAvailable(unsigned int n); 787039SN/A int getPriority() { return m_priority_rank; } 797039SN/A void setPriority(int rank) { m_priority_rank = rank; } 809602SN/A void setConsumer(Consumer* consumer) 817039SN/A { 829629SN/A if (m_consumer != NULL) { 839629SN/A fatal("Trying to connect %s to MessageBuffer %s. \ 849629SN/A \n%s already connected. Check the cntrl_id's.\n", 859629SN/A *consumer, *this, *m_consumer); 869629SN/A } 879602SN/A m_consumer = consumer; 887039SN/A } 896145SN/A 909508SN/A void setSender(ClockedObject* obj) 919465SN/A { 929602SN/A assert(m_sender == NULL || m_sender == obj); 939602SN/A m_sender = obj; 949508SN/A } 959508SN/A 969508SN/A void setReceiver(ClockedObject* obj) 979508SN/A { 989602SN/A assert(m_receiver == NULL || m_receiver == obj); 999602SN/A m_receiver = obj; 1009465SN/A } 1019465SN/A 1027039SN/A void setDescription(const std::string& name) { m_name = name; } 1037039SN/A std::string getDescription() { return m_name;} 1046863SN/A 1059602SN/A Consumer* getConsumer() { return m_consumer; } 1066145SN/A 10710074SN/A //! Function for extracting the message at the head of the 10810074SN/A //! message queue. The function assumes that the queue is nonempty. 10910074SN/A const Message* peek() const; 1106145SN/A 1117039SN/A const MsgPtr& 1127039SN/A peekMsgPtr() const 1137039SN/A { 1147039SN/A assert(isReady()); 1157456SN/A return m_prio_heap.front().m_msgptr; 1167039SN/A } 1176145SN/A 1189499SN/A void enqueue(MsgPtr message) { enqueue(message, Cycles(1)); } 1199499SN/A void enqueue(MsgPtr message, Cycles delta); 1209465SN/A 12110226SN/A //! Updates the delay cycles of the message at the head of the queue, 12210074SN/A //! removes it from the queue and returns its total delay. 12310226SN/A Cycles dequeue(); 12410074SN/A 1257039SN/A void recycle(); 1267039SN/A bool isEmpty() const { return m_prio_heap.size() == 0; } 1276145SN/A 1287039SN/A void 1297039SN/A setOrdering(bool order) 1307039SN/A { 1317039SN/A m_strict_fifo = order; 1327039SN/A m_ordering_set = true; 1337039SN/A } 13410074SN/A 13510096SN/A void resize(unsigned int size) { m_max_size = size; } 13610096SN/A unsigned int getSize(); 1377039SN/A void setRandomization(bool random_flag) { m_randomization = random_flag; } 1386145SN/A 1397039SN/A void clear(); 1407039SN/A void print(std::ostream& out) const; 1417039SN/A void clearStats() { m_not_avail_count = 0; m_msg_counter = 0; } 1426285SN/A 1437973SN/A void setIncomingLink(int link_id) { m_input_link_id = link_id; } 1447973SN/A void setVnet(int net) { m_vnet_id = net; } 1457973SN/A 1469302SN/A // Function for figuring out if any of the messages in the buffer can 1479302SN/A // satisfy the read request for the address in the packet. 1489302SN/A // Return value, if true, indicates that the request was fulfilled. 1499302SN/A bool functionalRead(Packet *pkt); 1509302SN/A 1519302SN/A // Function for figuring out if any of the messages in the buffer need 1529302SN/A // to be updated with the data from the packet. 1539302SN/A // Return value indicates the number of messages that were updated. 1549302SN/A // This required for debugging the code. 1559302SN/A uint32_t functionalWrite(Packet *pkt); 1569302SN/A 1577039SN/A private: 15810087SN/A void reanalyzeList(std::list<MsgPtr> &, Tick); 15910087SN/A 16010087SN/A private: 1617039SN/A //added by SS 1629499SN/A Cycles m_recycle_latency; 1636145SN/A 1647039SN/A // Data Members (m_ prefix) 1659508SN/A //! The two ends of the buffer. 1669602SN/A ClockedObject* m_sender; 1679602SN/A ClockedObject* m_receiver; 1689508SN/A 1699465SN/A //! Consumer to signal a wakeup(), can be NULL 1709602SN/A Consumer* m_consumer; 1717456SN/A std::vector<MessageBufferNode> m_prio_heap; 1729465SN/A 1738943SN/A // use a std::map for the stalled messages as this container is 1748943SN/A // sorted and ensures a well-defined iteration order 1758943SN/A typedef std::map< Address, std::list<MsgPtr> > StallMsgMapType; 1767567SN/A 1777567SN/A StallMsgMapType m_stall_msg_map; 1787039SN/A std::string m_name; 1796145SN/A 1809770SN/A unsigned int m_max_size; 1819503SN/A Cycles m_time_last_time_size_checked; 1829770SN/A unsigned int m_size_last_time_size_checked; 1836145SN/A 1847039SN/A // variables used so enqueues appear to happen imediately, while 1857039SN/A // pop happen the next cycle 1869503SN/A Cycles m_time_last_time_enqueue; 18710097SN/A Tick m_time_last_time_pop; 18810097SN/A Tick m_last_arrival_time; 18910097SN/A 1909770SN/A unsigned int m_size_at_cycle_start; 1919770SN/A unsigned int m_msgs_this_cycle; 1927039SN/A 1937039SN/A int m_not_avail_count; // count the # of times I didn't have N 1947039SN/A // slots available 1957566SN/A uint64 m_msg_counter; 1967039SN/A int m_priority_rank; 1977039SN/A bool m_strict_fifo; 1987039SN/A bool m_ordering_set; 1997039SN/A bool m_randomization; 2009499SN/A 2017973SN/A int m_input_link_id; 2027973SN/A int m_vnet_id; 2036145SN/A}; 2046145SN/A 2059554SN/ACycles random_time(); 2069554SN/A 2077039SN/Ainline std::ostream& 2087039SN/Aoperator<<(std::ostream& out, const MessageBuffer& obj) 2096145SN/A{ 2107039SN/A obj.print(out); 2117039SN/A out << std::flush; 2127039SN/A return out; 2136145SN/A} 2146145SN/A 2157039SN/A#endif // __MEM_RUBY_BUFFERS_MESSAGEBUFFER_HH__ 216