2 * Copyright (c) 2015,2017-2018 ARM Limited
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.
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.
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.
38 #ifndef __BASE_CIRCLEBUF_HH__
39 #define __BASE_CIRCLEBUF_HH__
46 #include "base/logging.hh"
47 #include "sim/serialize.hh"
50 * Circular buffer backed by a vector.
52 * The data in the cricular buffer is stored in a standard vector.
58 std::vector<T> buffer;
66 explicit CircleBuf(size_t size) : buffer(size), maxSize(size) {}
68 bool empty() const { return used == 0; }
69 size_t size() const { return used; }
70 size_t capacity() const { return maxSize; }
73 * Throw away any data in the buffer.
83 * Copy buffer contents without advancing the read pointer
85 * @param out Output iterator/pointer
86 * @param len Number of elements to copy
88 template <class OutputIterator>
90 peek(OutputIterator out, size_t len) const
96 * Copy buffer contents without advancing the read pointer
98 * @param out Output iterator/pointer
99 * @param offset Offset into the ring buffer
100 * @param len Number of elements to copy
102 template <class OutputIterator>
104 peek(OutputIterator out, off_t offset, size_t len) const
106 panic_if(offset + len > used,
107 "Trying to read past end of circular buffer.");
112 // The iterator for the next byte to copy out.
113 auto next_it = buffer.begin() + (start + offset) % maxSize;
114 // How much there is to copy from until the end of the buffer.
115 const size_t to_end = buffer.end() - next_it;
117 // If the data to be copied wraps, take care of the first part.
120 out = std::copy_n(next_it, to_end, out);
121 // Start copying again at the start of buffer.
122 next_it = buffer.begin();
125 // Copy the remaining (or only) chunk of data.
126 std::copy_n(next_it, len, out);
130 * Copy buffer contents and advance the read pointer
132 * @param out Output iterator/pointer
133 * @param len Number of elements to read
135 template <class OutputIterator>
137 read(OutputIterator out, size_t len)
145 * Add elements to the end of the ring buffers and advance. Writes which
146 * would exceed the capacity of the queue fill the avaialble space, and
147 * then continue overwriting the head of the queue. The head advances as
148 * if that data had been read out.
150 * @param in Input iterator/pointer
151 * @param len Number of elements to read
153 template <class InputIterator>
155 write(InputIterator in, size_t len)
160 // Writes that are larger than the buffer size are allowed, but only
161 // the last part of the date will be written since the rest will be
162 // overwritten and not remain in the buffer.
169 // How much existing data will be overwritten?
170 const size_t total_bytes = used + len;
171 const size_t overflow = total_bytes > maxSize ?
172 total_bytes - maxSize : 0;
173 // The iterator of the next byte to add.
174 auto next_it = buffer.begin() + (start + used) % maxSize;
175 // How much there is to copy to the end of the buffer.
176 const size_t to_end = buffer.end() - next_it;
178 // If this addition wraps, take care of the first part here.
181 std::copy_n(in, to_end, next_it);
182 // Update state to reflect what's left.
183 next_it = buffer.begin();
184 std::advance(in, to_end);
188 // Copy the remaining (or only) chunk of data.
189 std::copy_n(in, len, next_it);
192 // Don't count data that was overwritten.
199 * Simple FIFO implementation backed by a circular buffer.
201 * This class provides the same basic functionallity as the circular
202 * buffer with the folling differences:
204 * <li>Writes are checked to ensure that overflows can't happen.
205 * <li>Unserialization ensures that the data in the checkpoint fits
213 typedef T value_type;
216 Fifo(size_t size) : buf(size) {}
218 bool empty() const { return buf.empty(); }
219 size_t size() const { return buf.size(); }
220 size_t capacity() const { return buf.capacity(); }
222 void flush() { buf.flush(); }
224 template <class OutputIterator>
225 void peek(OutputIterator out, size_t len) const { buf.peek(out, len); }
226 template <class OutputIterator>
227 void read(OutputIterator out, size_t len) { buf.read(out, len); }
229 template <class InputIterator>
231 write(InputIterator in, size_t len)
233 panic_if(size() + len > capacity(), "Trying to overfill FIFO buffer.");
238 CircleBuf<value_type> buf;
242 template <typename T>
244 arrayParamOut(CheckpointOut &cp, const std::string &name,
245 const CircleBuf<T> ¶m)
247 std::vector<T> temp(param.size());
248 param.peek(temp.begin(), temp.size());
249 arrayParamOut(cp, name, temp);
252 template <typename T>
254 arrayParamIn(CheckpointIn &cp, const std::string &name, CircleBuf<T> ¶m)
257 arrayParamIn(cp, name, temp);
260 param.write(temp.cbegin(), temp.size());
263 template <typename T>
265 arrayParamOut(CheckpointOut &cp, const std::string &name, const Fifo<T> ¶m)
267 std::vector<T> temp(param.size());
268 param.peek(temp.begin(), temp.size());
269 arrayParamOut(cp, name, temp);
272 template <typename T>
274 arrayParamIn(CheckpointIn &cp, const std::string &name, Fifo<T> ¶m)
277 arrayParamIn(cp, name, temp);
279 fatal_if(param.capacity() < temp.size(),
280 "Trying to unserialize data into too small FIFO");
283 param.write(temp.cbegin(), temp.size());
286 #endif // __BASE_CIRCLEBUF_HH__