gem5
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
buffers.hh
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2013-2014 ARM Limited
3  * All rights reserved
4  *
5  * The license below extends only to copyright in the software and shall
6  * not be construed as granting a license to any other intellectual
7  * property including but not limited to intellectual property relating
8  * to a hardware implementation of the functionality of the software
9  * licensed hereunder. You may use the software subject to the license
10  * terms below provided that you ensure that this notice is replicated
11  * unmodified and in its entirety in all distributions of the software,
12  * modified or unmodified, in source code or in binary form.
13  *
14  * Redistribution and use in source and binary forms, with or without
15  * modification, are permitted provided that the following conditions are
16  * met: redistributions of source code must retain the above copyright
17  * notice, this list of conditions and the following disclaimer;
18  * redistributions in binary form must reproduce the above copyright
19  * notice, this list of conditions and the following disclaimer in the
20  * documentation and/or other materials provided with the distribution;
21  * neither the name of the copyright holders nor the names of its
22  * contributors may be used to endorse or promote products derived from
23  * this software without specific prior written permission.
24  *
25  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
26  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
27  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
28  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
29  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
30  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
31  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
32  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
33  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
35  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36  *
37  * Authors: Andrew Bardsley
38  */
39 
46 #ifndef __CPU_MINOR_BUFFERS_HH__
47 #define __CPU_MINOR_BUFFERS_HH__
48 
49 #include <iostream>
50 #include <queue>
51 #include <sstream>
52 
53 #include "base/misc.hh"
54 #include "cpu/minor/trace.hh"
55 #include "cpu/activity.hh"
56 #include "cpu/timebuf.hh"
57 
58 namespace Minor
59 {
60 
65 class ReportIF
66 {
67  public:
70  virtual void reportData(std::ostream &os) const = 0;
71 
72  virtual ~ReportIF() { }
73 };
74 
79 class BubbleIF
80 {
81  public:
82  virtual bool isBubble() const = 0;
83 };
84 
91 template <typename ElemType> /* ElemType should implement ReportIF */
93 {
94  public:
95  static void
96  reportData(std::ostream &os, const ElemType &elem)
97  { elem.reportData(os); }
98 };
99 
102 template <typename PtrType>
104 {
105  public:
106  static void
107  reportData(std::ostream &os, const PtrType &elem)
108  { elem->reportData(os); }
109 };
110 
116 template <typename ElemType>
118 {
119  public:
120  static bool isBubble(const ElemType &) { return false; }
121  static ElemType bubble() { assert(false); }
122 };
123 
125 template <typename ElemType>
127 {
128  public:
129  static bool isBubble(const ElemType &elem)
130  { return elem.isBubble(); }
131 
132  static ElemType bubble() { return ElemType::bubble(); }
133 };
134 
136 template <typename PtrType, typename ElemType>
138 {
139  public:
140  static bool isBubble(const PtrType &elem)
141  { return elem->isBubble(); }
142 
143  static PtrType bubble() { return ElemType::bubble(); }
144 };
145 
147 template <typename ElemType,
148  typename ReportTraits = ReportTraitsAdaptor<ElemType>,
149  typename BubbleTraits = BubbleTraitsAdaptor<ElemType> >
150 class MinorBuffer : public Named, public TimeBuffer<ElemType>
151 {
152  protected:
155 
157  std::string dataName;
158 
159  public:
160  MinorBuffer(const std::string &name,
161  const std::string &data_name,
162  int num_past, int num_future,
163  int report_left = -1, int report_right = -1) :
164  Named(name), TimeBuffer<ElemType>(num_past, num_future),
165  reportLeft(report_left), reportRight(report_right),
166  dataName(data_name)
167  { }
168 
169  public:
170  /* Is this buffer full of only bubbles */
171  bool
172  empty() const
173  {
174  bool ret = true;
175 
176  for (int i = -this->past; i <= this->future; i++) {
177  if (!BubbleTraits::isBubble((*this)[i]))
178  ret = false;
179  }
180 
181  return ret;
182  }
183 
188  void
189  minorTrace() const
190  {
191  std::ostringstream data;
192 
193  int step = (reportLeft > reportRight ? -1 : 1);
194  int end = reportRight + step;
195  int i = reportLeft;
196 
197  while (i != end) {
198  const ElemType &datum = (*this)[i];
199 
200  ReportTraits::reportData(data, datum);
201  i += step;
202  if (i != end)
203  data << ',';
204  }
205 
206  MINORTRACE("%s=%s\n", dataName, data.str());
207  }
208 };
209 
212 template <typename Data>
213 class Latch
214 {
215  public:
217 
218  protected:
222 
224 
225  public:
228  Latch(const std::string &name,
229  const std::string &data_name,
230  Cycles delay_ = Cycles(1),
231  bool report_backwards = false) :
232  delay(delay_),
233  buffer(name, data_name, delay_, 0, (report_backwards ? -delay_ : 0),
234  (report_backwards ? 0 : -delay_))
235  { }
236 
237  public:
243  class Input
244  {
245  public:
247 
248  public:
249  Input(typename Buffer::wire input_wire) :
250  inputWire(input_wire)
251  { }
252  };
253 
254  class Output
255  {
256  public:
258 
259  public:
260  Output(typename Buffer::wire output_wire) :
261  outputWire(output_wire)
262  { }
263  };
264 
265  bool empty() const { return buffer.empty(); }
266 
268  Input input() { return Input(buffer.getWire(0)); }
269 
271  Output output() { return Output(buffer.getWire(-delay)); }
272 
273  void minorTrace() const { buffer.minorTrace(); }
274 
275  void evaluate() { buffer.advance(); }
276 };
277 
282 template <typename ElemType,
283  typename ReportTraits,
284  typename BubbleTraits = BubbleTraitsAdaptor<ElemType> >
285 class SelfStallingPipeline : public MinorBuffer<ElemType, ReportTraits>
286 {
287  protected:
292 
293  public:
295  bool stalled;
296 
298  unsigned int occupancy;
299 
300  public:
301  SelfStallingPipeline(const std::string &name,
302  const std::string &data_name,
303  unsigned depth) :
304  MinorBuffer<ElemType, ReportTraits>
305  (name, data_name, depth, 0, -1, -depth),
306  pushWire(this->getWire(0)),
307  popWire(this->getWire(-depth)),
308  stalled(false),
309  occupancy(0)
310  {
311  assert(depth > 0);
312 
313  /* Write explicit bubbles to get around the case where the default
314  * constructor for the element type isn't good enough */
315  for (unsigned i = 0; i <= depth; i++)
316  (*this)[-i] = BubbleTraits::bubble();
317  }
318 
319  public:
324  void push(ElemType &elem)
325  {
326  assert(!alreadyPushed());
327  *pushWire = elem;
328  if (!BubbleTraits::isBubble(elem))
329  occupancy++;
330  }
331 
333  ElemType &front() { return *popWire; }
334 
335  const ElemType &front() const { return *popWire; }
336 
338  bool alreadyPushed() { return !BubbleTraits::isBubble(*pushWire); }
339 
341  bool isPopable() { return !BubbleTraits::isBubble(front()); }
342 
346  void
348  {
349  bool data_at_end = isPopable();
350 
351  if (!stalled) {
353  /* If there was data at the end of the pipe that has now been
354  * advanced out of the pipe, we've lost data */
355  if (data_at_end)
356  occupancy--;
357  /* Is there data at the end of the pipe now? */
358  stalled = isPopable();
359  /* Insert a bubble into the empty input slot to make sure that
360  * element is correct in the case where the default constructor
361  * for ElemType doesn't produce a bubble */
362  ElemType bubble = BubbleTraits::bubble();
363  *pushWire = bubble;
364  }
365  }
366 };
367 
370 {
371  public:
373  virtual bool canReserve() const = 0;
374 
376  virtual void reserve() = 0;
377 
379  virtual void freeReservation() = 0;
380 };
381 
390 template <typename ElemType,
391  typename ReportTraits = ReportTraitsAdaptor<ElemType>,
392  typename BubbleTraits = BubbleTraitsAdaptor<ElemType> >
393 class Queue : public Named, public Reservable
394 {
395  private:
397 
400  unsigned int numReservedSlots;
401 
403  unsigned int capacity;
404 
406  std::string dataName;
407 
408  public:
409  Queue(const std::string &name, const std::string &data_name,
410  unsigned int capacity_) :
411  Named(name),
412  numReservedSlots(0),
413  capacity(capacity_),
414  dataName(data_name)
415  { }
416 
417  virtual ~Queue() { }
418 
419  public:
423  void
424  push(ElemType &data)
425  {
426  if (!BubbleTraits::isBubble(data)) {
427  freeReservation();
428  queue.push_back(data);
429 
430  if (queue.size() > capacity) {
431  warn("%s: No space to push data into queue of capacity"
432  " %u, pushing anyway\n", name(), capacity);
433  }
434 
435  }
436  }
437 
440 
443  {
444  if (numReservedSlots != 0)
446  }
447 
451  void
453  {
454  /* Check reservable space */
455  if (unreservedRemainingSpace() == 0)
456  warn("%s: No space is reservable in queue", name());
457 
459  }
460 
461  bool canReserve() const { return unreservedRemainingSpace() != 0; }
462 
464  unsigned int totalSpace() const { return capacity; }
465 
467  unsigned int occupiedSpace() const { return queue.size(); }
468 
470  unsigned int reservedSpace() const { return numReservedSlots; }
471 
474  unsigned int
476  {
477  int ret = capacity - queue.size();
478 
479  return (ret < 0 ? 0 : ret);
480  }
481 
483  unsigned int
485  {
486  int ret = capacity - (queue.size() + numReservedSlots);
487 
488  return (ret < 0 ? 0 : ret);
489  }
490 
492  ElemType &front() { return queue.front(); }
493 
494  const ElemType &front() const { return queue.front(); }
495 
497  void pop() { queue.pop_front(); }
498 
500  bool empty() const { return queue.empty(); }
501 
502  void
503  minorTrace() const
504  {
505  std::ostringstream data;
506  /* If we become over-full, totalSpace() can actually be smaller than
507  * occupiedSpace(). Handle this */
508  unsigned int num_total = (occupiedSpace() > totalSpace() ?
509  occupiedSpace() : totalSpace());
510 
511  unsigned int num_reserved = reservedSpace();
512  unsigned int num_occupied = occupiedSpace();
513 
514  int num_printed = 1;
515  /* Bodge to rotate queue to report elements */
516  while (num_printed <= num_occupied) {
517  ReportTraits::reportData(data, queue[num_printed - 1]);
518  num_printed++;
519 
520  if (num_printed <= num_total)
521  data << ',';
522  }
523 
524  int num_printed_reserved = 1;
525  /* Show reserved slots */
526  while (num_printed_reserved <= num_reserved &&
527  num_printed <= num_total)
528  {
529  data << 'R';
530  num_printed_reserved++;
531  num_printed++;
532 
533  if (num_printed <= num_total)
534  data << ',';
535  }
536 
537  /* And finally pad with empty slots (if there are any) */
538  while (num_printed <= num_total) {
539  num_printed++;
540 
541  if (num_printed <= num_total)
542  data << ',';
543  }
544 
545  MINORTRACE("%s=%s\n", dataName, data.str());
546  }
547 };
548 
560 template <typename ElemType,
561  typename ReportTraits = ReportTraitsAdaptor<ElemType>,
562  typename BubbleTraits = BubbleTraitsAdaptor<ElemType> >
563 class InputBuffer : public Reservable
564 {
565  protected:
568 
570  mutable ElemType *elementPtr;
571 
572  public:
573  InputBuffer(const std::string &name, const std::string &data_name,
574  unsigned int capacity_) :
575  queue(name, data_name, capacity_),
576  elementPtr(NULL)
577  { }
578 
579  public:
583  void
584  setTail(ElemType &new_element)
585  {
586  assert(!elementPtr);
587  if (!BubbleTraits::isBubble(new_element)) {
588  if (queue.empty())
589  elementPtr = &new_element;
590  else
591  queue.push(new_element);
592  }
593  }
594 
596  bool empty() const { return !elementPtr && queue.empty(); }
597 
599  const ElemType &front() const
600  { return (elementPtr ? *elementPtr : queue.front()); }
601 
602  ElemType &front()
603  { return (elementPtr ? *elementPtr : queue.front()); }
604 
606  void
607  pop()
608  {
609  if (elementPtr) {
610  /* A popped element was expected to be pushed into queue
611  * and so take a reserved space */
612  elementPtr = NULL;
613  queue.freeReservation();
614  } else {
615  queue.pop();
616  }
617  }
618 
622  void
623  pushTail() const
624  {
625  if (elementPtr)
626  queue.push(*elementPtr);
627  elementPtr = NULL;
628  }
629 
631  void
632  minorTrace() const
633  {
634  pushTail();
635  queue.minorTrace();
636  }
637 
639  bool canReserve() const { return queue.canReserve(); }
640  void reserve() { queue.reserve(); }
641  void freeReservation() { queue.freeReservation(); }
642 
644  unsigned int
646  {
647  pushTail();
648  return queue.unreservedRemainingSpace();
649  }
650 };
651 
652 }
653 
654 #endif /* __CPU_MINOR_BUFFERS_HH__ */
...ReportTraits are trait classes with the same functionality as ReportIF, but with elements explicit...
Definition: buffers.hh:92
bool empty() const
No single element or queue entries.
Definition: buffers.hh:596
void evaluate()
Definition: buffers.hh:275
Queue< ElemType, ReportTraits, BubbleTraits > queue
Underlying queue.
Definition: buffers.hh:567
const std::string & name() const
Definition: trace.hh:149
Cycles is a wrapper class for representing cycle counts, i.e.
Definition: types.hh:83
void pop()
Pop the head item.
Definition: buffers.hh:497
static bool isBubble(const ElemType &)
Definition: buffers.hh:120
static ElemType bubble()
Definition: buffers.hh:121
unsigned int numReservedSlots
Number of slots currently reserved for future (reservation respecting) pushes.
Definition: buffers.hh:400
const std::string & name()
Definition: trace.cc:49
MinorBuffer(const std::string &name, const std::string &data_name, int num_past, int num_future, int report_left=-1, int report_right=-1)
Definition: buffers.hh:160
Bitfield< 7 > i
Definition: miscregs.hh:1378
Like a Queue but with a restricted interface and a setTail function which, when the queue is empty...
Definition: buffers.hh:563
Output(typename Buffer::wire output_wire)
Definition: buffers.hh:260
MinorBuffer< Data > Buffer
Definition: buffers.hh:216
void pop()
Pop either the head, or if none, the head of the queue.
Definition: buffers.hh:607
bool empty() const
Definition: buffers.hh:172
unsigned int unreservedRemainingSpace()
Like remainingSpace but does not count reserved spaces.
Definition: buffers.hh:645
virtual bool isBubble() const =0
int reportLeft
The range of elements that should appear in trace lines.
Definition: buffers.hh:154
void advance()
Definition: timebuf.hh:179
ElemType & front()
Peek at the end element of the pipe.
Definition: buffers.hh:333
Interface class for data with 'bubble' values.
Definition: buffers.hh:79
std::string dataName
Name to use for the data in a MinorTrace line.
Definition: buffers.hh:157
unsigned int unreservedRemainingSpace() const
Like remainingSpace but does not count reserved spaces.
Definition: buffers.hh:484
const ElemType & front() const
Definition: buffers.hh:335
Wrapper for a queue type to act as a pipeline stage input queue.
Definition: buffers.hh:393
bool empty() const
Definition: buffers.hh:265
This file contains miscellaneous classes and functions for formatting general trace information and a...
Queue(const std::string &name, const std::string &data_name, unsigned int capacity_)
Definition: buffers.hh:409
Bitfield< 17 > os
Definition: misc.hh:804
void reserve()
Reserve space in the queue for future pushes.
Definition: buffers.hh:452
void advance()
Try to advance the pipeline.
Definition: buffers.hh:347
TimeBuffer< ElemType >::wire popWire
Wire at the output end of the pipeline (for convenience)
Definition: buffers.hh:291
const char data[]
Definition: circlebuf.cc:43
std::string dataName
Name to use for the data in MinorTrace.
Definition: buffers.hh:406
#define warn(...)
Definition: misc.hh:219
Definition: trace.hh:140
unsigned int capacity
Need this here as queues usually don't have a limited capacity.
Definition: buffers.hh:403
void freeReservation()
Clear a single reserved slot.
Definition: buffers.hh:442
A similar adaptor but for elements held by pointer ElemType should implement ReportIF.
Definition: buffers.hh:103
bool empty() const
Is the queue empty?
Definition: buffers.hh:500
bool canReserve() const
Can a slot be reserved?
Definition: buffers.hh:461
TimeBuffer with MinorTrace and Named interfaces.
Definition: buffers.hh:150
const ElemType & front() const
Return the element, or the front of the queue.
Definition: buffers.hh:599
Base class for space reservation requestable objects.
Definition: buffers.hh:369
Pass on call to the element where the element is a pointer.
Definition: buffers.hh:137
void pushTail() const
Push the single element (if any) into the queue proper.
Definition: buffers.hh:623
std::deque< ElemType > queue
Definition: buffers.hh:396
static bool isBubble(const PtrType &elem)
Definition: buffers.hh:140
ElemType & front()
Head value.
Definition: buffers.hh:492
void setTail(ElemType &new_element)
Set the tail of the queue, this is like push but needs to be followed by pushTail for the new tail to...
Definition: buffers.hh:584
const ElemType & front() const
Definition: buffers.hh:494
static void reportData(std::ostream &os, const PtrType &elem)
Definition: buffers.hh:107
static ElemType bubble()
Definition: buffers.hh:132
virtual ~Queue()
Definition: buffers.hh:417
virtual bool canReserve() const =0
Can a slot be reserved?
bool canReserve() const
Reservable interface, passed on to queue.
Definition: buffers.hh:639
friend class wire
Definition: timebuf.hh:58
unsigned int occupancy
The number of slots with non-bubbles in them.
Definition: buffers.hh:298
Buffer::wire outputWire
Definition: buffers.hh:257
virtual void reportData(std::ostream &os) const =0
Print the data in a format suitable to be the value in "name=value" trace lines.
virtual void freeReservation()=0
Free a reserved slot.
ElemType * elementPtr
Pointer to the single element (if not NULL)
Definition: buffers.hh:570
Pass on call to the element.
Definition: buffers.hh:126
void minorTrace() const
Definition: buffers.hh:273
bool alreadyPushed()
Have we already pushed onto this pipe without advancing.
Definition: buffers.hh:338
Cycles delay
Delays, in cycles, writing data into the latch and seeing it on the latched wires.
Definition: buffers.hh:221
virtual ~ReportIF()
Definition: buffers.hh:72
unsigned int reservedSpace() const
Number of slots which are reserved.
Definition: buffers.hh:470
Output output()
An interface to just the output of the buffer.
Definition: buffers.hh:271
Buffer buffer
Definition: buffers.hh:223
InputBuffer(const std::string &name, const std::string &data_name, unsigned int capacity_)
Definition: buffers.hh:573
virtual void reserve()=0
Reserve a slot in whatever structure this is attached to.
void clearReservedSpace()
Clear all allocated space.
Definition: buffers.hh:439
unsigned int totalSpace() const
Number of slots available in an empty buffer.
Definition: buffers.hh:464
void minorTrace() const
Report buffer states from 'slot' 'from' to 'to'.
Definition: buffers.hh:189
Input(typename Buffer::wire input_wire)
Definition: buffers.hh:249
void reserve()
Reserve a slot in whatever structure this is attached to.
Definition: buffers.hh:640
static bool isBubble(const ElemType &elem)
Definition: buffers.hh:129
A pipeline simulating class that will stall (not advance when advance() is called) if a non-bubble va...
Definition: buffers.hh:285
void push(ElemType &data)
Push an element into the buffer if it isn't a bubble.
Definition: buffers.hh:424
#define MINORTRACE(...)
DPRINTFN for MinorTrace reporting.
Definition: trace.hh:62
SelfStallingPipeline(const std::string &name, const std::string &data_name, unsigned depth)
Definition: buffers.hh:301
Interface class for data with reporting/tracing facilities.
Definition: buffers.hh:65
Wraps a MinorBuffer with Input/Output interfaces to ensure that units within the model can only see t...
Definition: buffers.hh:213
wire getWire(int idx)
Definition: timebuf.hh:232
static void reportData(std::ostream &os, const ElemType &elem)
Definition: buffers.hh:96
void minorTrace() const
Definition: buffers.hh:503
void push(ElemType &elem)
Write an element to the back of the pipeline.
Definition: buffers.hh:324
TimeBuffer< ElemType >::wire pushWire
Wire at the input end of the pipeline (for convenience)
Definition: buffers.hh:289
ElemType & front()
Definition: buffers.hh:602
unsigned int remainingSpace() const
Number of slots yet to fill in this buffer.
Definition: buffers.hh:475
Encapsulate wires on either input or output of the latch.
Definition: buffers.hh:243
unsigned int occupiedSpace() const
Number of slots already occupied in this buffer.
Definition: buffers.hh:467
Buffer::wire inputWire
Definition: buffers.hh:246
bool stalled
If true, advance will not advance the pipeline.
Definition: buffers.hh:295
void freeReservation()
Free a reserved slot.
Definition: buffers.hh:641
void minorTrace() const
Report elements.
Definition: buffers.hh:632
bool isPopable()
There's data (not a bubble) at the end of the pipe.
Definition: buffers.hh:341
static PtrType bubble()
Definition: buffers.hh:143
Latch(const std::string &name, const std::string &data_name, Cycles delay_=Cycles(1), bool report_backwards=false)
forward/backwardDelay specify the delay from input to output in each direction.
Definition: buffers.hh:228
Input input()
An interface to just the input of the buffer.
Definition: buffers.hh:268

Generated on Fri Jun 9 2017 13:03:42 for gem5 by doxygen 1.8.6