113521Sgabeblack@google.com/*****************************************************************************
213521Sgabeblack@google.com
313521Sgabeblack@google.com  Licensed to Accellera Systems Initiative Inc. (Accellera) under one or
413521Sgabeblack@google.com  more contributor license agreements.  See the NOTICE file distributed
513521Sgabeblack@google.com  with this work for additional information regarding copyright ownership.
613521Sgabeblack@google.com  Accellera licenses this file to you under the Apache License, Version 2.0
713521Sgabeblack@google.com  (the "License"); you may not use this file except in compliance with the
813521Sgabeblack@google.com  License.  You may obtain a copy of the License at
913521Sgabeblack@google.com
1013521Sgabeblack@google.com    http://www.apache.org/licenses/LICENSE-2.0
1113521Sgabeblack@google.com
1213521Sgabeblack@google.com  Unless required by applicable law or agreed to in writing, software
1313521Sgabeblack@google.com  distributed under the License is distributed on an "AS IS" BASIS,
1413521Sgabeblack@google.com  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
1513521Sgabeblack@google.com  implied.  See the License for the specific language governing
1613521Sgabeblack@google.com  permissions and limitations under the License.
1713521Sgabeblack@google.com
1813521Sgabeblack@google.com *****************************************************************************/
1913521Sgabeblack@google.com
2013521Sgabeblack@google.com#ifndef __TLM_CORE_1_REQ_RSP_CHANNELS_FIFO_CIRCULAR_BUFFER_HH__
2113521Sgabeblack@google.com#define __TLM_CORE_1_REQ_RSP_CHANNELS_FIFO_CIRCULAR_BUFFER_HH__
2213521Sgabeblack@google.com
2313521Sgabeblack@google.com#include <iostream>
2413521Sgabeblack@google.com
2513521Sgabeblack@google.comnamespace tlm
2613521Sgabeblack@google.com{
2713521Sgabeblack@google.com
2813521Sgabeblack@google.comtemplate <typename T>
2913521Sgabeblack@google.comclass circular_buffer
3013521Sgabeblack@google.com{
3113521Sgabeblack@google.com  public:
3213521Sgabeblack@google.com    explicit circular_buffer(int size=0);
3313521Sgabeblack@google.com    ~circular_buffer();
3413521Sgabeblack@google.com
3513521Sgabeblack@google.com    void resize(int size);
3613521Sgabeblack@google.com    void clear();
3713521Sgabeblack@google.com
3813521Sgabeblack@google.com    T read();
3913521Sgabeblack@google.com    void write(const T &);
4013521Sgabeblack@google.com
4113521Sgabeblack@google.com    bool is_empty() const { return used() == 0; }
4213521Sgabeblack@google.com    bool is_full() const { return free() == 0; }
4313521Sgabeblack@google.com
4413521Sgabeblack@google.com    int size() const { return m_size; }
4513521Sgabeblack@google.com    int used() const { return m_used; }
4613521Sgabeblack@google.com    int free() const { return m_free; }
4713521Sgabeblack@google.com
4813521Sgabeblack@google.com    const T &read_data() const { return buf_read(m_buf, m_ri); }
4913521Sgabeblack@google.com    const T &
5013521Sgabeblack@google.com    peek_data(int i) const
5113521Sgabeblack@google.com    {
5213521Sgabeblack@google.com        return buf_read(m_buf, (m_ri + i) % size());
5313521Sgabeblack@google.com    }
5413521Sgabeblack@google.com
5513521Sgabeblack@google.com    T &
5613521Sgabeblack@google.com    poke_data(int i)
5713521Sgabeblack@google.com    {
5813521Sgabeblack@google.com        return buf_read(m_buf, (m_wi + i) % size());
5913521Sgabeblack@google.com    }
6013521Sgabeblack@google.com
6113521Sgabeblack@google.com    void debug() const;
6213521Sgabeblack@google.com
6313521Sgabeblack@google.com  private:
6413521Sgabeblack@google.com    void increment_write_pos(int i=1);
6513521Sgabeblack@google.com    void increment_read_pos(int i=1);
6613521Sgabeblack@google.com
6713521Sgabeblack@google.com    void init();
6813521Sgabeblack@google.com
6913521Sgabeblack@google.com    // Disabled.
7013521Sgabeblack@google.com    circular_buffer(const circular_buffer<T> &b);
7113521Sgabeblack@google.com    circular_buffer<T> &operator = (const circular_buffer<T> &);
7213521Sgabeblack@google.com
7313521Sgabeblack@google.com    void *buf_alloc(int size);
7413521Sgabeblack@google.com    void buf_free(void *&buf);
7513521Sgabeblack@google.com    void buf_write(void *buf, int n, const T &t);
7613521Sgabeblack@google.com    T &buf_read(void *buf, int n) const;
7713521Sgabeblack@google.com    void buf_clear(void *buf, int n);
7813521Sgabeblack@google.com
7913521Sgabeblack@google.com  private:
8013521Sgabeblack@google.com    int m_size; // size of the buffer
8113521Sgabeblack@google.com    void *m_buf; // the buffer
8213521Sgabeblack@google.com    int m_free; // number of free spaces
8313521Sgabeblack@google.com    int m_used; // number of used spaces
8413521Sgabeblack@google.com    int m_ri; // index of next read
8513521Sgabeblack@google.com    int m_wi; // index of next write
8613521Sgabeblack@google.com};
8713521Sgabeblack@google.com
8813521Sgabeblack@google.comtemplate <typename T>
8913521Sgabeblack@google.comvoid
9013521Sgabeblack@google.comcircular_buffer<T>::debug() const
9113521Sgabeblack@google.com{
9213521Sgabeblack@google.com    std::cout << "Buffer debug" << std::endl;
9313521Sgabeblack@google.com    std::cout << "Size : " << size() << std::endl;
9413521Sgabeblack@google.com    std::cout << "Free/Used " << free() << "/" << used() << std::endl;
9513521Sgabeblack@google.com    std::cout << "Indices : r/w = " << m_ri << "/" << m_wi << std::endl;
9613521Sgabeblack@google.com
9713521Sgabeblack@google.com    if (is_empty()) {
9813521Sgabeblack@google.com        std::cout << "empty" << std::endl;
9913521Sgabeblack@google.com    }
10013521Sgabeblack@google.com
10113521Sgabeblack@google.com    if (is_full()) {
10213521Sgabeblack@google.com        std::cout << "full" << std::endl;
10313521Sgabeblack@google.com    }
10413521Sgabeblack@google.com
10513521Sgabeblack@google.com    std::cout << "Data : " << std::endl;
10613521Sgabeblack@google.com    for (int i = 0; i < used(); i++) {
10713521Sgabeblack@google.com        std::cout << peek_data( i ) << std::endl;
10813521Sgabeblack@google.com    }
10913521Sgabeblack@google.com}
11013521Sgabeblack@google.com
11113521Sgabeblack@google.comtemplate <typename T>
11213521Sgabeblack@google.comcircular_buffer<T>::circular_buffer(int size) : m_size(size), m_buf(0)
11313521Sgabeblack@google.com{
11413521Sgabeblack@google.com    init();
11513521Sgabeblack@google.com}
11613521Sgabeblack@google.com
11713521Sgabeblack@google.comtemplate <typename T>
11813521Sgabeblack@google.comvoid
11913521Sgabeblack@google.comcircular_buffer<T>::clear()
12013521Sgabeblack@google.com{
12113521Sgabeblack@google.com    for (int i = 0; i < used(); i++) {
12213521Sgabeblack@google.com        buf_clear(m_buf, (m_ri + i) % m_size);
12313521Sgabeblack@google.com    }
12413521Sgabeblack@google.com    m_free = m_size;
12513521Sgabeblack@google.com    m_used = m_ri = m_wi = 0;
12613521Sgabeblack@google.com}
12713521Sgabeblack@google.com
12813521Sgabeblack@google.comtemplate <typename T>
12913521Sgabeblack@google.comcircular_buffer<T>::~circular_buffer()
13013521Sgabeblack@google.com{
13113521Sgabeblack@google.com    clear();
13213521Sgabeblack@google.com    buf_free(m_buf);
13313521Sgabeblack@google.com}
13413521Sgabeblack@google.com
13513521Sgabeblack@google.comtemplate <typename T>
13613521Sgabeblack@google.comvoid
13713521Sgabeblack@google.comcircular_buffer<T>::resize(int size)
13813521Sgabeblack@google.com{
13913521Sgabeblack@google.com    int i;
14013521Sgabeblack@google.com    void *new_buf = buf_alloc(size);
14113521Sgabeblack@google.com
14213521Sgabeblack@google.com    for (i = 0; i < size && i < used(); i++) {
14313521Sgabeblack@google.com        buf_write(new_buf, i, peek_data(i));
14413521Sgabeblack@google.com        buf_clear(m_buf, (m_ri + i) % m_size);
14513521Sgabeblack@google.com    }
14613521Sgabeblack@google.com
14713521Sgabeblack@google.com    buf_free(m_buf);
14813521Sgabeblack@google.com
14913521Sgabeblack@google.com    m_size = size;
15013521Sgabeblack@google.com    m_ri = 0;
15113521Sgabeblack@google.com    m_wi = i % m_size;
15213521Sgabeblack@google.com    m_used = i;
15313521Sgabeblack@google.com    m_free = m_size - m_used;
15413521Sgabeblack@google.com
15513521Sgabeblack@google.com    m_buf = new_buf;
15613521Sgabeblack@google.com}
15713521Sgabeblack@google.com
15813521Sgabeblack@google.com
15913521Sgabeblack@google.comtemplate <typename T>
16013521Sgabeblack@google.comvoid
16113521Sgabeblack@google.comcircular_buffer<T>::init()
16213521Sgabeblack@google.com{
16313521Sgabeblack@google.com    if (m_size > 0) {
16413521Sgabeblack@google.com        m_buf = buf_alloc(m_size);
16513521Sgabeblack@google.com    }
16613521Sgabeblack@google.com
16713521Sgabeblack@google.com    m_free = m_size;
16813521Sgabeblack@google.com    m_used = 0;
16913521Sgabeblack@google.com    m_ri = 0;
17013521Sgabeblack@google.com    m_wi = 0;
17113521Sgabeblack@google.com}
17213521Sgabeblack@google.com
17313521Sgabeblack@google.comtemplate <typename T>
17413521Sgabeblack@google.comT
17513521Sgabeblack@google.comcircular_buffer<T>::read()
17613521Sgabeblack@google.com{
17713521Sgabeblack@google.com    T t = read_data();
17813521Sgabeblack@google.com
17913521Sgabeblack@google.com    buf_clear(m_buf, m_ri);
18013521Sgabeblack@google.com    increment_read_pos();
18113521Sgabeblack@google.com
18213521Sgabeblack@google.com    return t;
18313521Sgabeblack@google.com}
18413521Sgabeblack@google.com
18513521Sgabeblack@google.comtemplate <typename T>
18613521Sgabeblack@google.comvoid
18713521Sgabeblack@google.comcircular_buffer<T>::write(const T &t)
18813521Sgabeblack@google.com{
18913521Sgabeblack@google.com    buf_write(m_buf, m_wi, t);
19013521Sgabeblack@google.com    increment_write_pos();
19113521Sgabeblack@google.com}
19213521Sgabeblack@google.com
19313521Sgabeblack@google.comtemplate <typename T>
19413521Sgabeblack@google.comvoid
19513521Sgabeblack@google.comcircular_buffer<T>::increment_write_pos(int i)
19613521Sgabeblack@google.com{
19713521Sgabeblack@google.com    m_wi = (m_wi + i) % m_size;
19813521Sgabeblack@google.com    m_used += i;
19913521Sgabeblack@google.com    m_free -= i;
20013521Sgabeblack@google.com}
20113521Sgabeblack@google.com
20213521Sgabeblack@google.comtemplate <typename T>
20313521Sgabeblack@google.comvoid
20413521Sgabeblack@google.comcircular_buffer<T>::increment_read_pos(int i)
20513521Sgabeblack@google.com{
20613521Sgabeblack@google.com    m_ri = (m_ri + i) % m_size;
20713521Sgabeblack@google.com    m_used -= i;
20813521Sgabeblack@google.com    m_free += i;
20913521Sgabeblack@google.com}
21013521Sgabeblack@google.com
21113521Sgabeblack@google.comtemplate <typename T>
21213521Sgabeblack@google.cominline void *
21313521Sgabeblack@google.comcircular_buffer<T>::buf_alloc(int size)
21413521Sgabeblack@google.com{
21513521Sgabeblack@google.com    return new unsigned char [size * sizeof(T)];
21613521Sgabeblack@google.com}
21713521Sgabeblack@google.com
21813521Sgabeblack@google.comtemplate <typename T>
21913521Sgabeblack@google.cominline void
22013521Sgabeblack@google.comcircular_buffer<T>::buf_free(void *&buf)
22113521Sgabeblack@google.com{
22213521Sgabeblack@google.com    delete [] static_cast<unsigned char *>(buf);
22313521Sgabeblack@google.com    buf = nullptr;
22413521Sgabeblack@google.com}
22513521Sgabeblack@google.com
22613521Sgabeblack@google.comtemplate <typename T>
22713521Sgabeblack@google.cominline void
22813521Sgabeblack@google.comcircular_buffer<T>::buf_write(void *buf, int n, const T &t)
22913521Sgabeblack@google.com{
23013521Sgabeblack@google.com    T *p = static_cast<T *>(buf) + n;
23113521Sgabeblack@google.com    new (p)T(t);
23213521Sgabeblack@google.com}
23313521Sgabeblack@google.com
23413521Sgabeblack@google.comtemplate <typename T>
23513521Sgabeblack@google.cominline T &
23613521Sgabeblack@google.comcircular_buffer<T>::buf_read(void *buf, int n) const
23713521Sgabeblack@google.com{
23813521Sgabeblack@google.com    T *p = static_cast<T *>(buf) + n;
23913521Sgabeblack@google.com    return *p;
24013521Sgabeblack@google.com}
24113521Sgabeblack@google.com
24213521Sgabeblack@google.comtemplate <typename T>
24313521Sgabeblack@google.cominline void
24413521Sgabeblack@google.comcircular_buffer<T>::buf_clear(void *buf, int n)
24513521Sgabeblack@google.com{
24613521Sgabeblack@google.com    T *p = static_cast<T *>(buf) + n;
24713521Sgabeblack@google.com    p->~T();
24813521Sgabeblack@google.com}
24913521Sgabeblack@google.com
25013521Sgabeblack@google.com} // namespace tlm
25113521Sgabeblack@google.com
25213521Sgabeblack@google.com#endif /* __TLM_CORE_1_REQ_RSP_CHANNELS_FIFO_CIRCULAR_BUFFER_HH__ */
253