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