SystemC  Recoding Infrastructure for SystemC v0.6.2 derived from Accellera SystemC 2.3.1
Accellera SystemC proof-of-concept library
sc_fifo.h
Go to the documentation of this file.
1 /*****************************************************************************
2 
3  The following code is derived, directly or indirectly, from the SystemC
4  source code Copyright (c) 1996-2014 by all Contributors.
5  All Rights reserved.
6 
7  The contents of this file are subject to the restrictions and limitations
8  set forth in the SystemC Open Source License (the "License");
9  You may not use this file except in compliance with such restrictions and
10  limitations. You may obtain instructions on how to receive a copy of the
11  License at http://www.accellera.org/. Software distributed by Contributors
12  under the License is distributed on an "AS IS" basis, WITHOUT WARRANTY OF
13  ANY KIND, either express or implied. See the License for the specific
14  language governing rights and limitations under the License.
15 
16  *****************************************************************************/
17 
18 /*****************************************************************************
19 
20  sc_fifo.h -- The sc_fifo<T> primitive channel class.
21 
22  Original Author: Martin Janssen, Synopsys, Inc., 2001-05-21
23 
24  CHANGE LOG IS AT THE END OF THE FILE
25  *****************************************************************************/
26 
27 #ifndef SC_FIFO_H
28 #define SC_FIFO_H
29 
30 
34 #include "sysc/kernel/sc_event.h"
36 #include "sysc/tracing/sc_trace.h"
37 #include <typeinfo>
38 
39 namespace sc_core {
40 
41 /**************************************************************************/
47 template <class T>
48 class sc_fifo
49 : public sc_fifo_in_if<T>,
50  public sc_fifo_out_if<T>,
51  public sc_prim_channel
52 {
53 public:
54 
55  // constructors
56 
57  explicit sc_fifo( int size_ = 16 )
58  : sc_prim_channel( sc_gen_unique_name( "fifo" ) ),
60  (std::string(SC_KERNEL_EVENT_PREFIX)+"_read_event").c_str()),
62  (std::string(SC_KERNEL_EVENT_PREFIX)+"_write_event").c_str())
63  { init( size_ ); }
64 
65  explicit sc_fifo( const char* name_, int size_ = 16 )
66  : sc_prim_channel( name_ ),
68  (std::string(SC_KERNEL_EVENT_PREFIX)+"_read_event").c_str()),
70  (std::string(SC_KERNEL_EVENT_PREFIX)+"_write_event").c_str())
71  { init( size_ ); }
72 
73 
74  // destructor
75 
76  virtual ~sc_fifo()
77  { delete [] m_buf; }
78 
79 
80  // interface methods
81 
82  virtual void register_port( sc_port_base&, const char* );
83 
84 
85  // blocking read
86 
91  // 08/19/2015 GL: modified for the OoO simulation
92  virtual void read( T&, sc_segid );
93  virtual void read( T&)
94  {
95  assert(false && "Should not be called");
96  }
97 
102  // 08/19/2015 GL: modified for the OoO simulation
103  virtual T read( sc_segid );
104  virtual T read()
105  {
106  assert(false && "Should not be called");
107  }
108 
109  // non-blocking read
110  virtual bool nb_read( T& );
111 
112 
113  // get the number of available samples
114 
115  virtual int num_available() const
116  {
117  // 02/24/2015 GL: acquire a lock to protect m_num_readable & m_num_read
118  chnl_scoped_lock lock( m_mutex );
119 
120  return ( m_num_readable - m_num_read );
121  // 02/24/2015 GL: return releases the lock
122  }
123 
124 
125  // get the data written event
126 
127  virtual const sc_event& data_written_event() const
128  { return m_data_written_event; }
129 
130 
131  // blocking write
132 
137  // 08/19/2015 GL: modified for the OoO simulation
138  virtual void write( const T&, int );
139  void write( const T& )
140  {
141  assert(false && "Should not be called");
142  }
143 
144  // non-blocking write
145  virtual bool nb_write( const T& );
146 
147 
148  // get the number of free spaces
149 
150  virtual int num_free() const
151  {
152  // 02/24/2015 GL: acquire a lock to protect m_num_readable &
153  // m_num_written
154  chnl_scoped_lock lock( m_mutex );
155 
156  return ( m_size - m_num_readable - m_num_written );
157  // 02/24/2015 GL: return releases the lock
158  }
159 
160 
161  // get the data read event
162 
163  virtual const sc_event& data_read_event() const
164  { return m_data_read_event; }
165 
166 
167  // other methods
168 
169  operator T ()
170  { return read(); }
171 
172 
177  // 08/24/2015 GL.
178  sc_fifo<T>& operator = ( const T& a )
179  { assert( 0 ); // 08/24/2015 GL: to support operator = in the future
180  write( a, -5 ); return *this; }
181 
182 
183  void trace( sc_trace_file* tf ) const;
184 
185 
186  virtual void print( ::std::ostream& = ::std::cout ) const;
187  virtual void dump( ::std::ostream& = ::std::cout ) const;
188 
189  virtual const char* kind() const
190  { return "sc_fifo"; }
191 
192 protected:
193 
194  virtual void update();
195 
196  // support methods
197 
198  void init( int );
199 
200  void buf_init( int );
201  bool buf_write( const T& );
202  bool buf_read( T& );
203 
204 protected:
205 
206  int m_size; // size of the buffer
207  T* m_buf; // the buffer
208  int m_free; // number of free spaces
209  int m_ri; // index of next read
210  int m_wi; // index of next write
211 
212  sc_port_base* m_reader; // used for static design rule checking
213  sc_port_base* m_writer; // used for static design rule checking
214 
215  int m_num_readable; // #samples readable
216  int m_num_read; // #samples read during this delta cycle
217  int m_num_written; // #samples written during this delta cycle
218 
221 
222 private:
223 
224  // disabled
225  sc_fifo( const sc_fifo<T>& );
226  sc_fifo& operator = ( const sc_fifo<T>& );
227 };
228 
229 
230 // IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII
231 
232 template <class T>
233 inline
234 void
236  const char* if_typename_ )
237 {
238  std::string nm( if_typename_ );
239  if( nm == typeid( sc_fifo_in_if<T> ).name() ||
240  nm == typeid( sc_fifo_blocking_in_if<T> ).name()
241  ) {
242  // only one reader can be connected
243  if( m_reader != 0 ) {
244  SC_REPORT_ERROR( SC_ID_MORE_THAN_ONE_FIFO_READER_, 0 );
245  }
246  m_reader = &port_;
247  } else if( nm == typeid( sc_fifo_out_if<T> ).name() ||
248  nm == typeid( sc_fifo_blocking_out_if<T> ).name()
249  ) {
250  // only one writer can be connected
251  if( m_writer != 0 ) {
252  SC_REPORT_ERROR( SC_ID_MORE_THAN_ONE_FIFO_WRITER_, 0 );
253  }
254  m_writer = &port_;
255  }
256  else
257  {
258  SC_REPORT_ERROR( SC_ID_BIND_IF_TO_PORT_,
259  "sc_fifo<T> port not recognized" );
260  }
261 }
262 
263 
264 // blocking read
265 
266 // 08/19/2015 GL: modified for the OoO simulation
267 
268 template <class T>
269 inline
270 void
271 sc_fifo<T>::read( T& val_, sc_segid seg_id )
272 {
273  // 02/24/2015 GL: acquire a lock to protect concurrent communication
274  chnl_scoped_lock lock( m_mutex );
275 
276  while( num_available() == 0 ) {
277  sc_core::wait( m_data_written_event, seg_id.seg_id );
278  }
279  m_num_read ++;
280  buf_read( val_ );
281  request_update();
282  // 02/24/2015 GL: return releases the lock
283 }
284 
285 // 02/24/2015 GL: protected by sc_fifo<T>::read(T&)
286 template <class T>
287 inline
288 T
290 {
291  T tmp;
292  read( tmp, seg_id );
293  return tmp;
294 }
295 
296 // non-blocking read
297 
298 template <class T>
299 inline
300 bool
302 {
303  // 02/24/2015 GL: acquire a lock to protect concurrent communication
304  chnl_scoped_lock lock( m_mutex );
305 
306  if( num_available() == 0 ) {
307  return false;
308  }
309  m_num_read ++;
310  buf_read( val_ );
311  request_update();
312  return true;
313  // 02/24/2015 GL: return releases the lock
314 }
315 
316 
317 // blocking write
318 
319 // 08/19/2015 GL: modified for the OoO simulation
320 
321 template <class T>
322 inline
323 void
324 sc_fifo<T>::write( const T& val_, int seg_id )
325 {
326  // 02/24/2015 GL: acquire a lock to protect concurrent communication
327  chnl_scoped_lock lock( m_mutex );
328 
329  while( num_free() == 0 ) {
330  sc_core::wait( m_data_read_event, seg_id );
331  }
332  m_num_written ++;
333  buf_write( val_ );
334  request_update();
335  // 02/24/2015 GL: return releases the lock
336 }
337 
338 // non-blocking write
339 
340 template <class T>
341 inline
342 bool
343 sc_fifo<T>::nb_write( const T& val_ )
344 {
345  // 02/24/2015 GL: acquire a lock to protect concurrent communication
346  chnl_scoped_lock lock( m_mutex );
347 
348  if( num_free() == 0 ) {
349  return false;
350  }
351  m_num_written ++;
352  buf_write( val_ );
353  request_update();
354  return true;
355  // 02/24/2015 GL: return releases the lock
356 }
357 
358 
359 // 02/24/2015 GL: take care of tracing in the future
360 template <class T>
361 inline
362 void
364 {
365 #if defined(DEBUG_SYSTEMC)
366  char buf[32];
367  std::string nm = name();
368  for( int i = 0; i < m_size; ++ i ) {
369  std::sprintf( buf, "_%d", i );
370  sc_trace( tf, m_buf[i], nm + buf );
371  }
372 #endif
373 }
374 
375 
376 template <class T>
377 inline
378 void
379 sc_fifo<T>::print( ::std::ostream& os ) const
380 {
381  // 02/24/2015 GL: acquire a lock to protect member variables
382  chnl_scoped_lock lock( m_mutex );
383 
384  if( m_free != m_size ) {
385  int i = m_ri;
386  do {
387  os << m_buf[i] << ::std::endl;
388  i = ( i + 1 ) % m_size;
389  } while( i != m_wi );
390  }
391  // 02/24/2015 GL: return releases the lock
392 }
393 
394 template <class T>
395 inline
396 void
397 sc_fifo<T>::dump( ::std::ostream& os ) const
398 {
399  // 02/24/2015 GL: acquire a lock to protect member variables
400  chnl_scoped_lock lock( m_mutex );
401 
402  os << "name = " << name() << ::std::endl;
403  if( m_free != m_size ) {
404  int i = m_ri;
405  int j = 0;
406  do {
407  os << "value[" << i << "] = " << m_buf[i] << ::std::endl;
408  i = ( i + 1 ) % m_size;
409  j ++;
410  } while( i != m_wi );
411  }
412  // 02/24/2015 GL: return releases the lock
413 }
414 
415 
416 // 02/24/2015 GL: only executed in the update phase
417 template <class T>
418 inline
419 void
421 {
422  if( m_num_read > 0 ) {
423  m_data_read_event.notify(SC_ZERO_TIME);
424  }
425 
426  if( m_num_written > 0 ) {
427  m_data_written_event.notify(SC_ZERO_TIME);
428  }
429 
430  m_num_readable = m_size - m_free;
431  m_num_read = 0;
432  m_num_written = 0;
433 }
434 
435 
436 // support methods
437 
438 // 02/24/2015 GL: already protected in public methods
439 template <class T>
440 inline
441 void
442 sc_fifo<T>::init( int size_ )
443 {
444  buf_init( size_ );
445 
446  m_reader = 0;
447  m_writer = 0;
448 
449  m_num_readable = 0;
450  m_num_read = 0;
451  m_num_written = 0;
452 }
453 
454 
455 // 02/24/2015 GL: already protected in public methods
456 template <class T>
457 inline
458 void
460 {
461  if( size_ <= 0 ) {
462  SC_REPORT_ERROR( SC_ID_INVALID_FIFO_SIZE_, 0 );
463  }
464  m_size = size_;
465  m_buf = new T[m_size];
466  m_free = m_size;
467  m_ri = 0;
468  m_wi = 0;
469 }
470 
471 // 02/24/2015 GL: already protected in public methods
472 template <class T>
473 inline
474 bool
475 sc_fifo<T>::buf_write( const T& val_ )
476 {
477  if( m_free == 0 ) {
478  return false;
479  }
480  m_buf[m_wi] = val_;
481  m_wi = ( m_wi + 1 ) % m_size;
482  m_free --;
483  return true;
484 }
485 
486 // 02/24/2015 GL: already protected in public methods
487 template <class T>
488 inline
489 bool
491 {
492  if( m_free == m_size ) {
493  return false;
494  }
495  val_ = m_buf[m_ri];
496  m_buf[m_ri] = T(); // clear entry for boost::shared_ptr, et al.
497  m_ri = ( m_ri + 1 ) % m_size;
498  m_free ++;
499  return true;
500 }
501 
502 
503 // ----------------------------------------------------------------------------
504 
505 template <class T>
506 inline
507 ::std::ostream&
508 operator << ( ::std::ostream& os, const sc_fifo<T>& a )
509 {
510  a.print( os );
511  return os;
512 }
513 
514 } // namespace sc_core
515 
516 //$Log: sc_fifo.h,v $
517 //Revision 1.6 2011/08/26 20:45:40 acg
518 // Andy Goodrich: moved the modification log to the end of the file to
519 // eliminate source line number skew when check-ins are done.
520 //
521 //Revision 1.5 2011/03/23 16:17:22 acg
522 // Andy Goodrich: hide the sc_events that are kernel related.
523 //
524 //Revision 1.4 2011/02/18 20:23:45 acg
525 // Andy Goodrich: Copyright update.
526 //
527 //Revision 1.3 2009/10/14 19:05:40 acg
528 // Andy Goodrich: added check for blocking interfaces in addition to the
529 // combined blocking/nonblocking interface.
530 //
531 //Revision 1.2 2009/05/22 16:06:24 acg
532 // Andy Goodrich: process control updates.
533 //
534 //Revision 1.1.1.1 2006/12/15 20:20:04 acg
535 //SystemC 2.3
536 //
537 //Revision 1.4 2006/01/24 20:46:31 acg
538 //Andy Goodrich: changes to eliminate use of deprecated features. For instance,
539 //using notify(SC_ZERO_TIME) in place of notify_delayed().
540 //
541 //Revision 1.3 2006/01/13 20:41:59 acg
542 //Andy Goodrich: Changes to add port registration to the things that are
543 //checked when SC_NO_WRITE_CHECK is not defined.
544 //
545 //Revision 1.2 2006/01/03 23:18:26 acg
546 //Changed copyright to include 2006.
547 //
548 //Revision 1.1.1.1 2005/12/19 23:16:43 acg
549 //First check in of SystemC 2.1 into its own archive.
550 //
551 //Revision 1.12 2005/09/15 23:01:51 acg
552 //Added std:: prefix to appropriate methods and types to get around
553 //issues with the Edison Front End.
554 //
555 //Revision 1.11 2005/06/10 22:43:55 acg
556 //Added CVS change log annotation.
557 //
558 
559 #endif
560 
561 // Taf!
void init(int)
Definition: sc_fifo.h:442
The sc_fifo&lt;T&gt; blocking output interface class.
virtual T read()
Definition: sc_fifo.h:104
void buf_init(int)
Definition: sc_fifo.h:459
#define SC_REPORT_ERROR(msg_type, msg)
Definition: sc_report.h:213
virtual const sc_event & data_read_event() const
Definition: sc_fifo.h:163
void write(const T &)
Definition: sc_fifo.h:139
CHNL_MTX_TYPE_ m_mutex
A mutex to protect concurrent communication.
virtual void read(T &)
Definition: sc_fifo.h:93
The sc_fifo&lt;T&gt; primitive channel class.
virtual const char * kind() const
Definition: sc_fifo.h:189
virtual void write(const T &, int)
A new parameter segment ID is added for the out-of-order simulation.
Definition: sc_fifo.h:324
void wait(int, sc_simcontext *)
virtual void register_port(sc_port_base &, const char *)
Definition: sc_fifo.h:235
virtual int num_available() const
Definition: sc_fifo.h:115
virtual bool nb_write(const T &)
Definition: sc_fifo.h:343
sc_port_base * m_writer
Definition: sc_fifo.h:213
sc_fifo(const char *name_, int size_=16)
Definition: sc_fifo.h:65
sc_event m_data_written_event
Definition: sc_fifo.h:220
sc_port_base * m_reader
Definition: sc_fifo.h:212
sc_fifo< T > & operator=(const T &a)
This operator is not supported by the out-of-order simulation in the current release.
Definition: sc_fifo.h:178
const char * sc_gen_unique_name(const char *, bool preserve_first)
sc_event m_data_read_event
Definition: sc_fifo.h:219
virtual ~sc_fifo()
Definition: sc_fifo.h:76
The event class.
Definition: sc_event.h:260
The sc_fifo&lt;T&gt; input blocking interface class.
virtual bool nb_read(T &)
Definition: sc_fifo.h:301
#define SC_KERNEL_EVENT_PREFIX
Definition: sc_event.h:388
virtual void print(::std::ostream &=::std::cout) const
Definition: sc_fifo.h:379
Abstract base class for class sc_port_b.
Definition: sc_port.h:69
The sc_fifo&lt;T&gt; input interface class.
virtual int num_free() const
Definition: sc_fifo.h:150
virtual const sc_event & data_written_event() const
Definition: sc_fifo.h:127
const sc_time SC_ZERO_TIME
int m_num_readable
Definition: sc_fifo.h:215
sc_fifo(int size_=16)
Definition: sc_fifo.h:57
virtual void update()
The update method (does nothing by default).
Definition: sc_fifo.h:420
bool buf_write(const T &)
Definition: sc_fifo.h:475
void sc_trace(sc_trace_file *tf, const sc_in< T > &port, const std::string &name)
The sc_fifo&lt;T&gt; output interface class.
virtual void dump(::std::ostream &=::std::cout) const
Definition: sc_fifo.h:397
The chnl_scoped_lock class to lock (and automatically release) a mutex.
segment id currently only used for sc_fifo::read(...) as a bug fix
bool buf_read(T &)
Definition: sc_fifo.h:490
Abstract base class of all primitive channel classes.
void trace(sc_trace_file *tf) const
Definition: sc_fifo.h:363