| /***************************************************************************** |
| |
| Licensed to Accellera Systems Initiative Inc. (Accellera) under one or |
| more contributor license agreements. See the NOTICE file distributed |
| with this work for additional information regarding copyright ownership. |
| Accellera licenses this file to you under the Apache License, Version 2.0 |
| (the "License"); you may not use this file except in compliance with the |
| License. You may obtain a copy of the License at |
| |
| http://www.apache.org/licenses/LICENSE-2.0 |
| |
| Unless required by applicable law or agreed to in writing, software |
| distributed under the License is distributed on an "AS IS" BASIS, |
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or |
| implied. See the License for the specific language governing |
| permissions and limitations under the License. |
| |
| *****************************************************************************/ |
| |
| /***************************************************************************** |
| |
| sc_fifo.h -- The sc_fifo<T> primitive channel class. |
| |
| Original Author: Martin Janssen, Synopsys, Inc., 2001-05-21 |
| |
| CHANGE LOG IS AT THE END OF THE FILE |
| *****************************************************************************/ |
| |
| #ifndef SC_FIFO_H |
| #define SC_FIFO_H |
| |
| |
| #include "sysc/communication/sc_communication_ids.h" |
| #include "sysc/communication/sc_prim_channel.h" |
| #include "sysc/communication/sc_fifo_ifs.h" |
| #include "sysc/kernel/sc_event.h" |
| #include "sysc/kernel/sc_simcontext.h" |
| #include "sysc/tracing/sc_trace.h" |
| #include <typeinfo> |
| |
| namespace sc_core { |
| |
| // ---------------------------------------------------------------------------- |
| // CLASS : sc_fifo<T> |
| // |
| // The sc_fifo<T> primitive channel class. |
| // ---------------------------------------------------------------------------- |
| |
| template <class T> |
| class sc_fifo |
| : public sc_fifo_in_if<T>, |
| public sc_fifo_out_if<T>, |
| public sc_prim_channel |
| { |
| public: |
| |
| // constructors |
| |
| explicit sc_fifo( int size_ = 16 ) |
| : sc_prim_channel( sc_gen_unique_name( "fifo" ) ), |
| m_data_read_event( |
| (std::string(SC_KERNEL_EVENT_PREFIX)+"_read_event").c_str()), |
| m_data_written_event( |
| (std::string(SC_KERNEL_EVENT_PREFIX)+"_write_event").c_str()) |
| { init( size_ ); } |
| |
| explicit sc_fifo( const char* name_, int size_ = 16 ) |
| : sc_prim_channel( name_ ), |
| m_data_read_event( |
| (std::string(SC_KERNEL_EVENT_PREFIX)+"_read_event").c_str()), |
| m_data_written_event( |
| (std::string(SC_KERNEL_EVENT_PREFIX)+"_write_event").c_str()) |
| { init( size_ ); } |
| |
| |
| // destructor |
| |
| virtual ~sc_fifo() |
| { delete [] m_buf; } |
| |
| |
| // interface methods |
| |
| virtual void register_port( sc_port_base&, const char* ); |
| |
| |
| // blocking read |
| virtual void read( T& ); |
| virtual T read(); |
| |
| // non-blocking read |
| virtual bool nb_read( T& ); |
| |
| |
| // get the number of available samples |
| |
| virtual int num_available() const |
| { return ( m_num_readable - m_num_read ); } |
| |
| |
| // get the data written event |
| |
| virtual const sc_event& data_written_event() const |
| { return m_data_written_event; } |
| |
| |
| // blocking write |
| virtual void write( const T& ); |
| |
| // non-blocking write |
| virtual bool nb_write( const T& ); |
| |
| |
| // get the number of free spaces |
| |
| virtual int num_free() const |
| { return ( m_size - m_num_readable - m_num_written ); } |
| |
| |
| // get the data read event |
| |
| virtual const sc_event& data_read_event() const |
| { return m_data_read_event; } |
| |
| |
| // other methods |
| |
| operator T () |
| { return read(); } |
| |
| |
| sc_fifo<T>& operator = ( const T& a ) |
| { write( a ); return *this; } |
| |
| |
| void trace( sc_trace_file* tf ) const; |
| |
| |
| virtual void print( ::std::ostream& = ::std::cout ) const; |
| virtual void dump( ::std::ostream& = ::std::cout ) const; |
| |
| virtual const char* kind() const |
| { return "sc_fifo"; } |
| |
| protected: |
| |
| virtual void update(); |
| |
| // support methods |
| |
| void init( int ); |
| |
| void buf_init( int ); |
| bool buf_write( const T& ); |
| bool buf_read( T& ); |
| |
| protected: |
| |
| int m_size; // size of the buffer |
| T* m_buf; // the buffer |
| int m_free; // number of free spaces |
| int m_ri; // index of next read |
| int m_wi; // index of next write |
| |
| sc_port_base* m_reader; // used for static design rule checking |
| sc_port_base* m_writer; // used for static design rule checking |
| |
| int m_num_readable; // #samples readable |
| int m_num_read; // #samples read during this delta cycle |
| int m_num_written; // #samples written during this delta cycle |
| |
| sc_event m_data_read_event; |
| sc_event m_data_written_event; |
| |
| private: |
| |
| // disabled |
| sc_fifo( const sc_fifo<T>& ); |
| sc_fifo& operator = ( const sc_fifo<T>& ); |
| }; |
| |
| |
| // IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII |
| |
| template <class T> |
| inline |
| void |
| sc_fifo<T>::register_port( sc_port_base& port_, |
| const char* if_typename_ ) |
| { |
| std::string nm( if_typename_ ); |
| if( nm == typeid( sc_fifo_in_if<T> ).name() || |
| nm == typeid( sc_fifo_blocking_in_if<T> ).name() |
| ) { |
| // only one reader can be connected |
| if( m_reader != 0 ) { |
| SC_REPORT_ERROR( SC_ID_MORE_THAN_ONE_FIFO_READER_, 0 ); |
| } |
| m_reader = &port_; |
| } else if( nm == typeid( sc_fifo_out_if<T> ).name() || |
| nm == typeid( sc_fifo_blocking_out_if<T> ).name() |
| ) { |
| // only one writer can be connected |
| if( m_writer != 0 ) { |
| SC_REPORT_ERROR( SC_ID_MORE_THAN_ONE_FIFO_WRITER_, 0 ); |
| } |
| m_writer = &port_; |
| } |
| else |
| { |
| SC_REPORT_ERROR( SC_ID_BIND_IF_TO_PORT_, |
| "sc_fifo<T> port not recognized" ); |
| } |
| } |
| |
| |
| // blocking read |
| |
| template <class T> |
| inline |
| void |
| sc_fifo<T>::read( T& val_ ) |
| { |
| while( num_available() == 0 ) { |
| sc_core::wait( m_data_written_event ); |
| } |
| m_num_read ++; |
| buf_read( val_ ); |
| request_update(); |
| } |
| |
| template <class T> |
| inline |
| T |
| sc_fifo<T>::read() |
| { |
| T tmp; |
| read( tmp ); |
| return tmp; |
| } |
| |
| // non-blocking read |
| |
| template <class T> |
| inline |
| bool |
| sc_fifo<T>::nb_read( T& val_ ) |
| { |
| if( num_available() == 0 ) { |
| return false; |
| } |
| m_num_read ++; |
| buf_read( val_ ); |
| request_update(); |
| return true; |
| } |
| |
| |
| // blocking write |
| |
| template <class T> |
| inline |
| void |
| sc_fifo<T>::write( const T& val_ ) |
| { |
| while( num_free() == 0 ) { |
| sc_core::wait( m_data_read_event ); |
| } |
| m_num_written ++; |
| buf_write( val_ ); |
| request_update(); |
| } |
| |
| // non-blocking write |
| |
| template <class T> |
| inline |
| bool |
| sc_fifo<T>::nb_write( const T& val_ ) |
| { |
| if( num_free() == 0 ) { |
| return false; |
| } |
| m_num_written ++; |
| buf_write( val_ ); |
| request_update(); |
| return true; |
| } |
| |
| |
| template <class T> |
| inline |
| void |
| sc_fifo<T>::trace( sc_trace_file* tf ) const |
| { |
| #if defined(DEBUG_SYSTEMC) |
| char buf[32]; |
| std::string nm = name(); |
| for( int i = 0; i < m_size; ++ i ) { |
| std::sprintf( buf, "_%d", i ); |
| sc_trace( tf, m_buf[i], nm + buf ); |
| } |
| #endif |
| } |
| |
| |
| template <class T> |
| inline |
| void |
| sc_fifo<T>::print( ::std::ostream& os ) const |
| { |
| if( m_free != m_size ) { |
| int i = m_ri; |
| do { |
| os << m_buf[i] << ::std::endl; |
| i = ( i + 1 ) % m_size; |
| } while( i != m_wi ); |
| } |
| } |
| |
| template <class T> |
| inline |
| void |
| sc_fifo<T>::dump( ::std::ostream& os ) const |
| { |
| os << "name = " << name() << ::std::endl; |
| if( m_free != m_size ) { |
| int i = m_ri; |
| int j = 0; |
| do { |
| os << "value[" << i << "] = " << m_buf[i] << ::std::endl; |
| i = ( i + 1 ) % m_size; |
| j ++; |
| } while( i != m_wi ); |
| } |
| } |
| |
| |
| template <class T> |
| inline |
| void |
| sc_fifo<T>::update() |
| { |
| if( m_num_read > 0 ) { |
| m_data_read_event.notify(SC_ZERO_TIME); |
| } |
| |
| if( m_num_written > 0 ) { |
| m_data_written_event.notify(SC_ZERO_TIME); |
| } |
| |
| m_num_readable = m_size - m_free; |
| m_num_read = 0; |
| m_num_written = 0; |
| } |
| |
| |
| // support methods |
| |
| template <class T> |
| inline |
| void |
| sc_fifo<T>::init( int size_ ) |
| { |
| buf_init( size_ ); |
| |
| m_reader = 0; |
| m_writer = 0; |
| |
| m_num_readable = 0; |
| m_num_read = 0; |
| m_num_written = 0; |
| } |
| |
| |
| template <class T> |
| inline |
| void |
| sc_fifo<T>::buf_init( int size_ ) |
| { |
| if( size_ <= 0 ) { |
| SC_REPORT_ERROR( SC_ID_INVALID_FIFO_SIZE_, 0 ); |
| } |
| m_size = size_; |
| m_buf = new T[m_size]; |
| m_free = m_size; |
| m_ri = 0; |
| m_wi = 0; |
| } |
| |
| template <class T> |
| inline |
| bool |
| sc_fifo<T>::buf_write( const T& val_ ) |
| { |
| if( m_free == 0 ) { |
| return false; |
| } |
| m_buf[m_wi] = val_; |
| m_wi = ( m_wi + 1 ) % m_size; |
| m_free --; |
| return true; |
| } |
| |
| template <class T> |
| inline |
| bool |
| sc_fifo<T>::buf_read( T& val_ ) |
| { |
| if( m_free == m_size ) { |
| return false; |
| } |
| val_ = m_buf[m_ri]; |
| m_buf[m_ri] = T(); // clear entry for boost::shared_ptr, et al. |
| m_ri = ( m_ri + 1 ) % m_size; |
| m_free ++; |
| return true; |
| } |
| |
| |
| // ---------------------------------------------------------------------------- |
| |
| template <class T> |
| inline |
| ::std::ostream& |
| operator << ( ::std::ostream& os, const sc_fifo<T>& a ) |
| { |
| a.print( os ); |
| return os; |
| } |
| |
| } // namespace sc_core |
| |
| //$Log: sc_fifo.h,v $ |
| //Revision 1.6 2011/08/26 20:45:40 acg |
| // Andy Goodrich: moved the modification log to the end of the file to |
| // eliminate source line number skew when check-ins are done. |
| // |
| //Revision 1.5 2011/03/23 16:17:22 acg |
| // Andy Goodrich: hide the sc_events that are kernel related. |
| // |
| //Revision 1.4 2011/02/18 20:23:45 acg |
| // Andy Goodrich: Copyright update. |
| // |
| //Revision 1.3 2009/10/14 19:05:40 acg |
| // Andy Goodrich: added check for blocking interfaces in addition to the |
| // combined blocking/nonblocking interface. |
| // |
| //Revision 1.2 2009/05/22 16:06:24 acg |
| // Andy Goodrich: process control updates. |
| // |
| //Revision 1.1.1.1 2006/12/15 20:20:04 acg |
| //SystemC 2.3 |
| // |
| //Revision 1.4 2006/01/24 20:46:31 acg |
| //Andy Goodrich: changes to eliminate use of deprecated features. For instance, |
| //using notify(SC_ZERO_TIME) in place of notify_delayed(). |
| // |
| //Revision 1.3 2006/01/13 20:41:59 acg |
| //Andy Goodrich: Changes to add port registration to the things that are |
| //checked when SC_NO_WRITE_CHECK is not defined. |
| // |
| //Revision 1.2 2006/01/03 23:18:26 acg |
| //Changed copyright to include 2006. |
| // |
| //Revision 1.1.1.1 2005/12/19 23:16:43 acg |
| //First check in of SystemC 2.1 into its own archive. |
| // |
| //Revision 1.12 2005/09/15 23:01:51 acg |
| //Added std:: prefix to appropriate methods and types to get around |
| //issues with the Edison Front End. |
| // |
| //Revision 1.11 2005/06/10 22:43:55 acg |
| //Added CVS change log annotation. |
| // |
| |
| #endif |
| |
| // Taf! |