1 /**************************************************************************
5 relative bloking (RB) and relative non-bloking (RN)
6 task transaction level (TTL) fifo channel
8 (c) 2006 by Alexander Maxiaguine <maxiagui@tik.ee.ethz.ch>
10 Computer Engineering and Networks Laboratory, TIK
11 Swiss Federal Institute of Technology, ETHZ Zurich
14 **************************************************************************/
16 /**************************************************************************
21 **************************************************************************/
29 #include "dol_rp_ids.h"
30 #include "dol_fifo_if.h"
35 : public dol_fifo_write_if<T>,
36 public dol_fifo_read_if<T>,
37 public sc_prim_channel
42 explicit dol_fifo( int size ) : sc_prim_channel( sc_gen_unique_name( "dol_fifo" ) )
45 explicit dol_fifo( const char* name, int size) : sc_prim_channel( name)
52 virtual void register_port( sc_port_base&, const char* );
54 // ********* WRITE interface methods **************
55 // bloking (re)acquire free room in the channel
56 virtual void reAcquireRoom(int count);
58 // non-bloking (re)acquire free room in the channel
59 virtual bool tryReAcquireRoom(int count);
61 // store data into the acquired free room
62 virtual void store(int offset, T* data, int count);
64 // release the stored data to the channel (commit write)
65 virtual void releaseData(int count);
67 // ********* READ interface methods **************
68 // bloking (re)acquire data in the channel
69 virtual void reAcquireData(int count);
71 // non-bloking (re)acquire data in the channel
72 virtual bool tryReAcquireData(int count);
74 // load the acquired data into a vector
75 virtual void load(int offset, T* vector, int count);
77 // free up the room in the channel (commit read)
78 virtual void releaseRoom(int count);
81 // ***************************************
82 // helper methods (for debug, etc.)
85 return reader_is_blocked && writer_is_blocked;
88 void trace( sc_trace_file* tf ) const;
89 virtual void print( ::std::ostream& = ::std::cout ) const;
90 virtual void dump( ::std::ostream& = ::std::cout ) const;
93 virtual const char* kind() const
94 { return "dol_fifo"; }
99 virtual void update();
105 int m_size; // buffer size
106 T* m_buf; // the buffer
108 // channel state variables
109 int m_rwin_head; // index of read window head (oldest full token)
110 int m_wwin_head; // index of write window head (oldest empty token)
112 int m_readable; // number of readable tokens (number of full tokens)
113 int m_acquired_room; // size of acquired room (write window)
114 int m_acquired_data; // size of acquired data (read window)
116 int m_released_data; // size of data (filled tokens) released during this delta cycle
117 int m_released_room; // size of room (emptied tokens) released during this delta cycle
120 // SC specific properties
121 sc_event m_data_released_event;
122 sc_event m_room_released_event;
124 sc_port_base* m_reader; // used for static design rule checking
125 sc_port_base* m_writer; // used for static design rule checking
127 // used to detect deadlocks
128 bool reader_is_blocked;
129 bool writer_is_blocked;
134 dol_fifo( const dol_fifo<T>& );
135 dol_fifo& operator = ( const dol_fifo<T>& );
141 // ************ Implementation ************************************
143 // *** WRITE interface methods ****
145 // blocking (re)acquire free room of size COUNT in the channel
147 inline void dol_fifo<T>::reAcquireRoom( int count )
149 while( m_size - m_readable < count ) {
150 if( m_size < count) {
151 SC_REPORT_WARNING(RP_ID_PARAMETER_PROBLEM, "Requested room is larger than total available buffer space \n --> This is a deadlock\n\n");
154 writer_is_blocked = true;
155 sc_core::wait( m_room_released_event );
156 writer_is_blocked = false;
158 m_acquired_room = count;
161 // non-bloking (re)acquire free room in the channel
163 inline bool dol_fifo<T>::tryReAcquireRoom( int count )
165 if( m_size - m_readable < count ) {
166 if( m_size < count) {
167 SC_REPORT_WARNING(RP_ID_PARAMETER_PROBLEM, "Requested room is larger than the total available buffer space \n\n");
171 m_acquired_room = count;
175 // write COUNT data into the acquired free room starting from the position indicated by OFFSET
177 inline void dol_fifo<T>::store( int offset, T* data, int count )
180 if( m_acquired_room <= 0) {
181 SC_REPORT_WARNING(RP_ID_PARAMETER_PROBLEM, "Attempt to write without acquiring the room\n --> I ignore this action\n\n");
184 if( offset > m_acquired_room - 1 ) {
185 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");
188 if( count > m_acquired_room - offset ) {
189 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");
190 count = m_acquired_room - offset;
193 int wi = ( m_wwin_head + offset ) % m_size;
194 for(int i=0; i<count; i++ ) {
196 wi = ( wi + 1 ) % m_size;
200 // release COUNT stored data to the channel (commit write)
202 inline void dol_fifo<T>::releaseData( int count )
205 if( count > m_acquired_room ) {
206 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");
207 count = m_acquired_room;
211 m_released_data += count;
213 m_acquired_room -= count;
214 m_wwin_head = ( m_wwin_head + count ) % m_size;
220 // *** READ interface methods ****
222 // bloking (re)acquire COUNT data in the channel
224 inline void dol_fifo<T>::reAcquireData( int count )
226 while( m_readable < count ) {
227 if( m_size < count) {
228 SC_REPORT_WARNING(RP_ID_PARAMETER_PROBLEM, "Acquired data size is larger than total available buffer space\n --> This is a deadlock\n\n");
231 reader_is_blocked = true;
232 sc_core::wait( m_data_released_event );
233 reader_is_blocked = false;
236 m_acquired_data = count;
239 // non-bloking (re)acquire COUNT data in the channel
243 dol_fifo<T>::tryReAcquireData( int count ) {
244 if( m_readable < count ) {
246 if( m_size < count) {
247 SC_REPORT_WARNING(RP_ID_PARAMETER_PROBLEM, "Acquired data size is larger than total available buffer space \n\n");
252 m_acquired_data = count;
256 // load COUNT acquired data into a vector
257 // from the read window starting at the position indicated by OFFSET
259 inline void dol_fifo<T>::load( int offset, T* vector, int count )
262 if( m_acquired_data <= 0) {
264 SC_REPORT_WARNING(RP_ID_PARAMETER_PROBLEM, "Attempt to load without acquiring the data\n --> I ignore this action\n\n");
268 if( offset > m_acquired_data - 1 ) {
270 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");
274 if( count > m_acquired_data - offset ) {
276 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");
277 count = m_acquired_data - offset;
281 int ri = ( m_rwin_head + offset ) % m_size;
283 for(int i=0; i<count; i++ ) {
284 vector[i] = m_buf[ri];
285 ri = ( ri + 1 ) % m_size;
289 // free up COUNT room in the channel (commit read)
291 inline void dol_fifo<T>::releaseRoom( int count )
294 if( count > m_acquired_data ) {
295 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");
296 count = m_acquired_data;
300 m_released_room += count;
302 m_acquired_data -= count;
303 m_rwin_head = ( m_rwin_head + count ) % m_size;
311 // *** Other methods ***
315 inline void dol_fifo<T>::update()
317 if( m_released_room > 0 ) {
318 m_room_released_event.notify_delayed();
321 if( m_released_data > 0 ) {
322 m_data_released_event.notify_delayed();
331 inline void dol_fifo<T>::init( int size )
334 SC_REPORT_ERROR( SC_ID_INVALID_FIFO_SIZE_, 0 );
338 m_buf = new T[m_size];
354 reader_is_blocked = false;
355 writer_is_blocked = false;
360 inline void dol_fifo<T>::register_port( sc_port_base& port_,
361 const char* if_typename_ )
363 std::string nm( if_typename_ );
364 if( nm == typeid( dol_fifo_read_if<T> ).name() ) {
365 // only one reader can be connected
366 if( m_reader != 0 ) {
367 SC_REPORT_ERROR( SC_ID_MORE_THAN_ONE_FIFO_READER_, 0 );
370 } else { // nm == typeid( dol_fifo_write_if<T> ).name()
371 // only one writer can be connected
372 if( m_writer != 0 ) {
373 SC_REPORT_ERROR( SC_ID_MORE_THAN_ONE_FIFO_WRITER_, 0 );
382 inline void dol_fifo<T>::trace( sc_trace_file* tf ) const
386 std::string nm = name();
387 for( int i = 0; i < m_size; ++ i ) {
388 sprintf( buf, "_%d", i );
389 sc_trace( tf, m_buf[i], nm + buf );
396 inline void dol_fifo<T>::print( ::std::ostream& os ) const
399 for(int j=0, i = m_rwin_head; j<m_readable; j++) {
400 // os << m_buf[i] << ::std::endl;
402 i = ( i + 1 ) % m_size;
409 inline void dol_fifo<T>::dump( ::std::ostream& os ) const
411 os << "name = " << name() << ::std::endl;
413 for(int j=0, i = m_rwin_head; j<m_readable; j++) {
414 os << "value[" << j << "] = " << m_buf[i] << ::std::endl;
415 i = ( i + 1 ) % m_size;
422 // ----------------------------------------------------------------------------
425 inline ::std::ostream& operator << ( ::std::ostream& os, const dol_fifo<T>& a )