MessageBuffer.hh revision 11061
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
4411021Sjthestness@gmail.com#include "debug/RubyQueue.hh"
458229SN/A#include "mem/ruby/common/Address.hh"
466154SN/A#include "mem/ruby/common/Consumer.hh"
476154SN/A#include "mem/ruby/slicc_interface/Message.hh"
4810301Snilay@cs.wisc.edu#include "mem/packet.hh"
4911021Sjthestness@gmail.com#include "params/MessageBuffer.hh"
5011021Sjthestness@gmail.com#include "sim/sim_object.hh"
516145SN/A
5211021Sjthestness@gmail.comclass MessageBuffer : public SimObject
537039SN/A{
547039SN/A  public:
5511021Sjthestness@gmail.com    typedef MessageBufferParams Params;
5611021Sjthestness@gmail.com    MessageBuffer(const Params *p);
576145SN/A
5811025Snilay@cs.wisc.edu    void reanalyzeMessages(Addr addr);
597922SN/A    void reanalyzeAllMessages();
6011025Snilay@cs.wisc.edu    void stallMessage(Addr addr);
617567SN/A
627039SN/A    // TRUE if head of queue timestamp <= SystemTime
639302SN/A    bool isReady() const;
646145SN/A
657039SN/A    void
667039SN/A    delayHead()
677039SN/A    {
6810893Snilay@cs.wisc.edu        MsgPtr m = m_prio_heap.front();
697456SN/A        std::pop_heap(m_prio_heap.begin(), m_prio_heap.end(),
7010893Snilay@cs.wisc.edu                      std::greater<MsgPtr>());
717456SN/A        m_prio_heap.pop_back();
7210893Snilay@cs.wisc.edu        enqueue(m, Cycles(1));
737039SN/A    }
746145SN/A
7510074SN/A    bool areNSlotsAvailable(unsigned int n);
767039SN/A    int getPriority() { return m_priority_rank; }
777039SN/A    void setPriority(int rank) { m_priority_rank = rank; }
789602SN/A    void setConsumer(Consumer* consumer)
797039SN/A    {
8011021Sjthestness@gmail.com        DPRINTF(RubyQueue, "Setting consumer: %s\n", *consumer);
819629SN/A        if (m_consumer != NULL) {
829629SN/A            fatal("Trying to connect %s to MessageBuffer %s. \
839629SN/A                  \n%s already connected. Check the cntrl_id's.\n",
849629SN/A                  *consumer, *this, *m_consumer);
859629SN/A        }
869602SN/A        m_consumer = consumer;
877039SN/A    }
886145SN/A
899508SN/A    void setSender(ClockedObject* obj)
909465SN/A    {
9111021Sjthestness@gmail.com        DPRINTF(RubyQueue, "Setting sender: %s\n", obj->name());
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    {
9811021Sjthestness@gmail.com        DPRINTF(RubyQueue, "Setting receiver: %s\n", obj->name());
999602SN/A        assert(m_receiver == NULL || m_receiver == obj);
1009602SN/A        m_receiver = obj;
1019465SN/A    }
1029465SN/A
10311021Sjthestness@gmail.com    Consumer* getConsumer() { return m_consumer; }
1046863SN/A
10511021Sjthestness@gmail.com    bool getOrdered() { return m_strict_fifo; }
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());
11510893Snilay@cs.wisc.edu        return m_prio_heap.front();
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; }
12710979Sdavid.hashe@amd.com    bool isStallMapEmpty() { return m_stall_msg_map.size() == 0; }
12810979Sdavid.hashe@amd.com    unsigned int getStallMapSize() { return m_stall_msg_map.size(); }
1296145SN/A
13010096SN/A    unsigned int getSize();
1316145SN/A
1327039SN/A    void clear();
1337039SN/A    void print(std::ostream& out) const;
1347039SN/A    void clearStats() { m_not_avail_count = 0; m_msg_counter = 0; }
1356285SN/A
1367973SN/A    void setIncomingLink(int link_id) { m_input_link_id = link_id; }
1377973SN/A    void setVnet(int net) { m_vnet_id = net; }
1387973SN/A
13911049Snilay@cs.wisc.edu    // Function for figuring out if any of the messages in the buffer can
14011049Snilay@cs.wisc.edu    // satisfy the read request for the address in the packet.
14111049Snilay@cs.wisc.edu    // Return value, if true, indicates that the request was fulfilled.
14211049Snilay@cs.wisc.edu    bool functionalRead(Packet *pkt);
14311049Snilay@cs.wisc.edu
1449302SN/A    // Function for figuring out if any of the messages in the buffer need
1459302SN/A    // to be updated with the data from the packet.
1469302SN/A    // Return value indicates the number of messages that were updated.
1479302SN/A    // This required for debugging the code.
1489302SN/A    uint32_t functionalWrite(Packet *pkt);
1499302SN/A
1507039SN/A  private:
15111021Sjthestness@gmail.com    //added by SS
15211021Sjthestness@gmail.com    const Cycles m_recycle_latency;
15311021Sjthestness@gmail.com
15410087SN/A    void reanalyzeList(std::list<MsgPtr> &, Tick);
15510087SN/A
15610087SN/A  private:
1577039SN/A    // Data Members (m_ prefix)
1589508SN/A    //! The two ends of the buffer.
1599602SN/A    ClockedObject* m_sender;
1609602SN/A    ClockedObject* m_receiver;
1619508SN/A
1629465SN/A    //! Consumer to signal a wakeup(), can be NULL
1639602SN/A    Consumer* m_consumer;
16410893Snilay@cs.wisc.edu    std::vector<MsgPtr> m_prio_heap;
1659465SN/A
1668943SN/A    // use a std::map for the stalled messages as this container is
1678943SN/A    // sorted and ensures a well-defined iteration order
16811025Snilay@cs.wisc.edu    typedef std::map<Addr, std::list<MsgPtr> > StallMsgMapType;
1697567SN/A
1707567SN/A    StallMsgMapType m_stall_msg_map;
1716145SN/A
17211021Sjthestness@gmail.com    const unsigned int m_max_size;
1739503SN/A    Cycles m_time_last_time_size_checked;
1749770SN/A    unsigned int m_size_last_time_size_checked;
1756145SN/A
17610917Sbrandon.potter@amd.com    // variables used so enqueues appear to happen immediately, while
1777039SN/A    // pop happen the next cycle
1789503SN/A    Cycles m_time_last_time_enqueue;
17910097SN/A    Tick m_time_last_time_pop;
18010097SN/A    Tick m_last_arrival_time;
18110097SN/A
1829770SN/A    unsigned int m_size_at_cycle_start;
1839770SN/A    unsigned int m_msgs_this_cycle;
1847039SN/A
1857039SN/A    int m_not_avail_count;  // count the # of times I didn't have N
1867039SN/A                            // slots available
18711061Snilay@cs.wisc.edu    uint64_t m_msg_counter;
1887039SN/A    int m_priority_rank;
18911021Sjthestness@gmail.com    const bool m_strict_fifo;
19011021Sjthestness@gmail.com    const bool m_randomization;
1919499SN/A
1927973SN/A    int m_input_link_id;
1937973SN/A    int m_vnet_id;
1946145SN/A};
1956145SN/A
1969554SN/ACycles random_time();
1979554SN/A
1987039SN/Ainline std::ostream&
1997039SN/Aoperator<<(std::ostream& out, const MessageBuffer& obj)
2006145SN/A{
2017039SN/A    obj.print(out);
2027039SN/A    out << std::flush;
2037039SN/A    return out;
2046145SN/A}
2056145SN/A
2067039SN/A#endif // __MEM_RUBY_BUFFERS_MESSAGEBUFFER_HH__
207