1/* 2 * Copyright (c) 2004-2005 The Regents of The University of Michigan 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are 7 * met: redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer; 9 * redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution; 12 * neither the name of the copyright holders nor the names of its 13 * contributors may be used to endorse or promote products derived from 14 * this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 * 28 * Authors: Nathan Binkert 29 * Kevin Lim 30 */ 31 32#ifndef __BASE_TIMEBUF_HH__ 33#define __BASE_TIMEBUF_HH__ 34 35#include <cassert> 36#include <cstring> 37#include <vector> 38 39template <class T> 40class TimeBuffer 41{ 42 protected: 43 int past; 44 int future; 45 unsigned size; 46 int _id; 47 48 char *data; 49 std::vector<char *> index; 50 unsigned base; 51 52 void valid(int idx) const 53 { 54 assert (idx >= -past && idx <= future); 55 } 56 57 public: 58 friend class wire; 59 class wire 60 { 61 friend class TimeBuffer; 62 protected: 63 TimeBuffer<T> *buffer; 64 int index; 65 66 void set(int idx) 67 { 68 buffer->valid(idx); 69 index = idx; 70 } 71 72 wire(TimeBuffer<T> *buf, int i) 73 : buffer(buf), index(i) 74 { } 75 76 public: 77 wire() 78 { } 79 80 wire(const wire &i) 81 : buffer(i.buffer), index(i.index) 82 { } 83 84 const wire &operator=(const wire &i) 85 { 86 buffer = i.buffer; 87 set(i.index); 88 return *this; 89 } 90 91 const wire &operator=(int idx) 92 { 93 set(idx); 94 return *this; 95 } 96 97 const wire &operator+=(int offset) 98 { 99 set(index + offset); 100 return *this; 101 } 102 103 const wire &operator-=(int offset) 104 { 105 set(index - offset); 106 return *this; 107 } 108 109 wire &operator++() 110 { 111 set(index + 1); 112 return *this; 113 } 114 115 wire &operator++(int) 116 { 117 int i = index; 118 set(index + 1); 119 return wire(this, i); 120 } 121 122 wire &operator--() 123 { 124 set(index - 1); 125 return *this; 126 } 127 128 wire &operator--(int) 129 { 130 int i = index; 131 set(index - 1); 132 return wire(this, i); 133 } 134 T &operator*() const { return *buffer->access(index); } 135 T *operator->() const { return buffer->access(index); } 136 }; 137 138 139 public: 140 TimeBuffer(int p, int f) 141 : past(p), future(f), size(past + future + 1), 142 data(new char[size * sizeof(T)]), index(size), base(0) 143 { 144 assert(past >= 0 && future >= 0); 145 char *ptr = data; 146 for (unsigned i = 0; i < size; i++) { 147 index[i] = ptr; 148 std::memset(ptr, 0, sizeof(T)); 149 new (ptr) T; 150 ptr += sizeof(T); 151 } 152 153 _id = -1; 154 } 155 156 TimeBuffer() 157 : data(NULL) 158 { 159 } 160 161 ~TimeBuffer() 162 { 163 for (unsigned i = 0; i < size; ++i) 164 (reinterpret_cast<T *>(index[i]))->~T(); 165 delete [] data; 166 } 167 168 void id(int id) 169 { 170 _id = id; 171 } 172 173 int id() 174 { 175 return _id; 176 } 177 178 void 179 advance() 180 { 181 if (++base >= size) 182 base = 0; 183 184 int ptr = base + future; 185 if (ptr >= (int)size) 186 ptr -= size; 187 (reinterpret_cast<T *>(index[ptr]))->~T(); 188 std::memset(index[ptr], 0, sizeof(T)); 189 new (index[ptr]) T; 190 } 191 192 protected: 193 //Calculate the index into this->index for element at position idx 194 //relative to now 195 inline int calculateVectorIndex(int idx) const 196 { 197 //Need more complex math here to calculate index. 198 valid(idx); 199 200 int vector_index = idx + base; 201 if (vector_index >= (int)size) { 202 vector_index -= size; 203 } else if (vector_index < 0) { 204 vector_index += size; 205 } 206 207 return vector_index; 208 } 209 210 public: 211 T *access(int idx) 212 { 213 int vector_index = calculateVectorIndex(idx); 214 215 return reinterpret_cast<T *>(index[vector_index]); 216 } 217 218 T &operator[](int idx) 219 { 220 int vector_index = calculateVectorIndex(idx); 221 222 return reinterpret_cast<T &>(*index[vector_index]); 223 } 224 225 const T &operator[] (int idx) const 226 { 227 int vector_index = calculateVectorIndex(idx); 228 229 return reinterpret_cast<const T &>(*index[vector_index]); 230 } 231 232 wire getWire(int idx) 233 { 234 valid(idx); 235 236 return wire(this, idx); 237 } 238 239 wire zero() 240 { 241 return wire(this, 0); 242 } 243 244 unsigned getSize() 245 { 246 return size; 247 } 248}; 249 250#endif // __BASE_TIMEBUF_HH__ 251 252