12SN/A/* 213483Srekai.gonzalezalberquilla@arm.com * Copyright (c) 2015,2017-2018 ARM Limited 311008Sandreas.sandberg@arm.com * All rights reserved 411008Sandreas.sandberg@arm.com * 511008Sandreas.sandberg@arm.com * The license below extends only to copyright in the software and shall 611008Sandreas.sandberg@arm.com * not be construed as granting a license to any other intellectual 711008Sandreas.sandberg@arm.com * property including but not limited to intellectual property relating 811008Sandreas.sandberg@arm.com * to a hardware implementation of the functionality of the software 911008Sandreas.sandberg@arm.com * licensed hereunder. You may use the software subject to the license 1011008Sandreas.sandberg@arm.com * terms below provided that you ensure that this notice is replicated 1111008Sandreas.sandberg@arm.com * unmodified and in its entirety in all distributions of the software, 1211008Sandreas.sandberg@arm.com * modified or unmodified, in source code or in binary form. 132SN/A * 142SN/A * Redistribution and use in source and binary forms, with or without 152SN/A * modification, are permitted provided that the following conditions are 162SN/A * met: redistributions of source code must retain the above copyright 172SN/A * notice, this list of conditions and the following disclaimer; 182SN/A * redistributions in binary form must reproduce the above copyright 192SN/A * notice, this list of conditions and the following disclaimer in the 202SN/A * documentation and/or other materials provided with the distribution; 212SN/A * neither the name of the copyright holders nor the names of its 222SN/A * contributors may be used to endorse or promote products derived from 232SN/A * this software without specific prior written permission. 242SN/A * 252SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 262SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 272SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 282SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 292SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 302SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 312SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 322SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 332SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 342SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 352SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 362665Ssaidi@eecs.umich.edu * 3711008Sandreas.sandberg@arm.com * Authors: Andreas Sandberg 382SN/A */ 392SN/A 4011008Sandreas.sandberg@arm.com#ifndef __BASE_CIRCLEBUF_HH__ 4111008Sandreas.sandberg@arm.com#define __BASE_CIRCLEBUF_HH__ 422SN/A 4311008Sandreas.sandberg@arm.com#include <algorithm> 4411008Sandreas.sandberg@arm.com#include <cassert> 4511008Sandreas.sandberg@arm.com#include <vector> 462SN/A 4713483Srekai.gonzalezalberquilla@arm.com#include "base/circular_queue.hh" 4812334Sgabeblack@google.com#include "base/logging.hh" 4911008Sandreas.sandberg@arm.com#include "sim/serialize.hh" 5011008Sandreas.sandberg@arm.com 5111008Sandreas.sandberg@arm.com/** 5213483Srekai.gonzalezalberquilla@arm.com * Circular buffer backed by a vector though a CircularQueue. 5311008Sandreas.sandberg@arm.com * 5411008Sandreas.sandberg@arm.com * The data in the cricular buffer is stored in a standard 5513483Srekai.gonzalezalberquilla@arm.com * vector. 5611008Sandreas.sandberg@arm.com * 5711008Sandreas.sandberg@arm.com */ 5811008Sandreas.sandberg@arm.comtemplate<typename T> 5913483Srekai.gonzalezalberquilla@arm.comclass CircleBuf : public CircularQueue<T> 602SN/A{ 6111008Sandreas.sandberg@arm.com public: 6211008Sandreas.sandberg@arm.com explicit CircleBuf(size_t size) 6313483Srekai.gonzalezalberquilla@arm.com : CircularQueue<T>(size) {} 6413483Srekai.gonzalezalberquilla@arm.com using CircularQueue<T>::empty; 6513483Srekai.gonzalezalberquilla@arm.com using CircularQueue<T>::size; 6613483Srekai.gonzalezalberquilla@arm.com using CircularQueue<T>::capacity; 6713483Srekai.gonzalezalberquilla@arm.com using CircularQueue<T>::begin; 6813483Srekai.gonzalezalberquilla@arm.com using CircularQueue<T>::end; 6913483Srekai.gonzalezalberquilla@arm.com using CircularQueue<T>::pop_front; 7013483Srekai.gonzalezalberquilla@arm.com using CircularQueue<T>::advance_tail; 7111008Sandreas.sandberg@arm.com 7211008Sandreas.sandberg@arm.com /** 7311008Sandreas.sandberg@arm.com * Copy buffer contents without advancing the read pointer 7411008Sandreas.sandberg@arm.com * 7511008Sandreas.sandberg@arm.com * @param out Output iterator/pointer 7611008Sandreas.sandberg@arm.com * @param len Number of elements to copy 7711008Sandreas.sandberg@arm.com */ 7811008Sandreas.sandberg@arm.com template <class OutputIterator> 7911008Sandreas.sandberg@arm.com void peek(OutputIterator out, size_t len) const { 8011460Sandreas.sandberg@arm.com peek(out, 0, len); 8111460Sandreas.sandberg@arm.com } 8211460Sandreas.sandberg@arm.com 8311460Sandreas.sandberg@arm.com /** 8411460Sandreas.sandberg@arm.com * Copy buffer contents without advancing the read pointer 8511460Sandreas.sandberg@arm.com * 8611460Sandreas.sandberg@arm.com * @param out Output iterator/pointer 8711460Sandreas.sandberg@arm.com * @param offset Offset into the ring buffer 8811460Sandreas.sandberg@arm.com * @param len Number of elements to copy 8911460Sandreas.sandberg@arm.com */ 9011460Sandreas.sandberg@arm.com template <class OutputIterator> 9111460Sandreas.sandberg@arm.com void peek(OutputIterator out, off_t offset, size_t len) const { 9211460Sandreas.sandberg@arm.com panic_if(offset + len > size(), 9311008Sandreas.sandberg@arm.com "Trying to read past end of circular buffer.\n"); 9411008Sandreas.sandberg@arm.com 9513483Srekai.gonzalezalberquilla@arm.com std::copy(begin() + offset, begin() + offset + len, out); 9611008Sandreas.sandberg@arm.com } 9711008Sandreas.sandberg@arm.com 9811008Sandreas.sandberg@arm.com /** 9911008Sandreas.sandberg@arm.com * Copy buffer contents and advance the read pointer 10011008Sandreas.sandberg@arm.com * 10111008Sandreas.sandberg@arm.com * @param out Output iterator/pointer 10211008Sandreas.sandberg@arm.com * @param len Number of elements to read 10311008Sandreas.sandberg@arm.com */ 10411008Sandreas.sandberg@arm.com template <class OutputIterator> 10511008Sandreas.sandberg@arm.com void read(OutputIterator out, size_t len) { 10611008Sandreas.sandberg@arm.com peek(out, len); 10713483Srekai.gonzalezalberquilla@arm.com pop_front(len); 10811008Sandreas.sandberg@arm.com } 10911008Sandreas.sandberg@arm.com 11011008Sandreas.sandberg@arm.com /** 11111008Sandreas.sandberg@arm.com * Add elements to the end of the ring buffers and advance. 11211008Sandreas.sandberg@arm.com * 11311008Sandreas.sandberg@arm.com * @param in Input iterator/pointer 11411008Sandreas.sandberg@arm.com * @param len Number of elements to read 11511008Sandreas.sandberg@arm.com */ 11611008Sandreas.sandberg@arm.com template <class InputIterator> 11711008Sandreas.sandberg@arm.com void write(InputIterator in, size_t len) { 11811008Sandreas.sandberg@arm.com // Writes that are larger than the backing store are allowed, 11911008Sandreas.sandberg@arm.com // but only the last part of the buffer will be written. 12013483Srekai.gonzalezalberquilla@arm.com if (len > capacity()) { 12113483Srekai.gonzalezalberquilla@arm.com in += len - capacity(); 12213483Srekai.gonzalezalberquilla@arm.com len = capacity(); 12311008Sandreas.sandberg@arm.com } 12411008Sandreas.sandberg@arm.com 12513483Srekai.gonzalezalberquilla@arm.com std::copy(in, in + len, end()); 12613483Srekai.gonzalezalberquilla@arm.com advance_tail(len); 12711008Sandreas.sandberg@arm.com } 1282SN/A}; 1292SN/A 13011008Sandreas.sandberg@arm.com/** 13111008Sandreas.sandberg@arm.com * Simple FIFO implementation backed by a circular buffer. 13211008Sandreas.sandberg@arm.com * 13311008Sandreas.sandberg@arm.com * This class provides the same basic functionallity as the circular 13411008Sandreas.sandberg@arm.com * buffer with the folling differences: 13511008Sandreas.sandberg@arm.com * <ul> 13611008Sandreas.sandberg@arm.com * <li>Writes are checked to ensure that overflows can't happen. 13711008Sandreas.sandberg@arm.com * <li>Unserialization ensures that the data in the checkpoint fits 13811008Sandreas.sandberg@arm.com * in the buffer. 13911008Sandreas.sandberg@arm.com * </ul> 14011008Sandreas.sandberg@arm.com */ 14111008Sandreas.sandberg@arm.comtemplate<typename T> 14211008Sandreas.sandberg@arm.comclass Fifo 14311008Sandreas.sandberg@arm.com{ 14411008Sandreas.sandberg@arm.com public: 14511008Sandreas.sandberg@arm.com typedef T value_type; 14611008Sandreas.sandberg@arm.com 14711008Sandreas.sandberg@arm.com public: 14811008Sandreas.sandberg@arm.com Fifo(size_t size) 14911008Sandreas.sandberg@arm.com : buf(size) {} 15011008Sandreas.sandberg@arm.com 15111008Sandreas.sandberg@arm.com bool empty() const { return buf.empty(); } 15211008Sandreas.sandberg@arm.com size_t size() const { return buf.size(); } 15311008Sandreas.sandberg@arm.com size_t capacity() const { return buf.capacity(); } 15411008Sandreas.sandberg@arm.com 15511008Sandreas.sandberg@arm.com void flush() { buf.flush(); } 15611008Sandreas.sandberg@arm.com 15711008Sandreas.sandberg@arm.com template <class OutputIterator> 15811008Sandreas.sandberg@arm.com void peek(OutputIterator out, size_t len) const { buf.peek(out, len); } 15911008Sandreas.sandberg@arm.com template <class OutputIterator> 16011008Sandreas.sandberg@arm.com void read(OutputIterator out, size_t len) { buf.read(out, len); } 16111008Sandreas.sandberg@arm.com 16211008Sandreas.sandberg@arm.com template <class InputIterator> 16311008Sandreas.sandberg@arm.com void write(InputIterator in, size_t len) { 16411008Sandreas.sandberg@arm.com panic_if(size() + len > capacity(), 16511008Sandreas.sandberg@arm.com "Trying to overfill FIFO buffer.\n"); 16611008Sandreas.sandberg@arm.com buf.write(in, len); 16711008Sandreas.sandberg@arm.com } 16811008Sandreas.sandberg@arm.com 16911008Sandreas.sandberg@arm.com private: 17011008Sandreas.sandberg@arm.com CircleBuf<value_type> buf; 17111008Sandreas.sandberg@arm.com}; 17211008Sandreas.sandberg@arm.com 17311008Sandreas.sandberg@arm.com 17411008Sandreas.sandberg@arm.comtemplate <typename T> 17512032Sandreas.sandberg@arm.comvoid 17611008Sandreas.sandberg@arm.comarrayParamOut(CheckpointOut &cp, const std::string &name, 17711008Sandreas.sandberg@arm.com const CircleBuf<T> ¶m) 17811008Sandreas.sandberg@arm.com{ 17911008Sandreas.sandberg@arm.com std::vector<T> temp(param.size()); 18011008Sandreas.sandberg@arm.com param.peek(temp.begin(), temp.size()); 18111008Sandreas.sandberg@arm.com arrayParamOut(cp, name, temp); 18211008Sandreas.sandberg@arm.com} 18311008Sandreas.sandberg@arm.com 18411008Sandreas.sandberg@arm.comtemplate <typename T> 18512032Sandreas.sandberg@arm.comvoid 18611008Sandreas.sandberg@arm.comarrayParamIn(CheckpointIn &cp, const std::string &name, 18711008Sandreas.sandberg@arm.com CircleBuf<T> ¶m) 18811008Sandreas.sandberg@arm.com{ 18911008Sandreas.sandberg@arm.com std::vector<T> temp; 19011008Sandreas.sandberg@arm.com arrayParamIn(cp, name, temp); 19111008Sandreas.sandberg@arm.com 19211008Sandreas.sandberg@arm.com param.flush(); 19311008Sandreas.sandberg@arm.com param.write(temp.cbegin(), temp.size()); 19411008Sandreas.sandberg@arm.com} 19511008Sandreas.sandberg@arm.com 19611008Sandreas.sandberg@arm.comtemplate <typename T> 19712032Sandreas.sandberg@arm.comvoid 19811008Sandreas.sandberg@arm.comarrayParamOut(CheckpointOut &cp, const std::string &name, 19911008Sandreas.sandberg@arm.com const Fifo<T> ¶m) 20011008Sandreas.sandberg@arm.com{ 20111008Sandreas.sandberg@arm.com std::vector<T> temp(param.size()); 20211008Sandreas.sandberg@arm.com param.peek(temp.begin(), temp.size()); 20311008Sandreas.sandberg@arm.com arrayParamOut(cp, name, temp); 20411008Sandreas.sandberg@arm.com} 20511008Sandreas.sandberg@arm.com 20611008Sandreas.sandberg@arm.comtemplate <typename T> 20712032Sandreas.sandberg@arm.comvoid 20811008Sandreas.sandberg@arm.comarrayParamIn(CheckpointIn &cp, const std::string &name, 20911008Sandreas.sandberg@arm.com Fifo<T> ¶m) 21011008Sandreas.sandberg@arm.com{ 21111008Sandreas.sandberg@arm.com std::vector<T> temp; 21211008Sandreas.sandberg@arm.com arrayParamIn(cp, name, temp); 21311008Sandreas.sandberg@arm.com 21411008Sandreas.sandberg@arm.com fatal_if(param.capacity() < temp.size(), 21511008Sandreas.sandberg@arm.com "Trying to unserialize data into too small FIFO\n"); 21611008Sandreas.sandberg@arm.com 21711008Sandreas.sandberg@arm.com param.flush(); 21811008Sandreas.sandberg@arm.com param.write(temp.cbegin(), temp.size()); 21911008Sandreas.sandberg@arm.com} 22011008Sandreas.sandberg@arm.com 22111008Sandreas.sandberg@arm.com#endif // __BASE_CIRCLEBUF_HH__ 222