summaryrefslogtreecommitdiff
path: root/src/systemc/ext/tlm_core/1/req_rsp/channels/fifo/circular_buffer.hh
diff options
context:
space:
mode:
Diffstat (limited to 'src/systemc/ext/tlm_core/1/req_rsp/channels/fifo/circular_buffer.hh')
-rw-r--r--src/systemc/ext/tlm_core/1/req_rsp/channels/fifo/circular_buffer.hh252
1 files changed, 252 insertions, 0 deletions
diff --git a/src/systemc/ext/tlm_core/1/req_rsp/channels/fifo/circular_buffer.hh b/src/systemc/ext/tlm_core/1/req_rsp/channels/fifo/circular_buffer.hh
new file mode 100644
index 000000000..0badaa56f
--- /dev/null
+++ b/src/systemc/ext/tlm_core/1/req_rsp/channels/fifo/circular_buffer.hh
@@ -0,0 +1,252 @@
+/*****************************************************************************
+
+ Licensed to Accellera Systems Initiative Inc. (Accellera) under one or
+ more contributor license agreements. See the NOTICE file distributed
+ with this work for additional information regarding copyright ownership.
+ Accellera licenses this file to you under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with the
+ License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied. See the License for the specific language governing
+ permissions and limitations under the License.
+
+ *****************************************************************************/
+
+#ifndef __TLM_CORE_1_REQ_RSP_CHANNELS_FIFO_CIRCULAR_BUFFER_HH__
+#define __TLM_CORE_1_REQ_RSP_CHANNELS_FIFO_CIRCULAR_BUFFER_HH__
+
+#include <iostream>
+
+namespace tlm
+{
+
+template <typename T>
+class circular_buffer
+{
+ public:
+ explicit circular_buffer(int size=0);
+ ~circular_buffer();
+
+ void resize(int size);
+ void clear();
+
+ T read();
+ void write(const T &);
+
+ bool is_empty() const { return used() == 0; }
+ bool is_full() const { return free() == 0; }
+
+ int size() const { return m_size; }
+ int used() const { return m_used; }
+ int free() const { return m_free; }
+
+ const T &read_data() const { return buf_read(m_buf, m_ri); }
+ const T &
+ peek_data(int i) const
+ {
+ return buf_read(m_buf, (m_ri + i) % size());
+ }
+
+ T &
+ poke_data(int i)
+ {
+ return buf_read(m_buf, (m_wi + i) % size());
+ }
+
+ void debug() const;
+
+ private:
+ void increment_write_pos(int i=1);
+ void increment_read_pos(int i=1);
+
+ void init();
+
+ // Disabled.
+ circular_buffer(const circular_buffer<T> &b);
+ circular_buffer<T> &operator = (const circular_buffer<T> &);
+
+ void *buf_alloc(int size);
+ void buf_free(void *&buf);
+ void buf_write(void *buf, int n, const T &t);
+ T &buf_read(void *buf, int n) const;
+ void buf_clear(void *buf, int n);
+
+ private:
+ int m_size; // size of the buffer
+ void *m_buf; // the buffer
+ int m_free; // number of free spaces
+ int m_used; // number of used spaces
+ int m_ri; // index of next read
+ int m_wi; // index of next write
+};
+
+template <typename T>
+void
+circular_buffer<T>::debug() const
+{
+ std::cout << "Buffer debug" << std::endl;
+ std::cout << "Size : " << size() << std::endl;
+ std::cout << "Free/Used " << free() << "/" << used() << std::endl;
+ std::cout << "Indices : r/w = " << m_ri << "/" << m_wi << std::endl;
+
+ if (is_empty()) {
+ std::cout << "empty" << std::endl;
+ }
+
+ if (is_full()) {
+ std::cout << "full" << std::endl;
+ }
+
+ std::cout << "Data : " << std::endl;
+ for (int i = 0; i < used(); i++) {
+ std::cout << peek_data( i ) << std::endl;
+ }
+}
+
+template <typename T>
+circular_buffer<T>::circular_buffer(int size) : m_size(size), m_buf(0)
+{
+ init();
+}
+
+template <typename T>
+void
+circular_buffer<T>::clear()
+{
+ for (int i = 0; i < used(); i++) {
+ buf_clear(m_buf, (m_ri + i) % m_size);
+ }
+ m_free = m_size;
+ m_used = m_ri = m_wi = 0;
+}
+
+template <typename T>
+circular_buffer<T>::~circular_buffer()
+{
+ clear();
+ buf_free(m_buf);
+}
+
+template <typename T>
+void
+circular_buffer<T>::resize(int size)
+{
+ int i;
+ void *new_buf = buf_alloc(size);
+
+ for (i = 0; i < size && i < used(); i++) {
+ buf_write(new_buf, i, peek_data(i));
+ buf_clear(m_buf, (m_ri + i) % m_size);
+ }
+
+ buf_free(m_buf);
+
+ m_size = size;
+ m_ri = 0;
+ m_wi = i % m_size;
+ m_used = i;
+ m_free = m_size - m_used;
+
+ m_buf = new_buf;
+}
+
+
+template <typename T>
+void
+circular_buffer<T>::init()
+{
+ if (m_size > 0) {
+ m_buf = buf_alloc(m_size);
+ }
+
+ m_free = m_size;
+ m_used = 0;
+ m_ri = 0;
+ m_wi = 0;
+}
+
+template <typename T>
+T
+circular_buffer<T>::read()
+{
+ T t = read_data();
+
+ buf_clear(m_buf, m_ri);
+ increment_read_pos();
+
+ return t;
+}
+
+template <typename T>
+void
+circular_buffer<T>::write(const T &t)
+{
+ buf_write(m_buf, m_wi, t);
+ increment_write_pos();
+}
+
+template <typename T>
+void
+circular_buffer<T>::increment_write_pos(int i)
+{
+ m_wi = (m_wi + i) % m_size;
+ m_used += i;
+ m_free -= i;
+}
+
+template <typename T>
+void
+circular_buffer<T>::increment_read_pos(int i)
+{
+ m_ri = (m_ri + i) % m_size;
+ m_used -= i;
+ m_free += i;
+}
+
+template <typename T>
+inline void *
+circular_buffer<T>::buf_alloc(int size)
+{
+ return new unsigned char [size * sizeof(T)];
+}
+
+template <typename T>
+inline void
+circular_buffer<T>::buf_free(void *&buf)
+{
+ delete [] static_cast<unsigned char *>(buf);
+ buf = nullptr;
+}
+
+template <typename T>
+inline void
+circular_buffer<T>::buf_write(void *buf, int n, const T &t)
+{
+ T *p = static_cast<T *>(buf) + n;
+ new (p)T(t);
+}
+
+template <typename T>
+inline T &
+circular_buffer<T>::buf_read(void *buf, int n) const
+{
+ T *p = static_cast<T *>(buf) + n;
+ return *p;
+}
+
+template <typename T>
+inline void
+circular_buffer<T>::buf_clear(void *buf, int n)
+{
+ T *p = static_cast<T *>(buf) + n;
+ p->~T();
+}
+
+} // namespace tlm
+
+#endif /* __TLM_CORE_1_REQ_RSP_CHANNELS_FIFO_CIRCULAR_BUFFER_HH__ */