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