TLM-2.0  2.0.3
Accellera TLM-2.0 proof-of-concept library
circular_buffer.h
Go to the documentation of this file.
1 /*****************************************************************************
2 
3  The following code is derived, directly or indirectly, from the SystemC
4  source code Copyright (c) 1996-2014 by all Contributors.
5  All Rights reserved.
6 
7  The contents of this file are subject to the restrictions and limitations
8  set forth in the SystemC Open Source License (the "License");
9  You may not use this file except in compliance with such restrictions and
10  limitations. You may obtain instructions on how to receive a copy of the
11  License at http://www.accellera.org/. Software distributed by Contributors
12  under the License is distributed on an "AS IS" basis, WITHOUT WARRANTY OF
13  ANY KIND, either express or implied. See the License for the specific
14  language governing rights and limitations under the License.
15 
16  *****************************************************************************/
17 
18 //
19 // To the LRM writer : this class is purely an artifact of the implementation.
20 //
21 
22 #ifndef __CIRCULAR_BUFFER_H__
23 #define __CIRCULAR_BUFFER_H__
24 
25 #include <iostream>
26 
27 namespace tlm {
28 
29 template < typename T >
31 {
32 public:
33 
34  explicit
35  circular_buffer( int size = 0 );
37 
38  void resize( int size );
39  void clear();
40 
41  T read();
42  void write( const T & );
43 
44  bool is_empty() const { return used() == 0; }
45  bool is_full() const { return free() == 0; }
46 
47  int size() const { return m_size; }
48  int used() const { return m_used; }
49  int free() const { return m_free; }
50 
51  const T& read_data() const
52  { return buf_read( m_buf, m_ri ); }
53 
54  const T& peek_data( int i ) const
55  { return buf_read( m_buf, (m_ri + i) % size() ); }
56 
57  T & poke_data( int i )
58  { return buf_read( m_buf , (m_wi + i) % size() ); }
59 
60  void debug() const;
61 
62 private:
63  void increment_write_pos( int i = 1 );
64  void increment_read_pos( int i = 1 );
65 
66  void init();
67 
68  circular_buffer( const circular_buffer<T> &b ); // disabled
69  circular_buffer<T> &operator=( const circular_buffer<T> & ); // disabled
70 
71  void* buf_alloc( int size );
72  void buf_free( void*& buf );
73  void buf_write( void* buf, int n, const T & t );
74  T& buf_read( void* buf, int n ) const;
75  void buf_clear( void* buf, int n );
76 
77 private:
78  int m_size; // size of the buffer
79  void* m_buf; // the buffer
80  int m_free; // number of free spaces
81  int m_used; // number of used spaces
82  int m_ri; // index of next read
83  int m_wi; // index of next write
84 
85 };
86 
87 template< typename T >
88 void
90 {
91 
92  std::cout << "Buffer debug" << std::endl;
93  std::cout << "Size : " << size() << std::endl;
94  std::cout << "Free/Used " << free() << "/" << used() << std::endl;
95  std::cout << "Indices : r/w = " << m_ri << "/" << m_wi << std::endl;
96 
97  if( is_empty() ) {
98 
99  std::cout << "empty" << std::endl;
100 
101  }
102 
103  if( is_full() ) {
104 
105  std::cout << "full" << std::endl;
106 
107  }
108 
109  std::cout << "Data : " << std::endl;
110  for( int i = 0; i < used(); i++ ) {
111 
112  std::cout << peek_data( i ) << std::endl;
113 
114  }
115 
116 
117 }
118 
119 template < typename T >
121  : m_size(size)
122  , m_buf(0)
123 {
124  init();
125 
126 }
127 
128 template < typename T >
129 void
131 {
132  for( int i=0; i < used(); i++ ) {
133  buf_clear( m_buf, i );
134  }
135  m_free = m_size;
136  m_used = m_ri = m_wi = 0;
137 }
138 
139 template < typename T >
141 {
142  clear();
143  buf_free( m_buf );
144 }
145 
146 template < typename T >
147 void
149 {
150 
151  int i;
152  void * new_buf = buf_alloc(size);
153 
154  for( i = 0; i < size && i < used(); i++ ) {
155 
156  buf_write( new_buf, i, peek_data( i ) );
157  buf_clear( m_buf, (m_ri + i) % m_size );
158 
159  }
160 
161  buf_free( m_buf );
162 
163  m_size = size;
164  m_ri = 0;
165  m_wi = i % m_size;
166  m_used = i;
167  m_free = m_size - m_used;
168 
169  m_buf = new_buf;
170 }
171 
172 
173 template < typename T >
174 void
176 
177  if( m_size > 0 ) {
178  m_buf = buf_alloc( m_size );
179  }
180 
181  m_free = m_size;
182  m_used = 0;
183  m_ri = 0;
184  m_wi = 0;
185 
186 }
187 
188 template < typename T >
189 T
191 {
192  T t = read_data();
193 
194  buf_clear( m_buf, m_ri );
195  increment_read_pos();
196 
197  return t;
198 }
199 
200 template < typename T >
201 void
203 {
204  buf_write( m_buf, m_wi, t );
205  increment_write_pos();
206 }
207 
208 
209 template < typename T >
210 void
212 
213  m_wi = ( m_wi + i ) % m_size;
214  m_used += i;
215  m_free -= i;
216 
217 }
218 
219 template < typename T >
220 void
221 circular_buffer<T>::increment_read_pos( int i ) {
222 
223  m_ri = ( m_ri + i ) % m_size;
224  m_used -= i;
225  m_free += i;
226 
227 }
228 
229 template < typename T >
230 inline void*
231 circular_buffer<T>::buf_alloc( int size )
232  { return new unsigned char[ size * sizeof(T) ]; }
233 
234 template < typename T >
235 inline void
236 circular_buffer<T>::buf_free( void* & buf )
237  { delete [] static_cast<unsigned char*>(buf); buf = 0; }
238 
239 template < typename T >
240 inline void
241 circular_buffer<T>::buf_write( void* buf, int n, const T & t )
242 {
243  T* p = static_cast<T*>(buf) + n;
244  new (p) T(t);
245 }
246 
247 template < typename T >
248 inline T&
249 circular_buffer<T>::buf_read( void* buf, int n ) const
250 {
251  T* p = static_cast<T*>(buf) + n;
252  return *p;
253 }
254 
255 template < typename T >
256 inline void
257 circular_buffer<T>::buf_clear( void* buf, int n )
258 {
259  T* p = static_cast<T*>(buf) + n;
260  p->~T();
261 }
262 
263 } // namespace tlm
264 
265 #endif
266 
void resize(int size)
bool is_full() const
circular_buffer(int size=0)
const T & read_data() const
void write(const T &)
const T & peek_data(int i) const
bool is_empty() const