base: Ported circlebuf to CircularQueue
Ported the existing circlebuf on top of the CircularQueue to condense shared functionality and minimise code/functionality replication. Additional contributors: Gabor Dozsa. Change-Id: Ib4e67c638f0fb66b54cef77007a03439218bda7f Signed-off-by: Giacomo Gabrielli <giacomo.gabrielli@arm.com> Signed-off-by: Giacomo Travaglini <giacomo.travaglini@arm.com> Reviewed-on: https://gem5-review.googlesource.com/c/13128 Maintainer: Andreas Sandberg <andreas.sandberg@arm.com> Reviewed-by: Daniel Carvalho <odanrc@yahoo.com.br>
This commit is contained in:
committed by
Giacomo Travaglini
parent
2e8e51dcea
commit
e003f9bb48
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2015 ARM Limited
|
||||
* Copyright (c) 2015,2017-2018 ARM Limited
|
||||
* All rights reserved
|
||||
*
|
||||
* The license below extends only to copyright in the software and shall
|
||||
@@ -44,56 +44,30 @@
|
||||
#include <cassert>
|
||||
#include <vector>
|
||||
|
||||
#include "base/circular_queue.hh"
|
||||
#include "base/logging.hh"
|
||||
#include "sim/serialize.hh"
|
||||
|
||||
/**
|
||||
* Circular buffer backed by a vector
|
||||
* Circular buffer backed by a vector though a CircularQueue.
|
||||
*
|
||||
* The data in the cricular buffer is stored in a standard
|
||||
* vector. _start designates the first element in the buffer and _stop
|
||||
* points to the last element + 1 (i.e., the position of the next
|
||||
* insertion). The _stop index may be outside the range of the backing
|
||||
* store, which means that the actual index must be calculated as
|
||||
* _stop % capacity.
|
||||
* vector.
|
||||
*
|
||||
* Invariants:
|
||||
* <ul>
|
||||
* <li>_start <= _stop
|
||||
* <li>_start < capacity
|
||||
* <li>_stop < 2 * capacity
|
||||
* </ul>
|
||||
*/
|
||||
template<typename T>
|
||||
class CircleBuf
|
||||
class CircleBuf : public CircularQueue<T>
|
||||
{
|
||||
public:
|
||||
typedef T value_type;
|
||||
|
||||
public:
|
||||
explicit CircleBuf(size_t size)
|
||||
: buf(size), _start(0), _stop(0) {}
|
||||
|
||||
/** Is the buffer empty? */
|
||||
bool empty() const { return _stop == _start; }
|
||||
/**
|
||||
* Return the maximum number of elements that can be stored in
|
||||
* the buffer at any one time.
|
||||
*/
|
||||
size_t capacity() const { return buf.size(); }
|
||||
/** Return the number of elements stored in the buffer. */
|
||||
size_t size() const { return _stop - _start; }
|
||||
|
||||
/**
|
||||
* Remove all the elements in the buffer.
|
||||
*
|
||||
* Note: This does not actually remove elements from the backing
|
||||
* store.
|
||||
*/
|
||||
void flush() {
|
||||
_start = 0;
|
||||
_stop = 0;
|
||||
}
|
||||
: CircularQueue<T>(size) {}
|
||||
using CircularQueue<T>::empty;
|
||||
using CircularQueue<T>::size;
|
||||
using CircularQueue<T>::capacity;
|
||||
using CircularQueue<T>::begin;
|
||||
using CircularQueue<T>::end;
|
||||
using CircularQueue<T>::pop_front;
|
||||
using CircularQueue<T>::advance_tail;
|
||||
|
||||
/**
|
||||
* Copy buffer contents without advancing the read pointer
|
||||
@@ -118,19 +92,7 @@ class CircleBuf
|
||||
panic_if(offset + len > size(),
|
||||
"Trying to read past end of circular buffer.\n");
|
||||
|
||||
const off_t real_start((offset + _start) % buf.size());
|
||||
if (real_start + len <= buf.size()) {
|
||||
std::copy(buf.begin() + real_start,
|
||||
buf.begin() + real_start + len,
|
||||
out);
|
||||
} else {
|
||||
const size_t head_size(buf.size() - real_start);
|
||||
const size_t tail_size(len - head_size);
|
||||
std::copy(buf.begin() + real_start, buf.end(),
|
||||
out);
|
||||
std::copy(buf.begin(), buf.begin() + tail_size,
|
||||
out + head_size);
|
||||
}
|
||||
std::copy(begin() + offset, begin() + offset + len, out);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -142,9 +104,7 @@ class CircleBuf
|
||||
template <class OutputIterator>
|
||||
void read(OutputIterator out, size_t len) {
|
||||
peek(out, len);
|
||||
|
||||
_start += len;
|
||||
normalize();
|
||||
pop_front(len);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -157,51 +117,16 @@ class CircleBuf
|
||||
void write(InputIterator in, size_t len) {
|
||||
// Writes that are larger than the backing store are allowed,
|
||||
// but only the last part of the buffer will be written.
|
||||
if (len > buf.size()) {
|
||||
in += len - buf.size();
|
||||
len = buf.size();
|
||||
if (len > capacity()) {
|
||||
in += len - capacity();
|
||||
len = capacity();
|
||||
}
|
||||
|
||||
const size_t next(_stop % buf.size());
|
||||
const size_t head_len(std::min(buf.size() - next, len));
|
||||
|
||||
std::copy(in, in + head_len, buf.begin() + next);
|
||||
std::copy(in + head_len, in + len, buf.begin());
|
||||
|
||||
_stop += len;
|
||||
// We may have written past the old _start pointer. Readjust
|
||||
// the _start pointer to remove the oldest entries in that
|
||||
// case.
|
||||
if (size() > buf.size())
|
||||
_start = _stop - buf.size();
|
||||
|
||||
normalize();
|
||||
std::copy(in, in + len, end());
|
||||
advance_tail(len);
|
||||
}
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Normalize the start and stop pointers to ensure that pointer
|
||||
* invariants hold after updates.
|
||||
*/
|
||||
void normalize() {
|
||||
if (_start >= buf.size()) {
|
||||
_stop -= buf.size();
|
||||
_start -= buf.size();
|
||||
}
|
||||
|
||||
assert(_start < buf.size());
|
||||
assert(_stop < 2 * buf.size());
|
||||
assert(_start <= _stop);
|
||||
}
|
||||
|
||||
protected:
|
||||
std::vector<value_type> buf;
|
||||
size_t _start;
|
||||
size_t _stop;
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Simple FIFO implementation backed by a circular buffer.
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user