| /* |
| * Copyright (c) 2004-2005 The Regents of The University of Michigan |
| * All rights reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions are |
| * met: redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer; |
| * redistributions in binary form must reproduce the above copyright |
| * notice, this list of conditions and the following disclaimer in the |
| * documentation and/or other materials provided with the distribution; |
| * neither the name of the copyright holders nor the names of its |
| * contributors may be used to endorse or promote products derived from |
| * this software without specific prior written permission. |
| * |
| * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
| * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
| * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
| * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| */ |
| |
| #ifndef __BASE_TIMEBUF_HH__ |
| #define __BASE_TIMEBUF_HH__ |
| |
| #include <cassert> |
| #include <cstring> |
| #include <vector> |
| |
| template <class T> |
| class TimeBuffer |
| { |
| protected: |
| int past; |
| int future; |
| unsigned size; |
| int _id; |
| |
| char *data; |
| std::vector<char *> index; |
| unsigned base; |
| |
| void valid(int idx) const |
| { |
| assert (idx >= -past && idx <= future); |
| } |
| |
| public: |
| friend class wire; |
| class wire |
| { |
| friend class TimeBuffer; |
| protected: |
| TimeBuffer<T> *buffer; |
| int index; |
| |
| void set(int idx) |
| { |
| buffer->valid(idx); |
| index = idx; |
| } |
| |
| wire(TimeBuffer<T> *buf, int i) |
| : buffer(buf), index(i) |
| { } |
| |
| public: |
| wire() |
| { } |
| |
| wire(const wire &i) |
| : buffer(i.buffer), index(i.index) |
| { } |
| |
| const wire &operator=(const wire &i) |
| { |
| buffer = i.buffer; |
| set(i.index); |
| return *this; |
| } |
| |
| const wire &operator=(int idx) |
| { |
| set(idx); |
| return *this; |
| } |
| |
| const wire &operator+=(int offset) |
| { |
| set(index + offset); |
| return *this; |
| } |
| |
| const wire &operator-=(int offset) |
| { |
| set(index - offset); |
| return *this; |
| } |
| |
| wire &operator++() |
| { |
| set(index + 1); |
| return *this; |
| } |
| |
| wire &operator++(int) |
| { |
| int i = index; |
| set(index + 1); |
| return wire(this, i); |
| } |
| |
| wire &operator--() |
| { |
| set(index - 1); |
| return *this; |
| } |
| |
| wire &operator--(int) |
| { |
| int i = index; |
| set(index - 1); |
| return wire(this, i); |
| } |
| T &operator*() const { return *buffer->access(index); } |
| T *operator->() const { return buffer->access(index); } |
| }; |
| |
| |
| public: |
| TimeBuffer(int p, int f) |
| : past(p), future(f), size(past + future + 1), |
| data(new char[size * sizeof(T)]), index(size), base(0) |
| { |
| assert(past >= 0 && future >= 0); |
| char *ptr = data; |
| for (unsigned i = 0; i < size; i++) { |
| index[i] = ptr; |
| std::memset(ptr, 0, sizeof(T)); |
| new (ptr) T; |
| ptr += sizeof(T); |
| } |
| |
| _id = -1; |
| } |
| |
| TimeBuffer() |
| : data(NULL) |
| { |
| } |
| |
| ~TimeBuffer() |
| { |
| for (unsigned i = 0; i < size; ++i) |
| (reinterpret_cast<T *>(index[i]))->~T(); |
| delete [] data; |
| } |
| |
| void id(int id) |
| { |
| _id = id; |
| } |
| |
| int id() |
| { |
| return _id; |
| } |
| |
| void |
| advance() |
| { |
| if (++base >= size) |
| base = 0; |
| |
| int ptr = base + future; |
| if (ptr >= (int)size) |
| ptr -= size; |
| (reinterpret_cast<T *>(index[ptr]))->~T(); |
| std::memset(index[ptr], 0, sizeof(T)); |
| new (index[ptr]) T; |
| } |
| |
| protected: |
| //Calculate the index into this->index for element at position idx |
| //relative to now |
| inline int calculateVectorIndex(int idx) const |
| { |
| //Need more complex math here to calculate index. |
| valid(idx); |
| |
| int vector_index = idx + base; |
| if (vector_index >= (int)size) { |
| vector_index -= size; |
| } else if (vector_index < 0) { |
| vector_index += size; |
| } |
| |
| return vector_index; |
| } |
| |
| public: |
| T *access(int idx) |
| { |
| int vector_index = calculateVectorIndex(idx); |
| |
| return reinterpret_cast<T *>(index[vector_index]); |
| } |
| |
| T &operator[](int idx) |
| { |
| int vector_index = calculateVectorIndex(idx); |
| |
| return reinterpret_cast<T &>(*index[vector_index]); |
| } |
| |
| const T &operator[] (int idx) const |
| { |
| int vector_index = calculateVectorIndex(idx); |
| |
| return reinterpret_cast<const T &>(*index[vector_index]); |
| } |
| |
| wire getWire(int idx) |
| { |
| valid(idx); |
| |
| return wire(this, idx); |
| } |
| |
| wire zero() |
| { |
| return wire(this, 0); |
| } |
| |
| unsigned getSize() |
| { |
| return size; |
| } |
| }; |
| |
| #endif // __BASE_TIMEBUF_HH__ |
| |