00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036 #ifndef SC_FIFO_H
00037 #define SC_FIFO_H
00038
00039
00040 #include "sysc/communication/sc_communication_ids.h"
00041 #include "sysc/communication/sc_prim_channel.h"
00042 #include "sysc/communication/sc_fifo_ifs.h"
00043 #include "sysc/kernel/sc_event.h"
00044 #include "sysc/kernel/sc_simcontext.h"
00045 #include "sysc/utils/sc_string.h"
00046 #include "sysc/tracing/sc_trace.h"
00047 #include <typeinfo>
00048
00049 namespace sc_core {
00050
00051
00052
00053
00054
00055
00056
00057 template <class T>
00058 class sc_fifo
00059 : public sc_fifo_in_if<T>,
00060 public sc_fifo_out_if<T>,
00061 public sc_prim_channel
00062 {
00063 public:
00064
00065
00066
00067 explicit sc_fifo( int size_ = 16 )
00068 : sc_prim_channel( sc_gen_unique_name( "fifo" ) )
00069 { init( size_ ); }
00070
00071 explicit sc_fifo( const char* name_, int size_ = 16 )
00072 : sc_prim_channel( name_ )
00073 { init( size_ ); }
00074
00075
00076
00077
00078 virtual ~sc_fifo()
00079 { delete [] m_buf; }
00080
00081
00082
00083
00084 virtual void register_port( sc_port_base&, const char* );
00085
00086
00087
00088 virtual void read( T& );
00089 virtual T read();
00090
00091
00092 virtual bool nb_read( T& );
00093
00094
00095
00096
00097 virtual int num_available() const
00098 { return ( m_num_readable - m_num_read ); }
00099
00100
00101
00102
00103 virtual const sc_event& data_written_event() const
00104 { return m_data_written_event; }
00105
00106
00107
00108 virtual void write( const T& );
00109
00110
00111 virtual bool nb_write( const T& );
00112
00113
00114
00115
00116 virtual int num_free() const
00117 { return ( m_size - m_num_readable - m_num_written ); }
00118
00119
00120
00121
00122 virtual const sc_event& data_read_event() const
00123 { return m_data_read_event; }
00124
00125
00126
00127
00128 operator T ()
00129 { return read(); }
00130
00131
00132 sc_fifo<T>& operator = ( const T& a )
00133 { write( a ); return *this; }
00134
00135
00136 void trace( sc_trace_file* tf ) const;
00137
00138
00139 virtual void print( ::std::ostream& = ::std::cout ) const;
00140 virtual void dump( ::std::ostream& = ::std::cout ) const;
00141
00142 virtual const char* kind() const
00143 { return "sc_fifo"; }
00144
00145 protected:
00146
00147 virtual void update();
00148
00149
00150
00151 void init( int );
00152
00153 void buf_init( int );
00154 bool buf_write( const T& );
00155 bool buf_read( T& );
00156
00157 protected:
00158
00159 int m_size;
00160 T* m_buf;
00161 int m_free;
00162 int m_ri;
00163 int m_wi;
00164
00165 sc_port_base* m_reader;
00166 sc_port_base* m_writer;
00167
00168 int m_num_readable;
00169 int m_num_read;
00170 int m_num_written;
00171
00172 sc_event m_data_read_event;
00173 sc_event m_data_written_event;
00174
00175 private:
00176
00177
00178 sc_fifo( const sc_fifo<T>& );
00179 sc_fifo& operator = ( const sc_fifo<T>& );
00180 };
00181
00182
00183
00184
00185 template <class T>
00186 inline
00187 void
00188 sc_fifo<T>::register_port( sc_port_base& port_,
00189 const char* if_typename_ )
00190 {
00191 std::string nm( if_typename_ );
00192 if( nm == typeid( sc_fifo_in_if<T> ).name() ) {
00193
00194 if( m_reader != 0 ) {
00195 SC_REPORT_ERROR( SC_ID_MORE_THAN_ONE_FIFO_READER_, 0 );
00196 }
00197 m_reader = &port_;
00198 } else {
00199
00200 if( m_writer != 0 ) {
00201 SC_REPORT_ERROR( SC_ID_MORE_THAN_ONE_FIFO_WRITER_, 0 );
00202 }
00203 m_writer = &port_;
00204 }
00205 }
00206
00207
00208
00209
00210 template <class T>
00211 inline
00212 void
00213 sc_fifo<T>::read( T& val_ )
00214 {
00215 while( num_available() == 0 ) {
00216 sc_core::wait( m_data_written_event );
00217 }
00218 m_num_read ++;
00219 buf_read( val_ );
00220 request_update();
00221 }
00222
00223 template <class T>
00224 inline
00225 T
00226 sc_fifo<T>::read()
00227 {
00228 T tmp;
00229 read( tmp );
00230 return tmp;
00231 }
00232
00233
00234
00235 template <class T>
00236 inline
00237 bool
00238 sc_fifo<T>::nb_read( T& val_ )
00239 {
00240 if( num_available() == 0 ) {
00241 return false;
00242 }
00243 m_num_read ++;
00244 buf_read( val_ );
00245 request_update();
00246 return true;
00247 }
00248
00249
00250
00251
00252 template <class T>
00253 inline
00254 void
00255 sc_fifo<T>::write( const T& val_ )
00256 {
00257 while( num_free() == 0 ) {
00258 sc_core::wait( m_data_read_event );
00259 }
00260 m_num_written ++;
00261 buf_write( val_ );
00262 request_update();
00263 }
00264
00265
00266
00267 template <class T>
00268 inline
00269 bool
00270 sc_fifo<T>::nb_write( const T& val_ )
00271 {
00272 if( num_free() == 0 ) {
00273 return false;
00274 }
00275 m_num_written ++;
00276 buf_write( val_ );
00277 request_update();
00278 return true;
00279 }
00280
00281
00282 template <class T>
00283 inline
00284 void
00285 sc_fifo<T>::trace( sc_trace_file* tf ) const
00286 {
00287 #ifdef DEBUG_SYSTEMC
00288 char buf[32];
00289 std::string nm = name();
00290 for( int i = 0; i < m_size; ++ i ) {
00291 sprintf( buf, "_%d", i );
00292 sc_trace( tf, m_buf[i], nm + buf );
00293 }
00294 #endif
00295 }
00296
00297
00298 template <class T>
00299 inline
00300 void
00301 sc_fifo<T>::print( ::std::ostream& os ) const
00302 {
00303 if( m_free != m_size ) {
00304 int i = m_ri;
00305 do {
00306 os << m_buf[i] << ::std::endl;
00307 i = ( i + 1 ) % m_size;
00308 } while( i != m_wi );
00309 }
00310 }
00311
00312 template <class T>
00313 inline
00314 void
00315 sc_fifo<T>::dump( ::std::ostream& os ) const
00316 {
00317 os << "name = " << name() << ::std::endl;
00318 if( m_free != m_size ) {
00319 int i = m_ri;
00320 int j = 0;
00321 do {
00322 os << "value[" << i << "] = " << m_buf[i] << ::std::endl;
00323 i = ( i + 1 ) % m_size;
00324 j ++;
00325 } while( i != m_wi );
00326 }
00327 }
00328
00329
00330 template <class T>
00331 inline
00332 void
00333 sc_fifo<T>::update()
00334 {
00335 if( m_num_read > 0 ) {
00336 m_data_read_event.notify_delayed();
00337 }
00338
00339 if( m_num_written > 0 ) {
00340 m_data_written_event.notify_delayed();
00341 }
00342
00343 m_num_readable = m_size - m_free;
00344 m_num_read = 0;
00345 m_num_written = 0;
00346 }
00347
00348
00349
00350
00351 template <class T>
00352 inline
00353 void
00354 sc_fifo<T>::init( int size_ )
00355 {
00356 buf_init( size_ );
00357
00358 m_reader = 0;
00359 m_writer = 0;
00360
00361 m_num_readable = 0;
00362 m_num_read = 0;
00363 m_num_written = 0;
00364 }
00365
00366
00367 template <class T>
00368 inline
00369 void
00370 sc_fifo<T>::buf_init( int size_ )
00371 {
00372 if( size_ <= 0 ) {
00373 SC_REPORT_ERROR( SC_ID_INVALID_FIFO_SIZE_, 0 );
00374 }
00375 m_size = size_;
00376 m_buf = new T[m_size];
00377 m_free = m_size;
00378 m_ri = 0;
00379 m_wi = 0;
00380 }
00381
00382 template <class T>
00383 inline
00384 bool
00385 sc_fifo<T>::buf_write( const T& val_ )
00386 {
00387 if( m_free == 0 ) {
00388 return false;
00389 }
00390 m_buf[m_wi] = val_;
00391 m_wi = ( m_wi + 1 ) % m_size;
00392 m_free --;
00393 return true;
00394 }
00395
00396 template <class T>
00397 inline
00398 bool
00399 sc_fifo<T>::buf_read( T& val_ )
00400 {
00401 if( m_free == m_size ) {
00402 return false;
00403 }
00404 val_ = m_buf[m_ri];
00405 m_ri = ( m_ri + 1 ) % m_size;
00406 m_free ++;
00407 return true;
00408 }
00409
00410
00411
00412
00413 template <class T>
00414 inline
00415 ::std::ostream&
00416 operator << ( ::std::ostream& os, const sc_fifo<T>& a )
00417 {
00418 a.print( os );
00419 return os;
00420 }
00421
00422 }
00423
00424 #endif
00425
00426