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 #ifndef SC_FIFO_H
00028 #define SC_FIFO_H
00029
00030
00031 #include "sysc/communication/sc_communication_ids.h"
00032 #include "sysc/communication/sc_prim_channel.h"
00033 #include "sysc/communication/sc_fifo_ifs.h"
00034 #include "sysc/kernel/sc_event.h"
00035 #include "sysc/kernel/sc_simcontext.h"
00036 #include "sysc/tracing/sc_trace.h"
00037 #include <typeinfo>
00038
00039 namespace sc_core {
00040
00041
00047 template <class T>
00048 class sc_fifo
00049 : public sc_fifo_in_if<T>,
00050 public sc_fifo_out_if<T>,
00051 public sc_prim_channel
00052 {
00053 public:
00054
00055
00056
00057 explicit sc_fifo( int size_ = 16 )
00058 : sc_prim_channel( sc_gen_unique_name( "fifo" ) ),
00059 m_data_read_event(
00060 (std::string(SC_KERNEL_EVENT_PREFIX)+"_read_event").c_str()),
00061 m_data_written_event(
00062 (std::string(SC_KERNEL_EVENT_PREFIX)+"_write_event").c_str())
00063 { init( size_ ); }
00064
00065 explicit sc_fifo( const char* name_, int size_ = 16 )
00066 : sc_prim_channel( name_ ),
00067 m_data_read_event(
00068 (std::string(SC_KERNEL_EVENT_PREFIX)+"_read_event").c_str()),
00069 m_data_written_event(
00070 (std::string(SC_KERNEL_EVENT_PREFIX)+"_write_event").c_str())
00071 { init( size_ ); }
00072
00073
00074
00075
00076 virtual ~sc_fifo()
00077 { delete [] m_buf; }
00078
00079
00080
00081
00082 virtual void register_port( sc_port_base&, const char* );
00083
00084
00085
00086
00091
00092 virtual void read( T&, int );
00093
00098
00099 virtual T read( int );
00100
00101
00102 virtual bool nb_read( T& );
00103
00104
00105
00106
00107 virtual int num_available() const
00108 {
00109
00110 chnl_scoped_lock lock( m_mutex );
00111
00112 return ( m_num_readable - m_num_read );
00113
00114 }
00115
00116
00117
00118
00119 virtual const sc_event& data_written_event() const
00120 { return m_data_written_event; }
00121
00122
00123
00124
00129
00130 virtual void write( const T&, int );
00131
00132
00133 virtual bool nb_write( const T& );
00134
00135
00136
00137
00138 virtual int num_free() const
00139 {
00140
00141
00142 chnl_scoped_lock lock( m_mutex );
00143
00144 return ( m_size - m_num_readable - m_num_written );
00145
00146 }
00147
00148
00149
00150
00151 virtual const sc_event& data_read_event() const
00152 { return m_data_read_event; }
00153
00154
00155
00156
00157 operator T ()
00158 { return read(); }
00159
00160
00165
00166 sc_fifo<T>& operator = ( const T& a )
00167 { assert( 0 );
00168 write( a, -5 ); return *this; }
00169
00170
00171 void trace( sc_trace_file* tf ) const;
00172
00173
00174 virtual void print( ::std::ostream& = ::std::cout ) const;
00175 virtual void dump( ::std::ostream& = ::std::cout ) const;
00176
00177 virtual const char* kind() const
00178 { return "sc_fifo"; }
00179
00180 protected:
00181
00182 virtual void update();
00183
00184
00185
00186 void init( int );
00187
00188 void buf_init( int );
00189 bool buf_write( const T& );
00190 bool buf_read( T& );
00191
00192 protected:
00193
00194 int m_size;
00195 T* m_buf;
00196 int m_free;
00197 int m_ri;
00198 int m_wi;
00199
00200 sc_port_base* m_reader;
00201 sc_port_base* m_writer;
00202
00203 int m_num_readable;
00204 int m_num_read;
00205 int m_num_written;
00206
00207 sc_event m_data_read_event;
00208 sc_event m_data_written_event;
00209
00210 private:
00211
00212
00213 sc_fifo( const sc_fifo<T>& );
00214 sc_fifo& operator = ( const sc_fifo<T>& );
00215 };
00216
00217
00218
00219
00220 template <class T>
00221 inline
00222 void
00223 sc_fifo<T>::register_port( sc_port_base& port_,
00224 const char* if_typename_ )
00225 {
00226 std::string nm( if_typename_ );
00227 if( nm == typeid( sc_fifo_in_if<T> ).name() ||
00228 nm == typeid( sc_fifo_blocking_in_if<T> ).name()
00229 ) {
00230
00231 if( m_reader != 0 ) {
00232 SC_REPORT_ERROR( SC_ID_MORE_THAN_ONE_FIFO_READER_, 0 );
00233 }
00234 m_reader = &port_;
00235 } else if( nm == typeid( sc_fifo_out_if<T> ).name() ||
00236 nm == typeid( sc_fifo_blocking_out_if<T> ).name()
00237 ) {
00238
00239 if( m_writer != 0 ) {
00240 SC_REPORT_ERROR( SC_ID_MORE_THAN_ONE_FIFO_WRITER_, 0 );
00241 }
00242 m_writer = &port_;
00243 }
00244 else
00245 {
00246 SC_REPORT_ERROR( SC_ID_BIND_IF_TO_PORT_,
00247 "sc_fifo<T> port not recognized" );
00248 }
00249 }
00250
00251
00252
00253
00254
00255
00256 template <class T>
00257 inline
00258 void
00259 sc_fifo<T>::read( T& val_, int seg_id )
00260 {
00261
00262 chnl_scoped_lock lock( m_mutex );
00263
00264 while( num_available() == 0 ) {
00265 sc_core::wait( m_data_written_event, seg_id );
00266 }
00267 m_num_read ++;
00268 buf_read( val_ );
00269 request_update();
00270
00271 }
00272
00273
00274 template <class T>
00275 inline
00276 T
00277 sc_fifo<T>::read( int seg_id )
00278 {
00279 T tmp;
00280 read( tmp, seg_id );
00281 return tmp;
00282 }
00283
00284
00285
00286 template <class T>
00287 inline
00288 bool
00289 sc_fifo<T>::nb_read( T& val_ )
00290 {
00291
00292 chnl_scoped_lock lock( m_mutex );
00293
00294 if( num_available() == 0 ) {
00295 return false;
00296 }
00297 m_num_read ++;
00298 buf_read( val_ );
00299 request_update();
00300 return true;
00301
00302 }
00303
00304
00305
00306
00307
00308
00309 template <class T>
00310 inline
00311 void
00312 sc_fifo<T>::write( const T& val_, int seg_id )
00313 {
00314
00315 chnl_scoped_lock lock( m_mutex );
00316
00317 while( num_free() == 0 ) {
00318 sc_core::wait( m_data_read_event, seg_id );
00319 }
00320 m_num_written ++;
00321 buf_write( val_ );
00322 request_update();
00323
00324 }
00325
00326
00327
00328 template <class T>
00329 inline
00330 bool
00331 sc_fifo<T>::nb_write( const T& val_ )
00332 {
00333
00334 chnl_scoped_lock lock( m_mutex );
00335
00336 if( num_free() == 0 ) {
00337 return false;
00338 }
00339 m_num_written ++;
00340 buf_write( val_ );
00341 request_update();
00342 return true;
00343
00344 }
00345
00346
00347
00348 template <class T>
00349 inline
00350 void
00351 sc_fifo<T>::trace( sc_trace_file* tf ) const
00352 {
00353 #if defined(DEBUG_SYSTEMC)
00354 char buf[32];
00355 std::string nm = name();
00356 for( int i = 0; i < m_size; ++ i ) {
00357 std::sprintf( buf, "_%d", i );
00358 sc_trace( tf, m_buf[i], nm + buf );
00359 }
00360 #endif
00361 }
00362
00363
00364 template <class T>
00365 inline
00366 void
00367 sc_fifo<T>::print( ::std::ostream& os ) const
00368 {
00369
00370 chnl_scoped_lock lock( m_mutex );
00371
00372 if( m_free != m_size ) {
00373 int i = m_ri;
00374 do {
00375 os << m_buf[i] << ::std::endl;
00376 i = ( i + 1 ) % m_size;
00377 } while( i != m_wi );
00378 }
00379
00380 }
00381
00382 template <class T>
00383 inline
00384 void
00385 sc_fifo<T>::dump( ::std::ostream& os ) const
00386 {
00387
00388 chnl_scoped_lock lock( m_mutex );
00389
00390 os << "name = " << name() << ::std::endl;
00391 if( m_free != m_size ) {
00392 int i = m_ri;
00393 int j = 0;
00394 do {
00395 os << "value[" << i << "] = " << m_buf[i] << ::std::endl;
00396 i = ( i + 1 ) % m_size;
00397 j ++;
00398 } while( i != m_wi );
00399 }
00400
00401 }
00402
00403
00404
00405 template <class T>
00406 inline
00407 void
00408 sc_fifo<T>::update()
00409 {
00410 if( m_num_read > 0 ) {
00411 m_data_read_event.notify(SC_ZERO_TIME);
00412 }
00413
00414 if( m_num_written > 0 ) {
00415 m_data_written_event.notify(SC_ZERO_TIME);
00416 }
00417
00418 m_num_readable = m_size - m_free;
00419 m_num_read = 0;
00420 m_num_written = 0;
00421 }
00422
00423
00424
00425
00426
00427 template <class T>
00428 inline
00429 void
00430 sc_fifo<T>::init( int size_ )
00431 {
00432 buf_init( size_ );
00433
00434 m_reader = 0;
00435 m_writer = 0;
00436
00437 m_num_readable = 0;
00438 m_num_read = 0;
00439 m_num_written = 0;
00440 }
00441
00442
00443
00444 template <class T>
00445 inline
00446 void
00447 sc_fifo<T>::buf_init( int size_ )
00448 {
00449 if( size_ <= 0 ) {
00450 SC_REPORT_ERROR( SC_ID_INVALID_FIFO_SIZE_, 0 );
00451 }
00452 m_size = size_;
00453 m_buf = new T[m_size];
00454 m_free = m_size;
00455 m_ri = 0;
00456 m_wi = 0;
00457 }
00458
00459
00460 template <class T>
00461 inline
00462 bool
00463 sc_fifo<T>::buf_write( const T& val_ )
00464 {
00465 if( m_free == 0 ) {
00466 return false;
00467 }
00468 m_buf[m_wi] = val_;
00469 m_wi = ( m_wi + 1 ) % m_size;
00470 m_free --;
00471 return true;
00472 }
00473
00474
00475 template <class T>
00476 inline
00477 bool
00478 sc_fifo<T>::buf_read( T& val_ )
00479 {
00480 if( m_free == m_size ) {
00481 return false;
00482 }
00483 val_ = m_buf[m_ri];
00484 m_buf[m_ri] = T();
00485 m_ri = ( m_ri + 1 ) % m_size;
00486 m_free ++;
00487 return true;
00488 }
00489
00490
00491
00492
00493 template <class T>
00494 inline
00495 ::std::ostream&
00496 operator << ( ::std::ostream& os, const sc_fifo<T>& a )
00497 {
00498 a.print( os );
00499 return os;
00500 }
00501
00502 }
00503
00504
00505
00506
00507
00508
00509
00510
00511
00512
00513
00514
00515
00516
00517
00518
00519
00520
00521
00522
00523
00524
00525
00526
00527
00528
00529
00530
00531
00532
00533
00534
00535
00536
00537
00538
00539
00540
00541
00542
00543
00544
00545
00546
00547 #endif
00548
00549