1/*****************************************************************************
2
3  Licensed to Accellera Systems Initiative Inc. (Accellera) under one or
4  more contributor license agreements.  See the NOTICE file distributed
5  with this work for additional information regarding copyright ownership.
6  Accellera licenses this file to you under the Apache License, Version 2.0
7  (the "License"); you may not use this file except in compliance with the
8  License.  You may obtain a copy of the License at
9
10    http://www.apache.org/licenses/LICENSE-2.0
11
12  Unless required by applicable law or agreed to in writing, software
13  distributed under the License is distributed on an "AS IS" BASIS,
14  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
15  implied.  See the License for the specific language governing
16  permissions and limitations under the License.
17
18 *****************************************************************************/
19
20/*****************************************************************************
21
22  sc_fifo.h -- The sc_fifo<T> primitive channel class.
23
24  Original Author: Martin Janssen, Synopsys, Inc., 2001-05-21
25
26  CHANGE LOG IS AT THE END OF THE FILE
27 *****************************************************************************/
28
29#ifndef SC_FIFO_H
30#define SC_FIFO_H
31
32
33#include "sysc/communication/sc_communication_ids.h"
34#include "sysc/communication/sc_prim_channel.h"
35#include "sysc/communication/sc_fifo_ifs.h"
36#include "sysc/kernel/sc_event.h"
37#include "sysc/kernel/sc_simcontext.h"
38#include "sysc/tracing/sc_trace.h"
39#include <typeinfo>
40
41namespace sc_core {
42
43// ----------------------------------------------------------------------------
44//  CLASS : sc_fifo<T>
45//
46//  The sc_fifo<T> primitive channel class.
47// ----------------------------------------------------------------------------
48
49template <class T>
50class sc_fifo
51: public sc_fifo_in_if<T>,
52  public sc_fifo_out_if<T>,
53  public sc_prim_channel
54{
55public:
56
57    // constructors
58
59    explicit sc_fifo( int size_ = 16 )
60	: sc_prim_channel( sc_gen_unique_name( "fifo" ) ),
61	  m_data_read_event(
62	      (std::string(SC_KERNEL_EVENT_PREFIX)+"_read_event").c_str()),
63	  m_data_written_event(
64	      (std::string(SC_KERNEL_EVENT_PREFIX)+"_write_event").c_str())
65	{ init( size_ ); }
66
67    explicit sc_fifo( const char* name_, int size_ = 16 )
68	: sc_prim_channel( name_ ),
69	  m_data_read_event(
70	      (std::string(SC_KERNEL_EVENT_PREFIX)+"_read_event").c_str()),
71	  m_data_written_event(
72	      (std::string(SC_KERNEL_EVENT_PREFIX)+"_write_event").c_str())
73	{ init( size_ ); }
74
75
76    // destructor
77
78    virtual ~sc_fifo()
79	{ delete [] m_buf; }
80
81
82    // interface methods
83
84    virtual void register_port( sc_port_base&, const char* );
85
86
87    // blocking read
88    virtual void read( T& );
89    virtual T read();
90
91    // non-blocking read
92    virtual bool nb_read( T& );
93
94
95    // get the number of available samples
96
97    virtual int num_available() const
98	{ return ( m_num_readable - m_num_read ); }
99
100
101    // get the data written event
102
103    virtual const sc_event& data_written_event() const
104	{ return m_data_written_event; }
105
106
107    // blocking write
108    virtual void write( const T& );
109
110    // non-blocking write
111    virtual bool nb_write( const T& );
112
113
114    // get the number of free spaces
115
116    virtual int num_free() const
117	{ return ( m_size - m_num_readable - m_num_written ); }
118
119
120    // get the data read event
121
122    virtual const sc_event& data_read_event() const
123	{ return m_data_read_event; }
124
125
126    // other methods
127
128    operator T ()
129	{ return read(); }
130
131
132    sc_fifo<T>& operator = ( const T& a )
133        { write( a ); return *this; }
134
135
136    void trace( sc_trace_file* tf ) const;
137
138
139    virtual void print( ::std::ostream& = ::std::cout ) const;
140    virtual void dump( ::std::ostream& = ::std::cout ) const;
141
142    virtual const char* kind() const
143        { return "sc_fifo"; }
144
145protected:
146
147    virtual void update();
148
149    // support methods
150
151    void init( int );
152
153    void buf_init( int );
154    bool buf_write( const T& );
155    bool buf_read( T& );
156
157protected:
158
159    int m_size;			// size of the buffer
160    T*  m_buf;			// the buffer
161    int m_free;			// number of free spaces
162    int m_ri;			// index of next read
163    int m_wi;			// index of next write
164
165    sc_port_base* m_reader;	// used for static design rule checking
166    sc_port_base* m_writer;	// used for static design rule checking
167
168    int m_num_readable;		// #samples readable
169    int m_num_read;		// #samples read during this delta cycle
170    int m_num_written;		// #samples written during this delta cycle
171
172    sc_event m_data_read_event;
173    sc_event m_data_written_event;
174
175private:
176
177    // disabled
178    sc_fifo( const sc_fifo<T>& );
179    sc_fifo& operator = ( const sc_fifo<T>& );
180};
181
182
183// IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII
184
185template <class T>
186inline
187void
188sc_fifo<T>::register_port( sc_port_base& port_,
189			    const char* if_typename_ )
190{
191    std::string nm( if_typename_ );
192    if( nm == typeid( sc_fifo_in_if<T> ).name() ||
193        nm == typeid( sc_fifo_blocking_in_if<T> ).name()
194    ) {
195	// only one reader can be connected
196	if( m_reader != 0 ) {
197	    SC_REPORT_ERROR( SC_ID_MORE_THAN_ONE_FIFO_READER_, 0 );
198	}
199	m_reader = &port_;
200    } else if( nm == typeid( sc_fifo_out_if<T> ).name() ||
201               nm == typeid( sc_fifo_blocking_out_if<T> ).name()
202    ) {
203	// only one writer can be connected
204	if( m_writer != 0 ) {
205	    SC_REPORT_ERROR( SC_ID_MORE_THAN_ONE_FIFO_WRITER_, 0 );
206	}
207	m_writer = &port_;
208    }
209    else
210    {
211        SC_REPORT_ERROR( SC_ID_BIND_IF_TO_PORT_,
212	                 "sc_fifo<T> port not recognized" );
213    }
214}
215
216
217// blocking read
218
219template <class T>
220inline
221void
222sc_fifo<T>::read( T& val_ )
223{
224    while( num_available() == 0 ) {
225	sc_core::wait( m_data_written_event );
226    }
227    m_num_read ++;
228    buf_read( val_ );
229    request_update();
230}
231
232template <class T>
233inline
234T
235sc_fifo<T>::read()
236{
237    T tmp;
238    read( tmp );
239    return tmp;
240}
241
242// non-blocking read
243
244template <class T>
245inline
246bool
247sc_fifo<T>::nb_read( T& val_ )
248{
249    if( num_available() == 0 ) {
250	return false;
251    }
252    m_num_read ++;
253    buf_read( val_ );
254    request_update();
255    return true;
256}
257
258
259// blocking write
260
261template <class T>
262inline
263void
264sc_fifo<T>::write( const T& val_ )
265{
266    while( num_free() == 0 ) {
267	sc_core::wait( m_data_read_event );
268    }
269    m_num_written ++;
270    buf_write( val_ );
271    request_update();
272}
273
274// non-blocking write
275
276template <class T>
277inline
278bool
279sc_fifo<T>::nb_write( const T& val_ )
280{
281    if( num_free() == 0 ) {
282	return false;
283    }
284    m_num_written ++;
285    buf_write( val_ );
286    request_update();
287    return true;
288}
289
290
291template <class T>
292inline
293void
294sc_fifo<T>::trace( sc_trace_file* tf ) const
295{
296#if defined(DEBUG_SYSTEMC)
297    char buf[32];
298    std::string nm = name();
299    for( int i = 0; i < m_size; ++ i ) {
300	std::sprintf( buf, "_%d", i );
301	sc_trace( tf, m_buf[i], nm + buf );
302    }
303#endif
304}
305
306
307template <class T>
308inline
309void
310sc_fifo<T>::print( ::std::ostream& os ) const
311{
312    if( m_free != m_size ) {
313        int i = m_ri;
314        do {
315            os << m_buf[i] << ::std::endl;
316            i = ( i + 1 ) % m_size;
317        } while( i != m_wi );
318    }
319}
320
321template <class T>
322inline
323void
324sc_fifo<T>::dump( ::std::ostream& os ) const
325{
326    os << "name = " << name() << ::std::endl;
327    if( m_free != m_size ) {
328        int i = m_ri;
329        int j = 0;
330        do {
331	    os << "value[" << i << "] = " << m_buf[i] << ::std::endl;
332	    i = ( i + 1 ) % m_size;
333	    j ++;
334        } while( i != m_wi );
335    }
336}
337
338
339template <class T>
340inline
341void
342sc_fifo<T>::update()
343{
344    if( m_num_read > 0 ) {
345	m_data_read_event.notify(SC_ZERO_TIME);
346    }
347
348    if( m_num_written > 0 ) {
349	m_data_written_event.notify(SC_ZERO_TIME);
350    }
351
352    m_num_readable = m_size - m_free;
353    m_num_read = 0;
354    m_num_written = 0;
355}
356
357
358// support methods
359
360template <class T>
361inline
362void
363sc_fifo<T>::init( int size_ )
364{
365    buf_init( size_ );
366
367    m_reader = 0;
368    m_writer = 0;
369
370    m_num_readable = 0;
371    m_num_read = 0;
372    m_num_written = 0;
373}
374
375
376template <class T>
377inline
378void
379sc_fifo<T>::buf_init( int size_ )
380{
381    if( size_ <= 0 ) {
382	SC_REPORT_ERROR( SC_ID_INVALID_FIFO_SIZE_, 0 );
383    }
384    m_size = size_;
385    m_buf = new T[m_size];
386    m_free = m_size;
387    m_ri = 0;
388    m_wi = 0;
389}
390
391template <class T>
392inline
393bool
394sc_fifo<T>::buf_write( const T& val_ )
395{
396    if( m_free == 0 ) {
397	return false;
398    }
399    m_buf[m_wi] = val_;
400    m_wi = ( m_wi + 1 ) % m_size;
401    m_free --;
402    return true;
403}
404
405template <class T>
406inline
407bool
408sc_fifo<T>::buf_read( T& val_ )
409{
410    if( m_free == m_size ) {
411	return false;
412    }
413    val_ = m_buf[m_ri];
414    m_buf[m_ri] = T(); // clear entry for boost::shared_ptr, et al.
415    m_ri = ( m_ri + 1 ) % m_size;
416    m_free ++;
417    return true;
418}
419
420
421// ----------------------------------------------------------------------------
422
423template <class T>
424inline
425::std::ostream&
426operator << ( ::std::ostream& os, const sc_fifo<T>& a )
427{
428    a.print( os );
429    return os;
430}
431
432} // namespace sc_core
433
434//$Log: sc_fifo.h,v $
435//Revision 1.6  2011/08/26 20:45:40  acg
436// Andy Goodrich: moved the modification log to the end of the file to
437// eliminate source line number skew when check-ins are done.
438//
439//Revision 1.5  2011/03/23 16:17:22  acg
440// Andy Goodrich: hide the sc_events that are kernel related.
441//
442//Revision 1.4  2011/02/18 20:23:45  acg
443// Andy Goodrich: Copyright update.
444//
445//Revision 1.3  2009/10/14 19:05:40  acg
446// Andy Goodrich: added check for blocking interfaces in addition to the
447// combined blocking/nonblocking interface.
448//
449//Revision 1.2  2009/05/22 16:06:24  acg
450// Andy Goodrich: process control updates.
451//
452//Revision 1.1.1.1  2006/12/15 20:20:04  acg
453//SystemC 2.3
454//
455//Revision 1.4  2006/01/24 20:46:31  acg
456//Andy Goodrich: changes to eliminate use of deprecated features. For instance,
457//using notify(SC_ZERO_TIME) in place of notify_delayed().
458//
459//Revision 1.3  2006/01/13 20:41:59  acg
460//Andy Goodrich: Changes to add port registration to the things that are
461//checked when SC_NO_WRITE_CHECK is not defined.
462//
463//Revision 1.2  2006/01/03 23:18:26  acg
464//Changed copyright to include 2006.
465//
466//Revision 1.1.1.1  2005/12/19 23:16:43  acg
467//First check in of SystemC 2.1 into its own archive.
468//
469//Revision 1.12  2005/09/15 23:01:51  acg
470//Added std:: prefix to appropriate methods and types to get around
471//issues with the Edison Front End.
472//
473//Revision 1.11  2005/06/10 22:43:55  acg
474//Added CVS change log annotation.
475//
476
477#endif
478
479// Taf!
480