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 #ifndef __TLM_FIFO_H__ 00019 #define __TLM_FIFO_H__ 00020 00021 // 00022 // This implements put, get and peek 00023 // 00024 // It also implements 0 and infinite size fifos - but the size 00025 // zero fifos aren't rendezvous like zero length fifos, they simply are both 00026 // full and empty at the same time. 00027 // 00028 // The size can be dynamically changed using the resize interface 00029 // 00030 // To get an infinite fifo use a -ve size in the constructor. 00031 // The absolute value of the size is taken as the starting size of the 00032 // actual physical buffer. 00033 // 00034 00035 //#include <systemc> 00036 00037 #include "tlm_h/tlm_req_rsp/tlm_1_interfaces/tlm_fifo_ifs.h" 00038 #include "tlm_h/tlm_req_rsp/tlm_channels/tlm_fifo/circular_buffer.h" 00039 00040 namespace tlm { 00041 00042 template <typename T> 00043 class tlm_fifo : 00044 public virtual tlm_fifo_get_if<T>, 00045 public virtual tlm_fifo_put_if<T>, 00046 public sc_core::sc_prim_channel 00047 { 00048 public: 00049 00050 // constructors 00051 00052 explicit tlm_fifo( int size_ = 1 ) 00053 : sc_core::sc_prim_channel( sc_core::sc_gen_unique_name( "fifo" ) ) { 00054 00055 init( size_ ); 00056 00057 } 00058 00059 explicit tlm_fifo( const char* name_, int size_ = 1 ) 00060 : sc_core::sc_prim_channel( name_ ) { 00061 00062 init( size_ ); 00063 00064 } 00065 00066 // destructor 00067 00068 virtual ‾tlm_fifo() { 00069 00070 if( buffer != 0 ) delete buffer; 00071 00072 } 00073 00074 // tlm get interface 00075 00076 T get( tlm_tag<T> *t = 0 ); 00077 00078 bool nb_get( T& ); 00079 bool nb_can_get( tlm_tag<T> *t = 0 ) const; 00080 const sc_core::sc_event &ok_to_get( tlm_tag<T> *t = 0 ) const { 00081 return m_data_written_event; 00082 } 00083 00084 // tlm peek interface 00085 00086 T peek( tlm_tag<T> *t = 0 ) const; 00087 00088 bool nb_peek( T& ) const; 00089 bool nb_can_peek( tlm_tag<T> *t = 0 ) const; 00090 const sc_core::sc_event &ok_to_peek( tlm_tag<T> *t = 0 ) const { 00091 return m_data_written_event; 00092 } 00093 00094 // tlm put interface 00095 00096 void put( const T& ); 00097 00098 bool nb_put( const T& ); 00099 bool nb_can_put( tlm_tag<T> *t = 0 ) const; 00100 00101 const sc_core::sc_event& ok_to_put( tlm_tag<T> *t = 0 ) const { 00102 return m_data_read_event; 00103 } 00104 00105 // resize if 00106 00107 void nb_expand( unsigned int n = 1 ); 00108 void nb_unbound( unsigned int n = 16 ); 00109 00110 bool nb_reduce( unsigned int n = 1 ); 00111 bool nb_bound( unsigned int n ); 00112 00113 // debug interface 00114 00115 bool nb_peek( T & , int n ) const; 00116 bool nb_poke( const T & , int n = 0 ); 00117 00118 int used() const { 00119 return m_num_readable - m_num_read; 00120 } 00121 00122 int size() const { 00123 return m_size; 00124 } 00125 00126 void debug() const { 00127 00128 if( is_empty() ) std::cout << "empty" << std::endl; 00129 if( is_full() ) std::cout << "full" << std::endl; 00130 00131 std::cout << "size " << size() << " - " << used() << " used " 00132 << std::endl; 00133 std::cout << "readable " << m_num_readable 00134 << std::endl; 00135 std::cout << "written/read " << m_num_written << "/" << m_num_read 00136 << std::endl; 00137 00138 } 00139 00140 // support functions 00141 00142 static const char* const kind_string; 00143 00144 const char* kind() const 00145 { return kind_string; } 00146 00147 00148 protected: 00149 sc_core::sc_event &read_event( tlm_tag<T> *t = 0 ) { 00150 return m_data_read_event; 00151 } 00152 00153 protected: 00154 00155 void update(); 00156 00157 // support methods 00158 00159 void init( int ); 00160 00161 protected: 00162 00163 circular_buffer<T> *buffer; 00164 00165 int m_size; // logical size of fifo 00166 00167 int m_num_readable; // #samples readable 00168 int m_num_read; // #samples read during this delta cycle 00169 int m_num_written; // #samples written during this delta cycle 00170 bool m_expand; // has an expand occurred during this delta cycle ? 00171 int m_num_read_no_notify; // #samples read without notify during this delta cycle 00172 00173 sc_core::sc_event m_data_read_event; 00174 sc_core::sc_event m_data_written_event; 00175 00176 private: 00177 00178 // disabled 00179 tlm_fifo( const tlm_fifo<T>& ); 00180 tlm_fifo& operator = ( const tlm_fifo<T>& ); 00181 00182 // 00183 // use nb_can_get() and nb_can_put() rather than the following two 00184 // private functions 00185 // 00186 00187 bool is_empty() const { 00188 return used() == 0; 00189 } 00190 00191 bool is_full() const { 00192 return size() == m_num_readable + m_num_written; 00193 } 00194 00195 }; 00196 00197 template <typename T> 00198 const char* const tlm_fifo<T>::kind_string = "tlm_fifo"; 00199 00200 00201 /****************************************************************** 00202 // 00203 // init and update 00204 // 00205 ******************************************************************/ 00206 00207 template< typename T > 00208 inline 00209 void 00210 tlm_fifo<T>::init( int size_ ) { 00211 00212 if( size_ > 0 ) { 00213 buffer = new circular_buffer<T>( size_); 00214 } 00215 00216 else if( size_ < 0 ) { 00217 buffer = new circular_buffer<T>( -size_ ); 00218 } 00219 00220 else { 00221 buffer = new circular_buffer<T>( 16 ); 00222 } 00223 00224 m_size = size_; 00225 m_num_readable = 0; 00226 m_num_read = 0; 00227 m_num_written = 0; 00228 m_expand = false; 00229 m_num_read_no_notify = false; 00230 00231 } 00232 00233 template < typename T> 00234 inline 00235 void 00236 tlm_fifo<T>::update() 00237 { 00238 if( m_num_read > m_num_read_no_notify || m_expand ) { 00239 m_data_read_event.notify( sc_core::SC_ZERO_TIME ); 00240 } 00241 00242 if( m_num_written > 0 ) { 00243 m_data_written_event.notify( sc_core::SC_ZERO_TIME ); 00244 } 00245 00246 m_expand = false; 00247 m_num_read = 0; 00248 m_num_written = 0; 00249 m_num_readable = buffer->used(); 00250 m_num_read_no_notify = 0; 00251 00252 } 00253 00254 } // namespace tlm 00255 00256 #include "tlm_h/tlm_req_rsp/tlm_channels/tlm_fifo/tlm_fifo_put_get.h" 00257 #include "tlm_h/tlm_req_rsp/tlm_channels/tlm_fifo/tlm_fifo_peek.h" 00258 #include "tlm_h/tlm_req_rsp/tlm_channels/tlm_fifo/tlm_fifo_resize.h" 00259 00260 #endif 00261