MessageBuffer.hh revision 7002
1
2/*
3 * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are
8 * met: redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer;
10 * redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution;
13 * neither the name of the copyright holders nor the names of its
14 * contributors may be used to endorse or promote products derived from
15 * this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29
30/*
31 * $Id$
32 *
33 * Description: Unordered buffer of messages that can be inserted such
34 * that they can be dequeued after a given delta time has expired.
35 *
36 */
37
38#ifndef MESSAGEBUFFER_H
39#define MESSAGEBUFFER_H
40
41#include <iostream>
42#include <string>
43
44#include "mem/ruby/common/Global.hh"
45#include "mem/ruby/buffers/MessageBufferNode.hh"
46#include "mem/ruby/common/Consumer.hh"
47#include "mem/ruby/eventqueue/RubyEventQueue.hh"
48#include "mem/ruby/slicc_interface/Message.hh"
49#include "mem/gems_common/PrioHeap.hh"
50#include "mem/gems_common/util.hh"
51
52class MessageBuffer {
53public:
54  // Constructors
55  MessageBuffer(const std::string &name = "");
56
57  // ~MessageBuffer()
58
59  // Public Methods
60
61  static void printConfig(std::ostream& out) {}
62  void setRecycleLatency(int recycle_latency) { m_recycle_latency = recycle_latency; }
63
64  // TRUE if head of queue timestamp <= SystemTime
65  bool isReady() const {
66    return ((m_prio_heap.size() > 0) &&
67            (m_prio_heap.peekMin().m_time <= g_eventQueue_ptr->getTime()));
68  }
69
70  void delayHead() {
71    MessageBufferNode node = m_prio_heap.extractMin();
72    enqueue(node.m_msgptr, 1);
73  }
74
75  bool areNSlotsAvailable(int n);
76  int getPriority() { return m_priority_rank; }
77  void setPriority(int rank) { m_priority_rank = rank; }
78  void setConsumer(Consumer* consumer_ptr) { ASSERT(m_consumer_ptr==NULL); m_consumer_ptr = consumer_ptr; }
79  void setDescription(const std::string& name) { m_name = name; }
80  std::string getDescription() { return m_name;}
81
82  Consumer* getConsumer() { return m_consumer_ptr; }
83
84  const Message* peekAtHeadOfQueue() const;
85  const Message* peek() const { return peekAtHeadOfQueue(); }
86  const MsgPtr getMsgPtrCopy() const;
87  const MsgPtr& peekMsgPtr() const { assert(isReady()); return m_prio_heap.peekMin().m_msgptr; }
88  const MsgPtr& peekMsgPtrEvenIfNotReady() const {return m_prio_heap.peekMin().m_msgptr; }
89
90  void enqueue(const MsgPtr& message) { enqueue(message, 1); }
91  void enqueue(const MsgPtr& message, Time delta);
92  //  void enqueueAbsolute(const MsgPtr& message, Time absolute_time);
93  int dequeue_getDelayCycles(MsgPtr& message);  // returns delay cycles of the message
94  void dequeue(MsgPtr& message);
95  int dequeue_getDelayCycles();  // returns delay cycles of the message
96  void dequeue() { pop(); }
97  void pop();
98  void recycle();
99  bool isEmpty() const { return m_prio_heap.size() == 0; }
100
101  void setOrdering(bool order) { m_strict_fifo = order; m_ordering_set = true; }
102  void setSize(int size) {m_max_size = size;}
103  int getSize();
104  void setRandomization(bool random_flag) { m_randomization = random_flag; }
105
106  void clear();
107
108  void print(std::ostream& out) const;
109  void printStats(std::ostream& out);
110  void clearStats() { m_not_avail_count = 0; m_msg_counter = 0; }
111
112private:
113  //added by SS
114  int m_recycle_latency;
115
116  // Private Methods
117  int setAndReturnDelayCycles(MsgPtr& message);
118
119  // Private copy constructor and assignment operator
120  MessageBuffer(const MessageBuffer& obj);
121  MessageBuffer& operator=(const MessageBuffer& obj);
122
123  // Data Members (m_ prefix)
124  Consumer* m_consumer_ptr;  // Consumer to signal a wakeup(), can be NULL
125  PrioHeap<MessageBufferNode> m_prio_heap;
126  std::string m_name;
127
128  int m_max_size;
129  int m_size;
130
131  Time m_time_last_time_size_checked;
132  int m_size_last_time_size_checked;
133
134  // variables used so enqueues appear to happen imediately, while pop happen the next cycle
135  Time m_time_last_time_enqueue;
136  Time m_time_last_time_pop;
137  int m_size_at_cycle_start;
138  int m_msgs_this_cycle;
139
140  int m_not_avail_count;  // count the # of times I didn't have N slots available
141  int m_msg_counter;
142  int m_priority_rank;
143  bool m_strict_fifo;
144  bool m_ordering_set;
145  bool m_randomization;
146  Time m_last_arrival_time;
147};
148
149// Output operator declaration
150//template <class TYPE>
151std::ostream& operator<<(std::ostream& out, const MessageBuffer& obj);
152
153// ******************* Definitions *******************
154
155// Output operator definition
156extern inline
157std::ostream& operator<<(std::ostream& out, const MessageBuffer& obj)
158{
159  obj.print(out);
160  out << std::flush;
161  return out;
162}
163
164#endif //MESSAGEBUFFER_H
165