MessageBuffer.hh revision 11061:25b53a7195f7
11060SN/A/* 29814Sandreas.hansson@arm.com * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood 39920Syasuko.eckert@amd.com * All rights reserved. 47944SGiacomo.Gabrielli@arm.com * 57944SGiacomo.Gabrielli@arm.com * Redistribution and use in source and binary forms, with or without 67944SGiacomo.Gabrielli@arm.com * modification, are permitted provided that the following conditions are 77944SGiacomo.Gabrielli@arm.com * met: redistributions of source code must retain the above copyright 87944SGiacomo.Gabrielli@arm.com * notice, this list of conditions and the following disclaimer; 97944SGiacomo.Gabrielli@arm.com * redistributions in binary form must reproduce the above copyright 107944SGiacomo.Gabrielli@arm.com * notice, this list of conditions and the following disclaimer in the 117944SGiacomo.Gabrielli@arm.com * documentation and/or other materials provided with the distribution; 127944SGiacomo.Gabrielli@arm.com * neither the name of the copyright holders nor the names of its 137944SGiacomo.Gabrielli@arm.com * contributors may be used to endorse or promote products derived from 147944SGiacomo.Gabrielli@arm.com * this software without specific prior written permission. 152702Sktlim@umich.edu * 166973Stjones1@inf.ed.ac.uk * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 171060SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 181060SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 191060SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 201060SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 211060SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 221060SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 231060SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 241060SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 251060SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 261060SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 271060SN/A */ 281060SN/A 291060SN/A/* 301060SN/A * Unordered buffer of messages that can be inserted such 311060SN/A * that they can be dequeued after a given delta time has expired. 321060SN/A */ 331060SN/A 341060SN/A#ifndef __MEM_RUBY_BUFFERS_MESSAGEBUFFER_HH__ 351060SN/A#define __MEM_RUBY_BUFFERS_MESSAGEBUFFER_HH__ 361060SN/A 371060SN/A#include <algorithm> 381060SN/A#include <cassert> 391060SN/A#include <functional> 401060SN/A#include <iostream> 412665Ssaidi@eecs.umich.edu#include <string> 422665Ssaidi@eecs.umich.edu#include <vector> 436973Stjones1@inf.ed.ac.uk 441060SN/A#include "debug/RubyQueue.hh" 451060SN/A#include "mem/ruby/common/Address.hh" 461464SN/A#include "mem/ruby/common/Consumer.hh" 471464SN/A#include "mem/ruby/slicc_interface/Message.hh" 481060SN/A#include "mem/packet.hh" 4910835Sandreas.hansson@arm.com#include "params/MessageBuffer.hh" 502731Sktlim@umich.edu#include "sim/sim_object.hh" 512292SN/A 521464SN/Aclass MessageBuffer : public SimObject 538733Sgeoffrey.blake@arm.com{ 541060SN/A public: 5510687SAndreas.Sandberg@ARM.com typedef MessageBufferParams Params; 567720Sgblack@eecs.umich.edu MessageBuffer(const Params *p); 571060SN/A 586658Snate@binkert.org void reanalyzeMessages(Addr addr); 598887Sgeoffrey.blake@arm.com void reanalyzeAllMessages(); 603770Sgblack@eecs.umich.edu void stallMessage(Addr addr); 6110319SAndreas.Sandberg@ARM.com 621464SN/A // TRUE if head of queue timestamp <= SystemTime 631464SN/A bool isReady() const; 642669Sktlim@umich.edu 651060SN/A void 666973Stjones1@inf.ed.ac.uk delayHead() 672669Sktlim@umich.edu { 6811608Snikos.nikoleris@arm.com MsgPtr m = m_prio_heap.front(); 697678Sgblack@eecs.umich.edu std::pop_heap(m_prio_heap.begin(), m_prio_heap.end(), 702292SN/A std::greater<MsgPtr>()); 711060SN/A m_prio_heap.pop_back(); 721060SN/A enqueue(m, Cycles(1)); 731060SN/A } 741060SN/A 751060SN/A bool areNSlotsAvailable(unsigned int n); 761060SN/A int getPriority() { return m_priority_rank; } 771060SN/A void setPriority(int rank) { m_priority_rank = rank; } 7810319SAndreas.Sandberg@ARM.com void setConsumer(Consumer* consumer) 791060SN/A { 801060SN/A DPRINTF(RubyQueue, "Setting consumer: %s\n", *consumer); 811060SN/A if (m_consumer != NULL) { 822733Sktlim@umich.edu fatal("Trying to connect %s to MessageBuffer %s. \ 832733Sktlim@umich.edu \n%s already connected. Check the cntrl_id's.\n", 841060SN/A *consumer, *this, *m_consumer); 852292SN/A } 862292SN/A m_consumer = consumer; 878486Sgblack@eecs.umich.edu } 882292SN/A 892292SN/A void setSender(ClockedObject* obj) 902292SN/A { 912292SN/A DPRINTF(RubyQueue, "Setting sender: %s\n", obj->name()); 921060SN/A assert(m_sender == NULL || m_sender == obj); 935543Ssaidi@eecs.umich.edu m_sender = obj; 948902Sandreas.hansson@arm.com } 951060SN/A 961060SN/A void setReceiver(ClockedObject* obj) 979046SAli.Saidi@ARM.com { 989046SAli.Saidi@ARM.com DPRINTF(RubyQueue, "Setting receiver: %s\n", obj->name()); 999046SAli.Saidi@ARM.com assert(m_receiver == NULL || m_receiver == obj); 1009046SAli.Saidi@ARM.com m_receiver = obj; 1019046SAli.Saidi@ARM.com } 1029046SAli.Saidi@ARM.com 1039046SAli.Saidi@ARM.com Consumer* getConsumer() { return m_consumer; } 1049046SAli.Saidi@ARM.com 1059046SAli.Saidi@ARM.com bool getOrdered() { return m_strict_fifo; } 1069046SAli.Saidi@ARM.com 1079046SAli.Saidi@ARM.com //! Function for extracting the message at the head of the 1089046SAli.Saidi@ARM.com //! message queue. The function assumes that the queue is nonempty. 1099046SAli.Saidi@ARM.com const Message* peek() const; 1109046SAli.Saidi@ARM.com 1119046SAli.Saidi@ARM.com const MsgPtr& 1129046SAli.Saidi@ARM.com peekMsgPtr() const 1139046SAli.Saidi@ARM.com { 1149046SAli.Saidi@ARM.com assert(isReady()); 1159046SAli.Saidi@ARM.com return m_prio_heap.front(); 1169046SAli.Saidi@ARM.com } 1179046SAli.Saidi@ARM.com 1189046SAli.Saidi@ARM.com void enqueue(MsgPtr message) { enqueue(message, Cycles(1)); } 1199046SAli.Saidi@ARM.com void enqueue(MsgPtr message, Cycles delta); 1209046SAli.Saidi@ARM.com 1219046SAli.Saidi@ARM.com //! Updates the delay cycles of the message at the head of the queue, 1229046SAli.Saidi@ARM.com //! removes it from the queue and returns its total delay. 1239046SAli.Saidi@ARM.com Cycles dequeue(); 1249046SAli.Saidi@ARM.com 1259046SAli.Saidi@ARM.com void recycle(); 1269046SAli.Saidi@ARM.com bool isEmpty() const { return m_prio_heap.size() == 0; } 1279046SAli.Saidi@ARM.com bool isStallMapEmpty() { return m_stall_msg_map.size() == 0; } 1289046SAli.Saidi@ARM.com unsigned int getStallMapSize() { return m_stall_msg_map.size(); } 1299046SAli.Saidi@ARM.com 1309046SAli.Saidi@ARM.com unsigned int getSize(); 1319046SAli.Saidi@ARM.com 1329046SAli.Saidi@ARM.com void clear(); 1339046SAli.Saidi@ARM.com void print(std::ostream& out) const; 1349046SAli.Saidi@ARM.com void clearStats() { m_not_avail_count = 0; m_msg_counter = 0; } 1359046SAli.Saidi@ARM.com 1369046SAli.Saidi@ARM.com void setIncomingLink(int link_id) { m_input_link_id = link_id; } 1379046SAli.Saidi@ARM.com void setVnet(int net) { m_vnet_id = net; } 1389046SAli.Saidi@ARM.com 1399046SAli.Saidi@ARM.com // Function for figuring out if any of the messages in the buffer can 1409046SAli.Saidi@ARM.com // satisfy the read request for the address in the packet. 1419046SAli.Saidi@ARM.com // Return value, if true, indicates that the request was fulfilled. 1429046SAli.Saidi@ARM.com bool functionalRead(Packet *pkt); 1439046SAli.Saidi@ARM.com 1449046SAli.Saidi@ARM.com // Function for figuring out if any of the messages in the buffer need 1459046SAli.Saidi@ARM.com // to be updated with the data from the packet. 14610824SAndreas.Sandberg@ARM.com // Return value indicates the number of messages that were updated. 1479046SAli.Saidi@ARM.com // This required for debugging the code. 1489046SAli.Saidi@ARM.com uint32_t functionalWrite(Packet *pkt); 1499046SAli.Saidi@ARM.com 1509046SAli.Saidi@ARM.com private: 1519046SAli.Saidi@ARM.com //added by SS 1529046SAli.Saidi@ARM.com const Cycles m_recycle_latency; 1539046SAli.Saidi@ARM.com 1549046SAli.Saidi@ARM.com void reanalyzeList(std::list<MsgPtr> &, Tick); 1559046SAli.Saidi@ARM.com 1562292SN/A private: 15710417Sandreas.hansson@arm.com // Data Members (m_ prefix) 1589046SAli.Saidi@ARM.com //! The two ends of the buffer. 1599046SAli.Saidi@ARM.com ClockedObject* m_sender; 1609046SAli.Saidi@ARM.com ClockedObject* m_receiver; 1619046SAli.Saidi@ARM.com 16210030SAli.Saidi@ARM.com //! Consumer to signal a wakeup(), can be NULL 16310030SAli.Saidi@ARM.com Consumer* m_consumer; 1649046SAli.Saidi@ARM.com std::vector<MsgPtr> m_prio_heap; 1659046SAli.Saidi@ARM.com 1669046SAli.Saidi@ARM.com // use a std::map for the stalled messages as this container is 1679046SAli.Saidi@ARM.com // sorted and ensures a well-defined iteration order 1689046SAli.Saidi@ARM.com typedef std::map<Addr, std::list<MsgPtr> > StallMsgMapType; 1699046SAli.Saidi@ARM.com 1709046SAli.Saidi@ARM.com StallMsgMapType m_stall_msg_map; 1719046SAli.Saidi@ARM.com 1729046SAli.Saidi@ARM.com const unsigned int m_max_size; 1739046SAli.Saidi@ARM.com Cycles m_time_last_time_size_checked; 1749046SAli.Saidi@ARM.com unsigned int m_size_last_time_size_checked; 1759046SAli.Saidi@ARM.com 1769046SAli.Saidi@ARM.com // variables used so enqueues appear to happen immediately, while 1779046SAli.Saidi@ARM.com // pop happen the next cycle 1789046SAli.Saidi@ARM.com Cycles m_time_last_time_enqueue; 1799046SAli.Saidi@ARM.com Tick m_time_last_time_pop; 1809046SAli.Saidi@ARM.com Tick m_last_arrival_time; 1819046SAli.Saidi@ARM.com 1829046SAli.Saidi@ARM.com unsigned int m_size_at_cycle_start; 1839046SAli.Saidi@ARM.com unsigned int m_msgs_this_cycle; 1849046SAli.Saidi@ARM.com 1859046SAli.Saidi@ARM.com int m_not_avail_count; // count the # of times I didn't have N 1869046SAli.Saidi@ARM.com // slots available 1879046SAli.Saidi@ARM.com uint64_t m_msg_counter; 1889046SAli.Saidi@ARM.com int m_priority_rank; 1899046SAli.Saidi@ARM.com const bool m_strict_fifo; 1909046SAli.Saidi@ARM.com const bool m_randomization; 1919046SAli.Saidi@ARM.com 1929046SAli.Saidi@ARM.com int m_input_link_id; 1939046SAli.Saidi@ARM.com int m_vnet_id; 1949046SAli.Saidi@ARM.com}; 1959046SAli.Saidi@ARM.com 1969046SAli.Saidi@ARM.comCycles random_time(); 1979046SAli.Saidi@ARM.com 1989046SAli.Saidi@ARM.cominline std::ostream& 1999046SAli.Saidi@ARM.comoperator<<(std::ostream& out, const MessageBuffer& obj) 2009046SAli.Saidi@ARM.com{ 2019046SAli.Saidi@ARM.com obj.print(out); 2029046SAli.Saidi@ARM.com out << std::flush; 2039046SAli.Saidi@ARM.com return out; 2049046SAli.Saidi@ARM.com} 20510417Sandreas.hansson@arm.com 2061060SN/A#endif // __MEM_RUBY_BUFFERS_MESSAGEBUFFER_HH__ 2079046SAli.Saidi@ARM.com