gem5  v22.1.0.0
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 
44 #ifndef __CPU_MINOR_BUFFERS_HH__
45 #define __CPU_MINOR_BUFFERS_HH__
46 
47 #include <iostream>
48 #include <queue>
49 #include <sstream>
50 #include <string>
51 
52 #include "base/logging.hh"
53 #include "base/named.hh"
54 #include "base/types.hh"
55 #include "cpu/activity.hh"
56 #include "cpu/minor/trace.hh"
57 #include "cpu/timebuf.hh"
58 
59 namespace gem5
60 {
61 
63 namespace minor
64 {
65 
70 class ReportIF
71 {
72  public:
75  virtual void reportData(std::ostream &os) const = 0;
76 
77  virtual ~ReportIF() { }
78 };
79 
84 class BubbleIF
85 {
86  public:
87  virtual bool isBubble() const = 0;
88 };
89 
96 template <typename ElemType> /* ElemType should implement ReportIF */
98 {
99  public:
100  static void
101  reportData(std::ostream &os, const ElemType &elem)
102  { elem.reportData(os); }
103 };
104 
107 template <typename PtrType>
109 {
110  public:
111  static void
112  reportData(std::ostream &os, const PtrType &elem)
113  { elem->reportData(os); }
114 };
115 
121 template <typename ElemType>
123 {
124  public:
125  static bool isBubble(const ElemType &) { return false; }
126  static ElemType
128  {
129  panic("bubble called but no bubble interface");
130  }
131 };
132 
134 template <typename ElemType>
136 {
137  public:
138  static bool isBubble(const ElemType &elem)
139  { return elem.isBubble(); }
140 
141  static ElemType bubble() { return ElemType::bubble(); }
142 };
143 
145 template <typename PtrType, typename ElemType>
147 {
148  public:
149  static bool isBubble(const PtrType &elem)
150  { return elem->isBubble(); }
151 
152  static PtrType bubble() { return ElemType::bubble(); }
153 };
154 
156 template <typename ElemType,
157  typename ReportTraits = ReportTraitsAdaptor<ElemType>,
158  typename BubbleTraits = BubbleTraitsAdaptor<ElemType> >
159 class MinorBuffer : public Named, public TimeBuffer<ElemType>
160 {
161  protected:
164 
166  std::string dataName;
167 
168  public:
169  MinorBuffer(const std::string &name,
170  const std::string &data_name,
171  int num_past, int num_future,
172  int report_left = -1, int report_right = -1) :
173  Named(name), TimeBuffer<ElemType>(num_past, num_future),
174  reportLeft(report_left), reportRight(report_right),
175  dataName(data_name)
176  { }
177 
178  public:
179  /* Is this buffer full of only bubbles */
180  bool
181  empty() const
182  {
183  bool ret = true;
184 
185  for (int i = -this->past; i <= this->future; i++) {
186  if (!BubbleTraits::isBubble((*this)[i]))
187  ret = false;
188  }
189 
190  return ret;
191  }
192 
197  void
198  minorTrace() const
199  {
200  std::ostringstream data;
201 
202  int step = (reportLeft > reportRight ? -1 : 1);
203  int end = reportRight + step;
204  int i = reportLeft;
205 
206  while (i != end) {
207  const ElemType &datum = (*this)[i];
208 
209  ReportTraits::reportData(data, datum);
210  i += step;
211  if (i != end)
212  data << ',';
213  }
214 
215  minor::minorTrace("%s=%s\n", dataName, data.str());
216  }
217 };
218 
221 template <typename Data>
222 class Latch
223 {
224  public:
226 
227  protected:
231 
233 
234  public:
237  Latch(const std::string &name,
238  const std::string &data_name,
239  Cycles delay_ = Cycles(1),
240  bool report_backwards = false) :
241  delay(delay_),
242  buffer(name, data_name, delay_, 0, (report_backwards ? -delay_ : 0),
243  (report_backwards ? 0 : -delay_))
244  { }
245 
246  public:
252  class Input
253  {
254  public:
256 
257  public:
258  Input(typename Buffer::wire input_wire) :
259  inputWire(input_wire)
260  { }
261  };
262 
263  class Output
264  {
265  public:
267 
268  public:
269  Output(typename Buffer::wire output_wire) :
270  outputWire(output_wire)
271  { }
272  };
273 
274  bool empty() const { return buffer.empty(); }
275 
277  Input input() { return Input(buffer.getWire(0)); }
278 
281 
282  void minorTrace() const { buffer.minorTrace(); }
283 
284  void evaluate() { buffer.advance(); }
285 };
286 
291 template <typename ElemType,
292  typename ReportTraits,
293  typename BubbleTraits = BubbleTraitsAdaptor<ElemType> >
294 class SelfStallingPipeline : public MinorBuffer<ElemType, ReportTraits>
295 {
296  protected:
301 
302  public:
304  bool stalled;
305 
307  unsigned int occupancy;
308 
309  public:
310  SelfStallingPipeline(const std::string &name,
311  const std::string &data_name,
312  unsigned depth) :
313  MinorBuffer<ElemType, ReportTraits>
314  (name, data_name, depth, 0, -1, -depth),
315  pushWire(this->getWire(0)),
316  popWire(this->getWire(-depth)),
317  stalled(false),
318  occupancy(0)
319  {
320  assert(depth > 0);
321 
322  /* Write explicit bubbles to get around the case where the default
323  * constructor for the element type isn't good enough */
324  for (unsigned i = 0; i <= depth; i++)
325  (*this)[-i] = BubbleTraits::bubble();
326  }
327 
328  public:
333  void push(ElemType &elem)
334  {
335  assert(!alreadyPushed());
336  *pushWire = elem;
337  if (!BubbleTraits::isBubble(elem))
338  occupancy++;
339  }
340 
342  ElemType &front() { return *popWire; }
343 
344  const ElemType &front() const { return *popWire; }
345 
347  bool alreadyPushed() { return !BubbleTraits::isBubble(*pushWire); }
348 
350  bool isPopable() { return !BubbleTraits::isBubble(front()); }
351 
355  void
357  {
358  bool data_at_end = isPopable();
359 
360  if (!stalled) {
362  /* If there was data at the end of the pipe that has now been
363  * advanced out of the pipe, we've lost data */
364  if (data_at_end)
365  occupancy--;
366  /* Is there data at the end of the pipe now? */
367  stalled = isPopable();
368  /* Insert a bubble into the empty input slot to make sure that
369  * element is correct in the case where the default constructor
370  * for ElemType doesn't produce a bubble */
371  ElemType bubble = BubbleTraits::bubble();
372  *pushWire = bubble;
373  }
374  }
375 };
376 
379 {
380  public:
382  virtual bool canReserve() const = 0;
383 
385  virtual void reserve() = 0;
386 
388  virtual void freeReservation() = 0;
389 
390  virtual ~Reservable() {};
391 };
392 
401 template <typename ElemType,
402  typename ReportTraits = ReportTraitsAdaptor<ElemType>,
403  typename BubbleTraits = BubbleTraitsAdaptor<ElemType> >
404 class Queue : public Named, public Reservable
405 {
406  private:
408 
411  unsigned int numReservedSlots;
412 
414  unsigned int capacity;
415 
417  std::string dataName;
418 
419  public:
420  Queue(const std::string &name, const std::string &data_name,
421  unsigned int capacity_) :
422  Named(name),
423  numReservedSlots(0),
424  capacity(capacity_),
425  dataName(data_name)
426  { }
427 
428  public:
432  void
433  push(ElemType &data)
434  {
435  if (!BubbleTraits::isBubble(data)) {
436  freeReservation();
437  queue.push_back(data);
438 
439  if (queue.size() > capacity) {
440  warn("%s: No space to push data into queue of capacity"
441  " %u, pushing anyway\n", name(), capacity);
442  }
443 
444  }
445  }
446 
449 
452  {
453  if (numReservedSlots != 0)
455  }
456 
460  void
462  {
463  /* Check reservable space */
464  if (unreservedRemainingSpace() == 0)
465  warn("%s: No space is reservable in queue", name());
466 
468  }
469 
470  bool canReserve() const { return unreservedRemainingSpace() != 0; }
471 
473  unsigned int totalSpace() const { return capacity; }
474 
476  unsigned int occupiedSpace() const { return queue.size(); }
477 
479  unsigned int reservedSpace() const { return numReservedSlots; }
480 
483  unsigned int
485  {
486  int ret = capacity - queue.size();
487 
488  return (ret < 0 ? 0 : ret);
489  }
490 
492  unsigned int
494  {
495  int ret = capacity - (queue.size() + numReservedSlots);
496 
497  return (ret < 0 ? 0 : ret);
498  }
499 
501  ElemType &front() { return queue.front(); }
502 
503  const ElemType &front() const { return queue.front(); }
504 
506  void pop() { queue.pop_front(); }
507 
509  bool empty() const { return queue.empty(); }
510 
511  void
512  minorTrace() const
513  {
514  std::ostringstream data;
515  /* If we become over-full, totalSpace() can actually be smaller than
516  * occupiedSpace(). Handle this */
517  unsigned int num_total = (occupiedSpace() > totalSpace() ?
518  occupiedSpace() : totalSpace());
519 
520  unsigned int num_reserved = reservedSpace();
521  unsigned int num_occupied = occupiedSpace();
522 
523  int num_printed = 1;
524  /* Bodge to rotate queue to report elements */
525  while (num_printed <= num_occupied) {
526  ReportTraits::reportData(data, queue[num_printed - 1]);
527  num_printed++;
528 
529  if (num_printed <= num_total)
530  data << ',';
531  }
532 
533  int num_printed_reserved = 1;
534  /* Show reserved slots */
535  while (num_printed_reserved <= num_reserved &&
536  num_printed <= num_total)
537  {
538  data << 'R';
539  num_printed_reserved++;
540  num_printed++;
541 
542  if (num_printed <= num_total)
543  data << ',';
544  }
545 
546  /* And finally pad with empty slots (if there are any) */
547  while (num_printed <= num_total) {
548  num_printed++;
549 
550  if (num_printed <= num_total)
551  data << ',';
552  }
553 
554  minor::minorTrace("%s=%s\n", dataName, data.str());
555  }
556 };
557 
569 template <typename ElemType,
570  typename ReportTraits = ReportTraitsAdaptor<ElemType>,
571  typename BubbleTraits = BubbleTraitsAdaptor<ElemType> >
572 class InputBuffer : public Reservable
573 {
574  protected:
577 
579  mutable ElemType *elementPtr;
580 
581  public:
582  InputBuffer(const std::string &name, const std::string &data_name,
583  unsigned int capacity_) :
584  queue(name, data_name, capacity_),
585  elementPtr(NULL)
586  { }
587 
588  public:
592  void
593  setTail(ElemType &new_element)
594  {
595  assert(!elementPtr);
596  if (!BubbleTraits::isBubble(new_element)) {
597  if (queue.empty())
598  elementPtr = &new_element;
599  else
600  queue.push(new_element);
601  }
602  }
603 
605  bool empty() const { return !elementPtr && queue.empty(); }
606 
608  const ElemType &front() const
609  { return (elementPtr ? *elementPtr : queue.front()); }
610 
611  ElemType &front()
612  { return (elementPtr ? *elementPtr : queue.front()); }
613 
615  void
616  pop()
617  {
618  if (elementPtr) {
619  /* A popped element was expected to be pushed into queue
620  * and so take a reserved space */
621  elementPtr = NULL;
622  queue.freeReservation();
623  } else {
624  queue.pop();
625  }
626  }
627 
631  void
632  pushTail() const
633  {
634  if (elementPtr)
635  queue.push(*elementPtr);
636  elementPtr = NULL;
637  }
638 
640  void
641  minorTrace() const
642  {
643  pushTail();
644  queue.minorTrace();
645  }
646 
648  bool canReserve() const { return queue.canReserve(); }
649  void reserve() { queue.reserve(); }
650  void freeReservation() { queue.freeReservation(); }
651 
653  unsigned int
655  {
656  pushTail();
657  return queue.unreservedRemainingSpace();
658  }
659 };
660 
661 } // namespace minor
662 } // namespace gem5
663 
664 #endif /* __CPU_MINOR_BUFFERS_HH__ */
Defines global host-dependent types: Counter, Tick, and (indirectly) {int,uint}{8,...
const char data[]
Cycles is a wrapper class for representing cycle counts, i.e.
Definition: types.hh:79
Interface for things with names.
Definition: named.hh:39
virtual std::string name() const
Definition: named.hh:47
wire getWire(int idx)
Definition: timebuf.hh:232
void advance()
Definition: timebuf.hh:179
Interface class for data with 'bubble' values.
Definition: buffers.hh:85
virtual bool isBubble() const =0
Pass on call to the element.
Definition: buffers.hh:136
static bool isBubble(const ElemType &elem)
Definition: buffers.hh:138
static ElemType bubble()
Definition: buffers.hh:141
Pass on call to the element where the element is a pointer.
Definition: buffers.hh:147
static bool isBubble(const PtrType &elem)
Definition: buffers.hh:149
Like a Queue but with a restricted interface and a setTail function which, when the queue is empty,...
Definition: buffers.hh:573
bool empty() const
No single element or queue entries.
Definition: buffers.hh:605
void reserve()
Reserve a slot in whatever structure this is attached to.
Definition: buffers.hh:649
InputBuffer(const std::string &name, const std::string &data_name, unsigned int capacity_)
Definition: buffers.hh:582
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:593
void pop()
Pop either the head, or if none, the head of the queue.
Definition: buffers.hh:616
void minorTrace() const
Report elements.
Definition: buffers.hh:641
void freeReservation()
Free a reserved slot.
Definition: buffers.hh:650
void pushTail() const
Push the single element (if any) into the queue proper.
Definition: buffers.hh:632
ElemType * elementPtr
Pointer to the single element (if not NULL)
Definition: buffers.hh:579
unsigned int unreservedRemainingSpace()
Like remainingSpace but does not count reserved spaces.
Definition: buffers.hh:654
const ElemType & front() const
Return the element, or the front of the queue.
Definition: buffers.hh:608
ElemType & front()
Definition: buffers.hh:611
Queue< ElemType, ReportTraits, BubbleTraits > queue
Underlying queue.
Definition: buffers.hh:576
bool canReserve() const
Reservable interface, passed on to queue.
Definition: buffers.hh:648
Encapsulate wires on either input or output of the latch.
Definition: buffers.hh:253
Buffer::wire inputWire
Definition: buffers.hh:255
Input(typename Buffer::wire input_wire)
Definition: buffers.hh:258
Output(typename Buffer::wire output_wire)
Definition: buffers.hh:269
Buffer::wire outputWire
Definition: buffers.hh:266
Wraps a MinorBuffer with Input/Output interfaces to ensure that units within the model can only see t...
Definition: buffers.hh:223
Input input()
An interface to just the input of the buffer.
Definition: buffers.hh:277
MinorBuffer< Data > Buffer
Definition: buffers.hh:225
void minorTrace() const
Definition: buffers.hh:282
Cycles delay
Delays, in cycles, writing data into the latch and seeing it on the latched wires.
Definition: buffers.hh:230
bool empty() const
Definition: buffers.hh:274
Output output()
An interface to just the output of the buffer.
Definition: buffers.hh:280
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:237
TimeBuffer with MinorTrace and Named interfaces.
Definition: buffers.hh:160
int reportLeft
The range of elements that should appear in trace lines.
Definition: buffers.hh:163
std::string dataName
Name to use for the data in a MinorTrace line.
Definition: buffers.hh:166
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:169
bool empty() const
Definition: buffers.hh:181
void minorTrace() const
Report buffer states from 'slot' 'from' to 'to'.
Definition: buffers.hh:198
static ElemType bubble()
Definition: buffers.hh:127
static bool isBubble(const ElemType &)
Definition: buffers.hh:125
Wrapper for a queue type to act as a pipeline stage input queue.
Definition: buffers.hh:405
Queue(const std::string &name, const std::string &data_name, unsigned int capacity_)
Definition: buffers.hh:420
bool empty() const
Is the queue empty?
Definition: buffers.hh:509
std::deque< ElemType > queue
Definition: buffers.hh:407
const ElemType & front() const
Definition: buffers.hh:503
void minorTrace() const
Definition: buffers.hh:512
unsigned int reservedSpace() const
Number of slots which are reserved.
Definition: buffers.hh:479
void clearReservedSpace()
Clear all allocated space.
Definition: buffers.hh:448
void pop()
Pop the head item.
Definition: buffers.hh:506
bool canReserve() const
Can a slot be reserved?
Definition: buffers.hh:470
unsigned int unreservedRemainingSpace() const
Like remainingSpace but does not count reserved spaces.
Definition: buffers.hh:493
unsigned int remainingSpace() const
Number of slots yet to fill in this buffer.
Definition: buffers.hh:484
unsigned int occupiedSpace() const
Number of slots already occupied in this buffer.
Definition: buffers.hh:476
void freeReservation()
Clear a single reserved slot.
Definition: buffers.hh:451
std::string dataName
Name to use for the data in MinorTrace.
Definition: buffers.hh:417
unsigned int capacity
Need this here as queues usually don't have a limited capacity.
Definition: buffers.hh:414
void reserve()
Reserve space in the queue for future pushes.
Definition: buffers.hh:461
unsigned int totalSpace() const
Number of slots available in an empty buffer.
Definition: buffers.hh:473
ElemType & front()
Head value.
Definition: buffers.hh:501
unsigned int numReservedSlots
Number of slots currently reserved for future (reservation respecting) pushes.
Definition: buffers.hh:411
void push(ElemType &data)
Push an element into the buffer if it isn't a bubble.
Definition: buffers.hh:433
Interface class for data with reporting/tracing facilities.
Definition: buffers.hh:71
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 ~ReportIF()
Definition: buffers.hh:77
...ReportTraits are trait classes with the same functionality as ReportIF, but with elements explicit...
Definition: buffers.hh:98
static void reportData(std::ostream &os, const ElemType &elem)
Definition: buffers.hh:101
A similar adaptor but for elements held by pointer ElemType should implement ReportIF.
Definition: buffers.hh:109
static void reportData(std::ostream &os, const PtrType &elem)
Definition: buffers.hh:112
Base class for space reservation requestable objects.
Definition: buffers.hh:379
virtual void freeReservation()=0
Free a reserved slot.
virtual void reserve()=0
Reserve a slot in whatever structure this is attached to.
virtual bool canReserve() const =0
Can a slot be reserved?
A pipeline simulating class that will stall (not advance when advance() is called) if a non-bubble va...
Definition: buffers.hh:295
bool alreadyPushed()
Have we already pushed onto this pipe without advancing.
Definition: buffers.hh:347
bool stalled
If true, advance will not advance the pipeline.
Definition: buffers.hh:304
void advance()
Try to advance the pipeline.
Definition: buffers.hh:356
SelfStallingPipeline(const std::string &name, const std::string &data_name, unsigned depth)
Definition: buffers.hh:310
TimeBuffer< ElemType >::wire popWire
Wire at the output end of the pipeline (for convenience)
Definition: buffers.hh:300
unsigned int occupancy
The number of slots with non-bubbles in them.
Definition: buffers.hh:307
const ElemType & front() const
Definition: buffers.hh:344
ElemType & front()
Peek at the end element of the pipe.
Definition: buffers.hh:342
TimeBuffer< ElemType >::wire pushWire
Wire at the input end of the pipeline (for convenience)
Definition: buffers.hh:298
bool isPopable()
There's data (not a bubble) at the end of the pipe.
Definition: buffers.hh:350
void push(ElemType &elem)
Write an element to the back of the pipeline.
Definition: buffers.hh:333
This file contains miscellaneous classes and functions for formatting general trace information and a...
#define panic(...)
This implements a cprintf based panic() function.
Definition: logging.hh:178
#define warn(...)
Definition: logging.hh:246
Bitfield< 7 > i
Definition: misc_types.hh:67
Bitfield< 17 > os
Definition: misc.hh:810
void minorTrace(const char *fmt, Args ...args)
DPRINTFN for MinorTrace reporting.
Definition: trace.hh:67
Reference material can be found at the JEDEC website: UFS standard http://www.jedec....
GEM5_DEPRECATED_NAMESPACE(GuestABI, guest_abi)
Minor contains all the definitions within the MinorCPU apart from the CPU class itself.
const std::string & name()
Definition: trace.cc:49

Generated on Wed Dec 21 2022 10:22:30 for gem5 by doxygen 1.9.1