X-Git-Url: http://sraa.de/git/?a=blobdiff_plain;f=dol%2Fsrc%2Fdol%2Fvisitor%2FsystemC%2Flib%2Fdol_fifo.h;fp=dol%2Fsrc%2Fdol%2Fvisitor%2FsystemC%2Flib%2Fdol_fifo.h;h=564668206d1968363d0961b8ce2c324ea9d8cfab;hb=8c411cf24ed0eb889191aaeafd8fa1e69081df42;hp=0000000000000000000000000000000000000000;hpb=dea7a4fb1ed110d3ce6e6d9255103d724bd66c0e;p=jump.git diff --git a/dol/src/dol/visitor/systemC/lib/dol_fifo.h b/dol/src/dol/visitor/systemC/lib/dol_fifo.h new file mode 100644 index 0000000..5646682 --- /dev/null +++ b/dol/src/dol/visitor/systemC/lib/dol_fifo.h @@ -0,0 +1,432 @@ +/************************************************************************** + dol_fifo.h + + DOL FIFO channel: + relative bloking (RB) and relative non-bloking (RN) + task transaction level (TTL) fifo channel + + (c) 2006 by Alexander Maxiaguine + + Computer Engineering and Networks Laboratory, TIK + Swiss Federal Institute of Technology, ETHZ Zurich + Switzerland + +**************************************************************************/ + +/************************************************************************** + Change Log: + + 14.03.06 -- creation + +**************************************************************************/ + +#ifndef DOL_FIFO_H +#define DOL_FIFO_H + +#include +#include "systemc.h" + +#include "dol_rp_ids.h" +#include "dol_fifo_if.h" + + +template +class dol_fifo +: public dol_fifo_write_if, + public dol_fifo_read_if, + public sc_prim_channel +{ +public: + + // constructors + explicit dol_fifo( int size ) : sc_prim_channel( sc_gen_unique_name( "dol_fifo" ) ) + { init( size ); } + + explicit dol_fifo( const char* name, int size) : sc_prim_channel( name) + { init( size ); } + + // destructor + virtual ~dol_fifo() + { delete [] m_buf; } + + virtual void register_port( sc_port_base&, const char* ); + + // ********* WRITE interface methods ************** + // bloking (re)acquire free room in the channel + virtual void reAcquireRoom(int count); + + // non-bloking (re)acquire free room in the channel + virtual bool tryReAcquireRoom(int count); + + // store data into the acquired free room + virtual void store(int offset, T* data, int count); + + // release the stored data to the channel (commit write) + virtual void releaseData(int count); + + // ********* READ interface methods ************** + // bloking (re)acquire data in the channel + virtual void reAcquireData(int count); + + // non-bloking (re)acquire data in the channel + virtual bool tryReAcquireData(int count); + + // load the acquired data into a vector + virtual void load(int offset, T* vector, int count); + + // free up the room in the channel (commit read) + virtual void releaseRoom(int count); + + + // *************************************** + // helper methods (for debug, etc.) + + bool in_deadlock() { + return reader_is_blocked && writer_is_blocked; + } + + 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 "dol_fifo"; } + + +protected: + + virtual void update(); + void init( int ); + + +protected: + + int m_size; // buffer size + T* m_buf; // the buffer + + // channel state variables + int m_rwin_head; // index of read window head (oldest full token) + int m_wwin_head; // index of write window head (oldest empty token) + + int m_readable; // number of readable tokens (number of full tokens) + int m_acquired_room; // size of acquired room (write window) + int m_acquired_data; // size of acquired data (read window) + + int m_released_data; // size of data (filled tokens) released during this delta cycle + int m_released_room; // size of room (emptied tokens) released during this delta cycle + + + // SC specific properties + sc_event m_data_released_event; + sc_event m_room_released_event; + + sc_port_base* m_reader; // used for static design rule checking + sc_port_base* m_writer; // used for static design rule checking + + // used to detect deadlocks + bool reader_is_blocked; + bool writer_is_blocked; + +private: + + // disabled + dol_fifo( const dol_fifo& ); + dol_fifo& operator = ( const dol_fifo& ); +}; + + + + +// ************ Implementation ************************************ + +// *** WRITE interface methods **** + +// blocking (re)acquire free room of size COUNT in the channel +template +inline void dol_fifo::reAcquireRoom( int count ) +{ + while( m_size - m_readable < count ) { + if( m_size < count) { + SC_REPORT_WARNING(RP_ID_PARAMETER_PROBLEM, "Requested room is larger than total available buffer space \n --> This is a deadlock\n\n"); + } + + writer_is_blocked = true; + sc_core::wait( m_room_released_event ); + writer_is_blocked = false; + } + m_acquired_room = count; +} + +// non-bloking (re)acquire free room in the channel +template +inline bool dol_fifo::tryReAcquireRoom( int count ) +{ + if( m_size - m_readable < count ) { + if( m_size < count) { + SC_REPORT_WARNING(RP_ID_PARAMETER_PROBLEM, "Requested room is larger than the total available buffer space \n\n"); + } + return false; + } + m_acquired_room = count; + return true; +} + +// write COUNT data into the acquired free room starting from the position indicated by OFFSET +template +inline void dol_fifo::store( int offset, T* data, int count ) +{ + // sanity checks + if( m_acquired_room <= 0) { + SC_REPORT_WARNING(RP_ID_PARAMETER_PROBLEM, "Attempt to write without acquiring the room\n --> I ignore this action\n\n"); + return; + } + if( offset > m_acquired_room - 1 ) { + SC_REPORT_WARNING(RP_ID_PARAMETER_PROBLEM, "Attempt to write beyond the acquired room: offset value may be too large\n --> I ignore this action\n\n"); + return; + } + if( count > m_acquired_room - offset ) { + SC_REPORT_WARNING(RP_ID_PARAMETER_PROBLEM, "Attempt to write beyound the acquired room: data size may be too large\n --> I'm decreasing the data size\n\n"); + count = m_acquired_room - offset; + } + + int wi = ( m_wwin_head + offset ) % m_size; + for(int i=0; i +inline void dol_fifo::releaseData( int count ) +{ + // sanity check + if( count > m_acquired_room ) { + SC_REPORT_WARNING(RP_ID_PARAMETER_PROBLEM, "Attempt to release more room than was acquired\n --> I'm decreasing the size of released room\n\n"); + count = m_acquired_room; + } + + m_readable += count; + m_released_data += count; + + m_acquired_room -= count; + m_wwin_head = ( m_wwin_head + count ) % m_size; + + request_update(); +} + + +// *** READ interface methods **** + +// bloking (re)acquire COUNT data in the channel +template +inline void dol_fifo::reAcquireData( int count ) +{ + while( m_readable < count ) { + if( m_size < count) { + SC_REPORT_WARNING(RP_ID_PARAMETER_PROBLEM, "Acquired data size is larger than total available buffer space\n --> This is a deadlock\n\n"); + } + + reader_is_blocked = true; + sc_core::wait( m_data_released_event ); + reader_is_blocked = false; + } + + m_acquired_data = count; +} + +// non-bloking (re)acquire COUNT data in the channel +template +inline +bool +dol_fifo::tryReAcquireData( int count ) { + if( m_readable < count ) { + + if( m_size < count) { + SC_REPORT_WARNING(RP_ID_PARAMETER_PROBLEM, "Acquired data size is larger than total available buffer space \n\n"); + } + return false; + } + + m_acquired_data = count; + return true; +} + +// load COUNT acquired data into a vector +// from the read window starting at the position indicated by OFFSET +template +inline void dol_fifo::load( int offset, T* vector, int count ) +{ + // sanity checks + if( m_acquired_data <= 0) { + + SC_REPORT_WARNING(RP_ID_PARAMETER_PROBLEM, "Attempt to load without acquiring the data\n --> I ignore this action\n\n"); + return; + } + + if( offset > m_acquired_data - 1 ) { + + SC_REPORT_WARNING(RP_ID_PARAMETER_PROBLEM, "Attempt to read beyond the acquired data: offset value may be too large\n --> I ignore this action\n\n"); + return; + } + + if( count > m_acquired_data - offset ) { + + SC_REPORT_WARNING(RP_ID_PARAMETER_PROBLEM, "Attempt to read beyound the acquired data: data size may be too large\n --> I'm decreasing the data size\n\n"); + count = m_acquired_data - offset; + } + + + int ri = ( m_rwin_head + offset ) % m_size; + + for(int i=0; i +inline void dol_fifo::releaseRoom( int count ) +{ + // sanity check + if( count > m_acquired_data ) { + SC_REPORT_WARNING(RP_ID_PARAMETER_PROBLEM, "Attempt to free up more room than was acquired\n --> I'm decreasing the size of released room\n\n"); + count = m_acquired_data; + } + + m_readable -= count; + m_released_room += count; + + m_acquired_data -= count; + m_rwin_head = ( m_rwin_head + count ) % m_size; + + request_update(); +} + + + + +// *** Other methods *** + + +template +inline void dol_fifo::update() +{ + if( m_released_room > 0 ) { + m_room_released_event.notify_delayed(); + } + + if( m_released_data > 0 ) { + m_data_released_event.notify_delayed(); + } + + m_released_room = 0; + m_released_data = 0; +} + + +template +inline void dol_fifo::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_readable = 0; + + m_acquired_room = 0; + m_acquired_data = 0; + + m_rwin_head = 0; + m_wwin_head = 0; + + m_released_data = 0; + m_released_room = 0; + + m_reader = 0; + m_writer = 0; + + reader_is_blocked = false; + writer_is_blocked = false; +} + + +template +inline void dol_fifo::register_port( sc_port_base& port_, + const char* if_typename_ ) +{ + std::string nm( if_typename_ ); + if( nm == typeid( dol_fifo_read_if ).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 { // nm == typeid( dol_fifo_write_if ).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_; + } +} + + + +template +inline void dol_fifo::trace( sc_trace_file* tf ) const +{ +#ifdef DEBUG_SYSTEMC + char buf[32]; + std::string nm = name(); + for( int i = 0; i < m_size; ++ i ) { + sprintf( buf, "_%d", i ); + sc_trace( tf, m_buf[i], nm + buf ); + } +#endif +} + + +template +inline void dol_fifo::print( ::std::ostream& os ) const +{ + if( m_readable ) { + for(int j=0, i = m_rwin_head; j +inline void dol_fifo::dump( ::std::ostream& os ) const +{ + os << "name = " << name() << ::std::endl; + if( m_readable ) { + for(int j=0, i = m_rwin_head; j