11060SN/A/*
21762SN/A * Copyright (c) 2004-2005 The Regents of The University of Michigan
31060SN/A * All rights reserved.
41060SN/A *
51060SN/A * Redistribution and use in source and binary forms, with or without
61060SN/A * modification, are permitted provided that the following conditions are
71060SN/A * met: redistributions of source code must retain the above copyright
81060SN/A * notice, this list of conditions and the following disclaimer;
91060SN/A * redistributions in binary form must reproduce the above copyright
101060SN/A * notice, this list of conditions and the following disclaimer in the
111060SN/A * documentation and/or other materials provided with the distribution;
121060SN/A * neither the name of the copyright holders nor the names of its
131060SN/A * contributors may be used to endorse or promote products derived from
141060SN/A * this software without specific prior written permission.
151060SN/A *
161060SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
171060SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
181060SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
191060SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
201060SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
211060SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
221060SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
231060SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
241060SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
251060SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
261060SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
272665SN/A *
282760SN/A * Authors: Nathan Binkert
292760SN/A *          Kevin Lim
301060SN/A */
311060SN/A
321060SN/A#ifndef __BASE_TIMEBUF_HH__
331060SN/A#define __BASE_TIMEBUF_HH__
341060SN/A
352989SN/A#include <cassert>
363918SN/A#include <cstring>
371060SN/A#include <vector>
381060SN/A
391060SN/Atemplate <class T>
401060SN/Aclass TimeBuffer
411060SN/A{
421060SN/A  protected:
431060SN/A    int past;
441060SN/A    int future;
456227SN/A    unsigned size;
465984SN/A    int _id;
471060SN/A
481060SN/A    char *data;
492291SN/A    std::vector<char *> index;
506227SN/A    unsigned base;
511060SN/A
5210200SAndrew.Bardsley@arm.com    void valid(int idx) const
531060SN/A    {
541060SN/A        assert (idx >= -past && idx <= future);
551060SN/A    }
561060SN/A
571060SN/A  public:
581060SN/A    friend class wire;
591060SN/A    class wire
601060SN/A    {
611060SN/A        friend class TimeBuffer;
621060SN/A      protected:
631060SN/A        TimeBuffer<T> *buffer;
641060SN/A        int index;
651060SN/A
661060SN/A        void set(int idx)
671060SN/A        {
681060SN/A            buffer->valid(idx);
691060SN/A            index = idx;
701060SN/A        }
711060SN/A
721060SN/A        wire(TimeBuffer<T> *buf, int i)
731060SN/A            : buffer(buf), index(i)
741060SN/A        { }
751060SN/A
761060SN/A      public:
771060SN/A        wire()
781060SN/A        { }
791060SN/A
801060SN/A        wire(const wire &i)
811060SN/A            : buffer(i.buffer), index(i.index)
821060SN/A        { }
831060SN/A
841060SN/A        const wire &operator=(const wire &i)
851060SN/A        {
861060SN/A            buffer = i.buffer;
871060SN/A            set(i.index);
881060SN/A            return *this;
891060SN/A        }
901060SN/A
911060SN/A        const wire &operator=(int idx)
921060SN/A        {
931060SN/A            set(idx);
941060SN/A            return *this;
951060SN/A        }
961060SN/A
971060SN/A        const wire &operator+=(int offset)
981060SN/A        {
991060SN/A            set(index + offset);
1001060SN/A            return *this;
1011060SN/A        }
1021060SN/A
1031060SN/A        const wire &operator-=(int offset)
1041060SN/A        {
1051060SN/A            set(index - offset);
1061060SN/A            return *this;
1071060SN/A        }
1081060SN/A
1091060SN/A        wire &operator++()
1101060SN/A        {
1111060SN/A            set(index + 1);
1121060SN/A            return *this;
1131060SN/A        }
1141060SN/A
1151060SN/A        wire &operator++(int)
1161060SN/A        {
1171060SN/A            int i = index;
1181060SN/A            set(index + 1);
1191060SN/A            return wire(this, i);
1201060SN/A        }
1211060SN/A
1221060SN/A        wire &operator--()
1231060SN/A        {
1241060SN/A            set(index - 1);
1251060SN/A            return *this;
1261060SN/A        }
1271060SN/A
1281060SN/A        wire &operator--(int)
1291060SN/A        {
1301060SN/A            int i = index;
1311060SN/A            set(index - 1);
1321060SN/A            return wire(this, i);
1331060SN/A        }
1341060SN/A        T &operator*() const { return *buffer->access(index); }
1351060SN/A        T *operator->() const { return buffer->access(index); }
1361060SN/A    };
1371060SN/A
1381060SN/A
1391060SN/A  public:
1401060SN/A    TimeBuffer(int p, int f)
14111320Ssteve.reinhardt@amd.com        : past(p), future(f), size(past + future + 1),
1421060SN/A          data(new char[size * sizeof(T)]), index(size), base(0)
1431060SN/A    {
1441060SN/A        assert(past >= 0 && future >= 0);
1451060SN/A        char *ptr = data;
1466227SN/A        for (unsigned i = 0; i < size; i++) {
1471060SN/A            index[i] = ptr;
1483918SN/A            std::memset(ptr, 0, sizeof(T));
1491060SN/A            new (ptr) T;
1501060SN/A            ptr += sizeof(T);
1511060SN/A        }
1525984SN/A
1535984SN/A        _id = -1;
1541060SN/A    }
1551060SN/A
1561060SN/A    TimeBuffer()
1571060SN/A        : data(NULL)
1581060SN/A    {
1591060SN/A    }
1601060SN/A
1611060SN/A    ~TimeBuffer()
1621060SN/A    {
1636227SN/A        for (unsigned i = 0; i < size; ++i)
1641060SN/A            (reinterpret_cast<T *>(index[i]))->~T();
1651060SN/A        delete [] data;
1661060SN/A    }
1671060SN/A
1685984SN/A    void id(int id)
1695984SN/A    {
1705984SN/A        _id = id;
1715984SN/A    }
1725984SN/A
1735984SN/A    int id()
1745984SN/A    {
1755984SN/A        return _id;
1765984SN/A    }
1775984SN/A
1781060SN/A    void
1791060SN/A    advance()
1801060SN/A    {
1811060SN/A        if (++base >= size)
1821060SN/A            base = 0;
1831060SN/A
1841060SN/A        int ptr = base + future;
1856227SN/A        if (ptr >= (int)size)
1861060SN/A            ptr -= size;
1871060SN/A        (reinterpret_cast<T *>(index[ptr]))->~T();
1883918SN/A        std::memset(index[ptr], 0, sizeof(T));
1891060SN/A        new (index[ptr]) T;
1901060SN/A    }
1911060SN/A
19210200SAndrew.Bardsley@arm.com  protected:
19310200SAndrew.Bardsley@arm.com    //Calculate the index into this->index for element at position idx
19410200SAndrew.Bardsley@arm.com    //relative to now
19510200SAndrew.Bardsley@arm.com    inline int calculateVectorIndex(int idx) const
1961060SN/A    {
1971060SN/A        //Need more complex math here to calculate index.
1981060SN/A        valid(idx);
1991060SN/A
2001060SN/A        int vector_index = idx + base;
2016227SN/A        if (vector_index >= (int)size) {
2021060SN/A            vector_index -= size;
2031060SN/A        } else if (vector_index < 0) {
2041060SN/A            vector_index += size;
2051060SN/A        }
2061060SN/A
20710200SAndrew.Bardsley@arm.com        return vector_index;
20810200SAndrew.Bardsley@arm.com    }
20910200SAndrew.Bardsley@arm.com
21010200SAndrew.Bardsley@arm.com  public:
21110200SAndrew.Bardsley@arm.com    T *access(int idx)
21210200SAndrew.Bardsley@arm.com    {
21310200SAndrew.Bardsley@arm.com        int vector_index = calculateVectorIndex(idx);
21410200SAndrew.Bardsley@arm.com
2151060SN/A        return reinterpret_cast<T *>(index[vector_index]);
2161060SN/A    }
2171060SN/A
2181060SN/A    T &operator[](int idx)
2191060SN/A    {
22010200SAndrew.Bardsley@arm.com        int vector_index = calculateVectorIndex(idx);
2211060SN/A
2221060SN/A        return reinterpret_cast<T &>(*index[vector_index]);
2231060SN/A    }
2241060SN/A
22510200SAndrew.Bardsley@arm.com    const T &operator[] (int idx) const
22610200SAndrew.Bardsley@arm.com    {
22710200SAndrew.Bardsley@arm.com        int vector_index = calculateVectorIndex(idx);
22810200SAndrew.Bardsley@arm.com
22910200SAndrew.Bardsley@arm.com        return reinterpret_cast<const T &>(*index[vector_index]);
23010200SAndrew.Bardsley@arm.com    }
23110200SAndrew.Bardsley@arm.com
2321060SN/A    wire getWire(int idx)
2331060SN/A    {
2341060SN/A        valid(idx);
2351060SN/A
2361060SN/A        return wire(this, idx);
2371060SN/A    }
2381060SN/A
2391060SN/A    wire zero()
2401060SN/A    {
2411060SN/A        return wire(this, 0);
2421060SN/A    }
2432873SN/A
2446227SN/A    unsigned getSize()
2452873SN/A    {
2462873SN/A        return size;
2472873SN/A    }
2481060SN/A};
2491060SN/A
2501060SN/A#endif // __BASE_TIMEBUF_HH__
2511060SN/A
252