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&, sc_segid );
00093 virtual void read( T&)
00094 {
00095 assert(false && "Should not be called");
00096 }
00097
00102
00103 virtual T read( sc_segid );
00104 virtual T read()
00105 {
00106 assert(false && "Should not be called");
00107 }
00108
00109
00110 virtual bool nb_read( T& );
00111
00112
00113
00114
00115 virtual int num_available() const
00116 {
00117
00118 chnl_scoped_lock lock( m_mutex );
00119
00120 return ( m_num_readable - m_num_read );
00121
00122 }
00123
00124
00125
00126
00127 virtual const sc_event& data_written_event() const
00128 { return m_data_written_event; }
00129
00130
00131
00132
00137
00138 virtual void write( const T&, int );
00139 void write( const T& )
00140 {
00141 assert(false && "Should not be called");
00142 }
00143
00144
00145 virtual bool nb_write( const T& );
00146
00147
00148
00149
00150 virtual int num_free() const
00151 {
00152
00153
00154 chnl_scoped_lock lock( m_mutex );
00155
00156 return ( m_size - m_num_readable - m_num_written );
00157
00158 }
00159
00160
00161
00162
00163 virtual const sc_event& data_read_event() const
00164 { return m_data_read_event; }
00165
00166
00167
00168
00169 operator T ()
00170 { return read(); }
00171
00172
00177
00178 sc_fifo<T>& operator = ( const T& a )
00179 { assert( 0 );
00180 write( a, -5 ); return *this; }
00181
00182
00183 void trace( sc_trace_file* tf ) const;
00184
00185
00186 virtual void print( ::std::ostream& = ::std::cout ) const;
00187 virtual void dump( ::std::ostream& = ::std::cout ) const;
00188
00189 virtual const char* kind() const
00190 { return "sc_fifo"; }
00191
00192 protected:
00193
00194 virtual void update();
00195
00196
00197
00198 void init( int );
00199
00200 void buf_init( int );
00201 bool buf_write( const T& );
00202 bool buf_read( T& );
00203
00204 protected:
00205
00206 int m_size;
00207 T* m_buf;
00208 int m_free;
00209 int m_ri;
00210 int m_wi;
00211
00212 sc_port_base* m_reader;
00213 sc_port_base* m_writer;
00214
00215 int m_num_readable;
00216 int m_num_read;
00217 int m_num_written;
00218
00219 sc_event m_data_read_event;
00220 sc_event m_data_written_event;
00221
00222 private:
00223
00224
00225 sc_fifo( const sc_fifo<T>& );
00226 sc_fifo& operator = ( const sc_fifo<T>& );
00227 };
00228
00229
00230
00231
00232 template <class T>
00233 inline
00234 void
00235 sc_fifo<T>::register_port( sc_port_base& port_,
00236 const char* if_typename_ )
00237 {
00238 std::string nm( if_typename_ );
00239 if( nm == typeid( sc_fifo_in_if<T> ).name() ||
00240 nm == typeid( sc_fifo_blocking_in_if<T> ).name()
00241 ) {
00242
00243 if( m_reader != 0 ) {
00244 SC_REPORT_ERROR( SC_ID_MORE_THAN_ONE_FIFO_READER_, 0 );
00245 }
00246 m_reader = &port_;
00247 } else if( nm == typeid( sc_fifo_out_if<T> ).name() ||
00248 nm == typeid( sc_fifo_blocking_out_if<T> ).name()
00249 ) {
00250
00251 if( m_writer != 0 ) {
00252 SC_REPORT_ERROR( SC_ID_MORE_THAN_ONE_FIFO_WRITER_, 0 );
00253 }
00254 m_writer = &port_;
00255 }
00256 else
00257 {
00258 SC_REPORT_ERROR( SC_ID_BIND_IF_TO_PORT_,
00259 "sc_fifo<T> port not recognized" );
00260 }
00261 }
00262
00263
00264
00265
00266
00267
00268 template <class T>
00269 inline
00270 void
00271 sc_fifo<T>::read( T& val_, sc_segid seg_id )
00272 {
00273
00274 chnl_scoped_lock lock( m_mutex );
00275
00276 while( num_available() == 0 ) {
00277 sc_core::wait( m_data_written_event, seg_id.seg_id );
00278 }
00279 m_num_read ++;
00280 buf_read( val_ );
00281 request_update();
00282
00283 }
00284
00285
00286 template <class T>
00287 inline
00288 T
00289 sc_fifo<T>::read( sc_segid seg_id )
00290 {
00291 T tmp;
00292 read( tmp, seg_id );
00293 return tmp;
00294 }
00295
00296
00297
00298 template <class T>
00299 inline
00300 bool
00301 sc_fifo<T>::nb_read( T& val_ )
00302 {
00303
00304 chnl_scoped_lock lock( m_mutex );
00305
00306 if( num_available() == 0 ) {
00307 return false;
00308 }
00309 m_num_read ++;
00310 buf_read( val_ );
00311 request_update();
00312 return true;
00313
00314 }
00315
00316
00317
00318
00319
00320
00321 template <class T>
00322 inline
00323 void
00324 sc_fifo<T>::write( const T& val_, int seg_id )
00325 {
00326
00327 chnl_scoped_lock lock( m_mutex );
00328
00329 while( num_free() == 0 ) {
00330 sc_core::wait( m_data_read_event, seg_id );
00331 }
00332 m_num_written ++;
00333 buf_write( val_ );
00334 request_update();
00335
00336 }
00337
00338
00339
00340 template <class T>
00341 inline
00342 bool
00343 sc_fifo<T>::nb_write( const T& val_ )
00344 {
00345
00346 chnl_scoped_lock lock( m_mutex );
00347
00348 if( num_free() == 0 ) {
00349 return false;
00350 }
00351 m_num_written ++;
00352 buf_write( val_ );
00353 request_update();
00354 return true;
00355
00356 }
00357
00358
00359
00360 template <class T>
00361 inline
00362 void
00363 sc_fifo<T>::trace( sc_trace_file* tf ) const
00364 {
00365 #if defined(DEBUG_SYSTEMC)
00366 char buf[32];
00367 std::string nm = name();
00368 for( int i = 0; i < m_size; ++ i ) {
00369 std::sprintf( buf, "_%d", i );
00370 sc_trace( tf, m_buf[i], nm + buf );
00371 }
00372 #endif
00373 }
00374
00375
00376 template <class T>
00377 inline
00378 void
00379 sc_fifo<T>::print( ::std::ostream& os ) const
00380 {
00381
00382 chnl_scoped_lock lock( m_mutex );
00383
00384 if( m_free != m_size ) {
00385 int i = m_ri;
00386 do {
00387 os << m_buf[i] << ::std::endl;
00388 i = ( i + 1 ) % m_size;
00389 } while( i != m_wi );
00390 }
00391
00392 }
00393
00394 template <class T>
00395 inline
00396 void
00397 sc_fifo<T>::dump( ::std::ostream& os ) const
00398 {
00399
00400 chnl_scoped_lock lock( m_mutex );
00401
00402 os << "name = " << name() << ::std::endl;
00403 if( m_free != m_size ) {
00404 int i = m_ri;
00405 int j = 0;
00406 do {
00407 os << "value[" << i << "] = " << m_buf[i] << ::std::endl;
00408 i = ( i + 1 ) % m_size;
00409 j ++;
00410 } while( i != m_wi );
00411 }
00412
00413 }
00414
00415
00416
00417 template <class T>
00418 inline
00419 void
00420 sc_fifo<T>::update()
00421 {
00422 if( m_num_read > 0 ) {
00423 m_data_read_event.notify(SC_ZERO_TIME);
00424 }
00425
00426 if( m_num_written > 0 ) {
00427 m_data_written_event.notify(SC_ZERO_TIME);
00428 }
00429
00430 m_num_readable = m_size - m_free;
00431 m_num_read = 0;
00432 m_num_written = 0;
00433 }
00434
00435
00436
00437
00438
00439 template <class T>
00440 inline
00441 void
00442 sc_fifo<T>::init( int size_ )
00443 {
00444 buf_init( size_ );
00445
00446 m_reader = 0;
00447 m_writer = 0;
00448
00449 m_num_readable = 0;
00450 m_num_read = 0;
00451 m_num_written = 0;
00452 }
00453
00454
00455
00456 template <class T>
00457 inline
00458 void
00459 sc_fifo<T>::buf_init( int size_ )
00460 {
00461 if( size_ <= 0 ) {
00462 SC_REPORT_ERROR( SC_ID_INVALID_FIFO_SIZE_, 0 );
00463 }
00464 m_size = size_;
00465 m_buf = new T[m_size];
00466 m_free = m_size;
00467 m_ri = 0;
00468 m_wi = 0;
00469 }
00470
00471
00472 template <class T>
00473 inline
00474 bool
00475 sc_fifo<T>::buf_write( const T& val_ )
00476 {
00477 if( m_free == 0 ) {
00478 return false;
00479 }
00480 m_buf[m_wi] = val_;
00481 m_wi = ( m_wi + 1 ) % m_size;
00482 m_free --;
00483 return true;
00484 }
00485
00486
00487 template <class T>
00488 inline
00489 bool
00490 sc_fifo<T>::buf_read( T& val_ )
00491 {
00492 if( m_free == m_size ) {
00493 return false;
00494 }
00495 val_ = m_buf[m_ri];
00496 m_buf[m_ri] = T();
00497 m_ri = ( m_ri + 1 ) % m_size;
00498 m_free ++;
00499 return true;
00500 }
00501
00502
00503
00504
00505 template <class T>
00506 inline
00507 ::std::ostream&
00508 operator << ( ::std::ostream& os, const sc_fifo<T>& a )
00509 {
00510 a.print( os );
00511 return os;
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
00548
00549
00550
00551
00552
00553
00554
00555
00556
00557
00558
00559 #endif
00560
00561