MessageBuffer.hh revision 10096
114184Sgabeblack@google.com/*
214184Sgabeblack@google.com * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
314184Sgabeblack@google.com * All rights reserved.
414184Sgabeblack@google.com *
514184Sgabeblack@google.com * Redistribution and use in source and binary forms, with or without
614184Sgabeblack@google.com * modification, are permitted provided that the following conditions are
714184Sgabeblack@google.com * met: redistributions of source code must retain the above copyright
814184Sgabeblack@google.com * notice, this list of conditions and the following disclaimer;
914184Sgabeblack@google.com * redistributions in binary form must reproduce the above copyright
1014184Sgabeblack@google.com * notice, this list of conditions and the following disclaimer in the
1114184Sgabeblack@google.com * documentation and/or other materials provided with the distribution;
1214184Sgabeblack@google.com * neither the name of the copyright holders nor the names of its
1314184Sgabeblack@google.com * contributors may be used to endorse or promote products derived from
1414184Sgabeblack@google.com * this software without specific prior written permission.
1514184Sgabeblack@google.com *
1614184Sgabeblack@google.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
1714184Sgabeblack@google.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
1814184Sgabeblack@google.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
1914184Sgabeblack@google.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
2014184Sgabeblack@google.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
2114184Sgabeblack@google.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
2214184Sgabeblack@google.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2314184Sgabeblack@google.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2414184Sgabeblack@google.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2514184Sgabeblack@google.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2614184Sgabeblack@google.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2714184Sgabeblack@google.com */
2814184Sgabeblack@google.com
2914184Sgabeblack@google.com/*
3014184Sgabeblack@google.com * Unordered buffer of messages that can be inserted such
3114184Sgabeblack@google.com * that they can be dequeued after a given delta time has expired.
3214184Sgabeblack@google.com */
3314184Sgabeblack@google.com
3414184Sgabeblack@google.com#ifndef __MEM_RUBY_BUFFERS_MESSAGEBUFFER_HH__
3514184Sgabeblack@google.com#define __MEM_RUBY_BUFFERS_MESSAGEBUFFER_HH__
3614184Sgabeblack@google.com
3714184Sgabeblack@google.com#include <algorithm>
3814184Sgabeblack@google.com#include <cassert>
3914184Sgabeblack@google.com#include <functional>
4014184Sgabeblack@google.com#include <iostream>
4114184Sgabeblack@google.com#include <string>
4214184Sgabeblack@google.com#include <vector>
4314184Sgabeblack@google.com
4414184Sgabeblack@google.com#include "mem/packet.hh"
4514184Sgabeblack@google.com#include "mem/ruby/buffers/MessageBufferNode.hh"
4614184Sgabeblack@google.com#include "mem/ruby/common/Address.hh"
4714184Sgabeblack@google.com#include "mem/ruby/common/Consumer.hh"
4814184Sgabeblack@google.com#include "mem/ruby/slicc_interface/Message.hh"
4914184Sgabeblack@google.com
5014184Sgabeblack@google.comclass MessageBuffer
5114184Sgabeblack@google.com{
5214184Sgabeblack@google.com  public:
5314184Sgabeblack@google.com    MessageBuffer(const std::string &name = "");
5414184Sgabeblack@google.com
5514184Sgabeblack@google.com    std::string name() const { return m_name; }
5614184Sgabeblack@google.com
5714184Sgabeblack@google.com    void setRecycleLatency(Cycles recycle_latency)
5814184Sgabeblack@google.com    { m_recycle_latency = recycle_latency; }
5914184Sgabeblack@google.com
6014184Sgabeblack@google.com    void reanalyzeMessages(const Address& addr);
6114184Sgabeblack@google.com    void reanalyzeAllMessages();
6214184Sgabeblack@google.com    void stallMessage(const Address& addr);
6314184Sgabeblack@google.com
6414184Sgabeblack@google.com    // TRUE if head of queue timestamp <= SystemTime
6514184Sgabeblack@google.com    bool isReady() const;
6614184Sgabeblack@google.com
6714184Sgabeblack@google.com    void
6814184Sgabeblack@google.com    delayHead()
6914184Sgabeblack@google.com    {
7014184Sgabeblack@google.com        MessageBufferNode node = m_prio_heap.front();
7114184Sgabeblack@google.com        std::pop_heap(m_prio_heap.begin(), m_prio_heap.end(),
7214184Sgabeblack@google.com                      std::greater<MessageBufferNode>());
7314184Sgabeblack@google.com        m_prio_heap.pop_back();
7414184Sgabeblack@google.com        enqueue(node.m_msgptr, Cycles(1));
7514184Sgabeblack@google.com    }
7614184Sgabeblack@google.com
7714184Sgabeblack@google.com    bool areNSlotsAvailable(unsigned int n);
7814184Sgabeblack@google.com    int getPriority() { return m_priority_rank; }
7914184Sgabeblack@google.com    void setPriority(int rank) { m_priority_rank = rank; }
8014184Sgabeblack@google.com    void setConsumer(Consumer* consumer)
8114184Sgabeblack@google.com    {
8214184Sgabeblack@google.com        if (m_consumer != NULL) {
8314184Sgabeblack@google.com            fatal("Trying to connect %s to MessageBuffer %s. \
8414184Sgabeblack@google.com                  \n%s already connected. Check the cntrl_id's.\n",
8514184Sgabeblack@google.com                  *consumer, *this, *m_consumer);
8614184Sgabeblack@google.com        }
8714184Sgabeblack@google.com        m_consumer = consumer;
8814184Sgabeblack@google.com    }
8914184Sgabeblack@google.com
9014184Sgabeblack@google.com    void setSender(ClockedObject* obj)
9114184Sgabeblack@google.com    {
9214184Sgabeblack@google.com        assert(m_sender == NULL || m_sender == obj);
9314184Sgabeblack@google.com        m_sender = obj;
9414184Sgabeblack@google.com    }
9514184Sgabeblack@google.com
9614184Sgabeblack@google.com    void setReceiver(ClockedObject* obj)
9714184Sgabeblack@google.com    {
9814184Sgabeblack@google.com        assert(m_receiver == NULL || m_receiver == obj);
9914184Sgabeblack@google.com        m_receiver = obj;
10014184Sgabeblack@google.com    }
10114184Sgabeblack@google.com
10214184Sgabeblack@google.com    void setDescription(const std::string& name) { m_name = name; }
10314184Sgabeblack@google.com    std::string getDescription() { return m_name;}
10414184Sgabeblack@google.com
10514184Sgabeblack@google.com    Consumer* getConsumer() { return m_consumer; }
10614184Sgabeblack@google.com
10714184Sgabeblack@google.com    //! Function for extracting the message at the head of the
10814184Sgabeblack@google.com    //! message queue.  The function assumes that the queue is nonempty.
10914184Sgabeblack@google.com    const Message* peek() const;
11014184Sgabeblack@google.com
11114184Sgabeblack@google.com    const MsgPtr&
11214184Sgabeblack@google.com    peekMsgPtr() const
11314184Sgabeblack@google.com    {
11414184Sgabeblack@google.com        assert(isReady());
11514184Sgabeblack@google.com        return m_prio_heap.front().m_msgptr;
11614184Sgabeblack@google.com    }
11714184Sgabeblack@google.com
11814184Sgabeblack@google.com    void enqueue(MsgPtr message) { enqueue(message, Cycles(1)); }
11914184Sgabeblack@google.com    void enqueue(MsgPtr message, Cycles delta);
12014184Sgabeblack@google.com
12114184Sgabeblack@google.com    //! Updates the delay cycles of the message at the of the queue,
12214184Sgabeblack@google.com    //! removes it from the queue and returns its total delay.
12314184Sgabeblack@google.com    Cycles dequeue_getDelayCycles();
12414184Sgabeblack@google.com
12514184Sgabeblack@google.com    void dequeue();
12614184Sgabeblack@google.com
12714184Sgabeblack@google.com    void recycle();
12814184Sgabeblack@google.com    bool isEmpty() const { return m_prio_heap.size() == 0; }
12914184Sgabeblack@google.com
13014184Sgabeblack@google.com    void
13114184Sgabeblack@google.com    setOrdering(bool order)
13214184Sgabeblack@google.com    {
13314184Sgabeblack@google.com        m_strict_fifo = order;
13414184Sgabeblack@google.com        m_ordering_set = true;
13514184Sgabeblack@google.com    }
13614184Sgabeblack@google.com
13714184Sgabeblack@google.com    void resize(unsigned int size) { m_max_size = size; }
13814184Sgabeblack@google.com    unsigned int getSize();
13914184Sgabeblack@google.com    void setRandomization(bool random_flag) { m_randomization = random_flag; }
14014184Sgabeblack@google.com
14114184Sgabeblack@google.com    void clear();
14214184Sgabeblack@google.com    void print(std::ostream& out) const;
14314184Sgabeblack@google.com    void clearStats() { m_not_avail_count = 0; m_msg_counter = 0; }
14414184Sgabeblack@google.com
14514184Sgabeblack@google.com    void setIncomingLink(int link_id) { m_input_link_id = link_id; }
14614184Sgabeblack@google.com    void setVnet(int net) { m_vnet_id = net; }
14714184Sgabeblack@google.com
14814184Sgabeblack@google.com    // Function for figuring out if any of the messages in the buffer can
14914184Sgabeblack@google.com    // satisfy the read request for the address in the packet.
15014184Sgabeblack@google.com    // Return value, if true, indicates that the request was fulfilled.
15114184Sgabeblack@google.com    bool functionalRead(Packet *pkt);
15214184Sgabeblack@google.com
15314184Sgabeblack@google.com    // Function for figuring out if any of the messages in the buffer need
15414184Sgabeblack@google.com    // to be updated with the data from the packet.
15514184Sgabeblack@google.com    // Return value indicates the number of messages that were updated.
15614184Sgabeblack@google.com    // This required for debugging the code.
15714184Sgabeblack@google.com    uint32_t functionalWrite(Packet *pkt);
15814184Sgabeblack@google.com
15914184Sgabeblack@google.com  private:
16014184Sgabeblack@google.com    void reanalyzeList(std::list<MsgPtr> &, Tick);
16114184Sgabeblack@google.com
16214184Sgabeblack@google.com  private:
16314184Sgabeblack@google.com    //added by SS
16414184Sgabeblack@google.com    Cycles m_recycle_latency;
16514184Sgabeblack@google.com
16614184Sgabeblack@google.com    // Data Members (m_ prefix)
16714184Sgabeblack@google.com    //! The two ends of the buffer.
16814184Sgabeblack@google.com    ClockedObject* m_sender;
16914184Sgabeblack@google.com    ClockedObject* m_receiver;
17014184Sgabeblack@google.com
17114184Sgabeblack@google.com    //! Consumer to signal a wakeup(), can be NULL
17214184Sgabeblack@google.com    Consumer* m_consumer;
17314184Sgabeblack@google.com    std::vector<MessageBufferNode> m_prio_heap;
17414184Sgabeblack@google.com
17514184Sgabeblack@google.com    // use a std::map for the stalled messages as this container is
17614184Sgabeblack@google.com    // sorted and ensures a well-defined iteration order
17714184Sgabeblack@google.com    typedef std::map< Address, std::list<MsgPtr> > StallMsgMapType;
17814184Sgabeblack@google.com
17914184Sgabeblack@google.com    StallMsgMapType m_stall_msg_map;
18014184Sgabeblack@google.com    std::string m_name;
18114184Sgabeblack@google.com
18214184Sgabeblack@google.com    unsigned int m_max_size;
18314184Sgabeblack@google.com    Cycles m_time_last_time_size_checked;
18414184Sgabeblack@google.com    unsigned int m_size_last_time_size_checked;
18514184Sgabeblack@google.com
18614184Sgabeblack@google.com    // variables used so enqueues appear to happen imediately, while
18714184Sgabeblack@google.com    // pop happen the next cycle
18814184Sgabeblack@google.com    Cycles m_time_last_time_enqueue;
18914184Sgabeblack@google.com    Cycles m_time_last_time_pop;
19014184Sgabeblack@google.com    unsigned int m_size_at_cycle_start;
19114184Sgabeblack@google.com    unsigned int m_msgs_this_cycle;
19214184Sgabeblack@google.com
19314184Sgabeblack@google.com    int m_not_avail_count;  // count the # of times I didn't have N
19414184Sgabeblack@google.com                            // slots available
19514184Sgabeblack@google.com    uint64 m_msg_counter;
19614184Sgabeblack@google.com    int m_priority_rank;
19714184Sgabeblack@google.com    bool m_strict_fifo;
19814184Sgabeblack@google.com    bool m_ordering_set;
19914184Sgabeblack@google.com    bool m_randomization;
20014184Sgabeblack@google.com
20114184Sgabeblack@google.com    Tick m_last_arrival_time;
20214184Sgabeblack@google.com
20314184Sgabeblack@google.com    int m_input_link_id;
20414184Sgabeblack@google.com    int m_vnet_id;
20514184Sgabeblack@google.com};
20614184Sgabeblack@google.com
20714184Sgabeblack@google.comCycles random_time();
20814184Sgabeblack@google.com
20914184Sgabeblack@google.cominline std::ostream&
21014184Sgabeblack@google.comoperator<<(std::ostream& out, const MessageBuffer& obj)
21114184Sgabeblack@google.com{
21214184Sgabeblack@google.com    obj.print(out);
21314184Sgabeblack@google.com    out << std::flush;
21414184Sgabeblack@google.com    return out;
21514184Sgabeblack@google.com}
21614184Sgabeblack@google.com
21714184Sgabeblack@google.com#endif // __MEM_RUBY_BUFFERS_MESSAGEBUFFER_HH__
21814184Sgabeblack@google.com