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