00001 /***************************************************************************** 00002 00003 The following code is derived, directly or indirectly, from the SystemC 00004 source code Copyright (c) 1996-2008 by all Contributors. 00005 All Rights reserved. 00006 00007 The contents of this file are subject to the restrictions and limitations 00008 set forth in the SystemC Open Source License Version 3.0 (the "License"); 00009 You may not use this file except in compliance with such restrictions and 00010 limitations. You may obtain instructions on how to receive a copy of the 00011 License at http://www.systemc.org/. Software distributed by Contributors 00012 under the License is distributed on an "AS IS" basis, WITHOUT WARRANTY OF 00013 ANY KIND, either express or implied. See the License for the specific 00014 language governing rights and limitations under the License. 00015 00016 *****************************************************************************/ 00017 00018 // 00019 // To the LRM writer : this class is purely an artifact of the implementation. 00020 // 00021 00022 #ifndef __CIRCULAR_BUFFER_H__ 00023 #define __CIRCULAR_BUFFER_H__ 00024 00025 #include <iostream> 00026 00027 namespace tlm { 00028 00029 template < typename T > 00030 class circular_buffer 00031 { 00032 public: 00033 circular_buffer( int size ); 00034 00035 circular_buffer<T> &operator=( const circular_buffer<T> & ); 00036 00037 ‾circular_buffer() { delete [] m_buf; } 00038 00039 void resize( int size ); 00040 00041 const T &read(); 00042 void write( const T & ); 00043 00044 bool is_empty() const { return used() == 0; } 00045 bool is_full() const { return free() == 0; } 00046 00047 int size() const { return m_size; } 00048 int used() const { return m_used; } 00049 int free() const { return m_free; } 00050 00051 T &write_data() { return m_buf[m_wi]; } 00052 const T &read_data() const { return m_buf[m_ri]; } 00053 00054 const T &peek_data( int i ) const { return m_buf[(m_ri + i) % size()]; } 00055 T &poke_data( int i ) { return m_buf[(m_ri + i) % size()]; } 00056 00057 void increment_write_pos( int i = 1 ); 00058 void increment_read_pos( int i = 1 ); 00059 00060 void init(); 00061 00062 void debug() const; 00063 00064 private: 00065 circular_buffer( const circular_buffer<T> &b ); // disabled 00066 void copy( const circular_buffer<T> &b ); 00067 00068 private: 00069 int m_size; // size of the buffer 00070 T* m_buf; // the buffer 00071 int m_free; // number of free spaces 00072 int m_used; // number of used spaces 00073 int m_ri; // index of next read 00074 int m_wi; // index of next write 00075 00076 }; 00077 00078 template< typename T > 00079 void 00080 circular_buffer<T>::debug() const 00081 { 00082 00083 std::cout << "Buffer debug" << std::endl; 00084 std::cout << "Size : " << size() << std::endl; 00085 std::cout << "Free/Used " << free() << "/" << used() << std::endl; 00086 std::cout << "Indeces : r/w = " << m_ri << "/" << m_wi << std::endl; 00087 00088 if( is_empty() ) { 00089 00090 std::cout << "empty" << std::endl; 00091 00092 } 00093 00094 if( is_full() ) { 00095 00096 std::cout << "full" << std::endl; 00097 00098 } 00099 00100 std::cout << "Data : " << std::endl; 00101 for( int i = 0; i < used(); i++ ) { 00102 00103 std::cout << peek_data( i ) << std::endl; 00104 00105 } 00106 00107 00108 } 00109 00110 template < typename T > 00111 circular_buffer<T>:: 00112 circular_buffer( int size ) { 00113 00114 m_size = size; 00115 m_buf = new T[m_size]; 00116 00117 init(); 00118 00119 } 00120 00121 template < typename T > 00122 circular_buffer<T> & 00123 circular_buffer<T>::operator=( const circular_buffer<T> &b ) { 00124 00125 init(); 00126 00127 for( int i = 0; i < size() && i < b.used(); i++ ) { 00128 00129 write( b.peek_data( i ) ); 00130 00131 } 00132 00133 return *this; 00134 00135 } 00136 00137 template < typename T > 00138 void 00139 circular_buffer<T>::resize( int size ) 00140 { 00141 00142 int i; 00143 T *new_buf = new T[size]; 00144 00145 for( i = 0; i < size && i < used(); i++ ) { 00146 00147 new_buf[i] = peek_data( i ); 00148 00149 } 00150 00151 delete [] m_buf; 00152 00153 m_size = size; 00154 m_ri = 0; 00155 m_wi = i % m_size; 00156 m_used = i; 00157 m_free = m_size - m_used; 00158 00159 m_buf = new_buf; 00160 00161 } 00162 00163 00164 template < typename T > 00165 void 00166 circular_buffer<T>::init() { 00167 00168 m_free = m_size; 00169 m_used = 0; 00170 m_ri = 0; 00171 m_wi = 0; 00172 00173 } 00174 00175 template < typename T > 00176 void 00177 circular_buffer<T>::copy( const circular_buffer<T> &b ) 00178 { 00179 00180 m_size = b.m_size; // size of the buffer 00181 m_buf = b.m_buf; // the buffer 00182 m_free = b.m_free; // number of free spaces 00183 m_used = b.m_used; // number of used spaces 00184 m_ri = b.m_ri; // index of next read 00185 m_wi = b.m_wi; // index of next write 00186 00187 } 00188 00189 template < typename T > 00190 const T & 00191 circular_buffer<T>::read() 00192 { 00193 00194 const T &t = read_data(); 00195 00196 increment_read_pos(); 00197 00198 return t; 00199 00200 } 00201 00202 template < typename T > 00203 void 00204 circular_buffer<T>::write( const T &t ) 00205 { 00206 00207 write_data() = t; 00208 increment_write_pos(); 00209 00210 } 00211 00212 00213 template < typename T > 00214 void 00215 circular_buffer<T>::increment_write_pos( int i ) { 00216 00217 m_wi = ( m_wi + i ) % m_size; 00218 m_used += i; 00219 m_free -= i; 00220 00221 } 00222 00223 template < typename T > 00224 void 00225 circular_buffer<T>::increment_read_pos( int i ) { 00226 00227 m_ri = ( m_ri + i ) % m_size; 00228 m_used -= i; 00229 m_free += i; 00230 00231 } 00232 00233 } // namespace tlm 00234 00235 #endif 00236