TLM-2.0  2.0.4
Accellera TLM-2.0 proof-of-concept library
tlm_fifo.h
Go to the documentation of this file.
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 #ifndef __TLM_FIFO_H__
21 #define __TLM_FIFO_H__
22 
23 //
24 // This implements put, get and peek
25 //
26 // It also implements 0 and infinite size fifos - but the size
27 // zero fifos aren't rendezvous like zero length fifos, they simply are both
28 // full and empty at the same time.
29 //
30 // The size can be dynamically changed using the resize interface
31 //
32 // To get an infinite fifo use a -ve size in the constructor.
33 // The absolute value of the size is taken as the starting size of the
34 // actual physical buffer.
35 //
36 
37 //#include <systemc>
38 
41 
42 namespace tlm {
43 
44 template <typename T>
45 class tlm_fifo :
46  public virtual tlm_fifo_get_if<T>,
47  public virtual tlm_fifo_put_if<T>,
49 {
50 public:
51 
52  // constructors
53 
54  explicit tlm_fifo( int size_ = 1 )
56 
57  init( size_ );
58 
59  }
60 
61  explicit tlm_fifo( const char* name_, int size_ = 1 )
62  : sc_core::sc_prim_channel( name_ ) {
63 
64  init( size_ );
65 
66  }
67 
68  // destructor
69 
70  virtual ~tlm_fifo() {}
71 
72  // tlm get interface
73 
74  T get( tlm_tag<T> * = 0 );
75 
76  bool nb_get( T& );
77  bool nb_can_get( tlm_tag<T> * = 0 ) const;
78  const sc_core::sc_event &ok_to_get( tlm_tag<T> * = 0 ) const {
79  return m_data_written_event;
80  }
81 
82  // tlm peek interface
83 
84  T peek( tlm_tag<T> * = 0 ) const;
85 
86  bool nb_peek( T& ) const;
87  bool nb_can_peek( tlm_tag<T> * = 0 ) const;
88  const sc_core::sc_event &ok_to_peek( tlm_tag<T> * = 0 ) const {
89  return m_data_written_event;
90  }
91 
92  // tlm put interface
93 
94  void put( const T& );
95 
96  bool nb_put( const T& );
97  bool nb_can_put( tlm_tag<T> * = 0 ) const;
98 
99  const sc_core::sc_event& ok_to_put( tlm_tag<T> * = 0 ) const {
100  return m_data_read_event;
101  }
102 
103  // resize if
104 
105  void nb_expand( unsigned int n = 1 );
106  void nb_unbound( unsigned int n = 16 );
107 
108  bool nb_reduce( unsigned int n = 1 );
109  bool nb_bound( unsigned int n );
110 
111  // debug interface
112 
113  bool nb_peek( T & , int n ) const;
114  bool nb_poke( const T & , int n = 0 );
115 
116  int used() const {
117  return m_num_readable - m_num_read;
118  }
119 
120  int size() const {
121  return m_size;
122  }
123 
124  void debug() const {
125 
126  if( is_empty() ) std::cout << "empty" << std::endl;
127  if( is_full() ) std::cout << "full" << std::endl;
128 
129  std::cout << "size " << size() << " - " << used() << " used "
130  << std::endl;
131  std::cout << "readable " << m_num_readable
132  << std::endl;
133  std::cout << "written/read " << m_num_written << "/" << m_num_read
134  << std::endl;
135 
136  }
137 
138  // support functions
139 
140  static const char* const kind_string;
141 
142  const char* kind() const
143  { return kind_string; }
144 
145 
146 protected:
147  sc_core::sc_event &read_event( tlm_tag<T> * = 0 ) {
148  return m_data_read_event;
149  }
150 
151 protected:
152 
153  void update();
154 
155  // support methods
156 
157  void init( int );
158 
159 protected:
160 
162 
163  int m_size; // logical size of fifo
164 
165  int m_num_readable; // #samples readable
166  int m_num_read; // #samples read during this delta cycle
167  int m_num_written; // #samples written during this delta cycle
168  bool m_expand; // has an expand occurred during this delta cycle ?
169  int m_num_read_no_notify; // #samples read without notify during this delta cycle
170 
173 
174 private:
175 
176  // disabled
177  tlm_fifo( const tlm_fifo<T>& );
178  tlm_fifo& operator = ( const tlm_fifo<T>& );
179 
180  //
181  // use nb_can_get() and nb_can_put() rather than the following two
182  // private functions
183  //
184 
185  bool is_empty() const {
186  return used() == 0;
187  }
188 
189  bool is_full() const {
190  //return size() == m_num_readable + m_num_written; // Old buggy code
191  if( size() < 0 )
192  return false;
193  else
194  return size() <= m_num_readable + m_num_written;
195  }
196 
197 };
198 
199 template <typename T>
200 const char* const tlm_fifo<T>::kind_string = "tlm_fifo";
201 
202 
203 /******************************************************************
204 //
205 // init and update
206 //
207 ******************************************************************/
208 
209 template< typename T >
210 inline
211 void
212 tlm_fifo<T>::init( int size_ ) {
213 
214  if( size_ > 0 ) {
215  buffer.resize( size_ );
216  }
217 
218  else if( size_ < 0 ) {
219  buffer.resize( -size_ );
220  }
221 
222  else {
223  buffer.resize( 16 );
224  }
225 
226  m_size = size_;
227  m_num_readable = 0;
228  m_num_read = 0;
229  m_num_written = 0;
230  m_expand = false;
231  m_num_read_no_notify = false;
232 
233 }
234 
235 template < typename T>
236 inline
237 void
239 {
240  if( m_num_read > m_num_read_no_notify || m_expand ) {
241  m_data_read_event.notify( sc_core::SC_ZERO_TIME );
242  }
243 
244  if( m_num_written > 0 ) {
245  m_data_written_event.notify( sc_core::SC_ZERO_TIME );
246  }
247 
248  m_expand = false;
249  m_num_read = 0;
250  m_num_written = 0;
251  m_num_readable = buffer.used();
252  m_num_read_no_notify = 0;
253 
254 }
255 
256 } // namespace tlm
257 
261 
262 #endif
263 
const sc_core::sc_event & ok_to_peek(tlm_tag< T > *=0) const
Definition: tlm_fifo.h:88
SC_API const sc_time SC_ZERO_TIME
const char * kind() const
Definition: tlm_fifo.h:142
bool m_expand
Definition: tlm_fifo.h:168
bool nb_reduce(unsigned int n=1)
bool nb_bound(unsigned int n)
const sc_core::sc_event & ok_to_get(tlm_tag< T > *=0) const
Definition: tlm_fifo.h:78
bool nb_can_get(tlm_tag< T > *=0) const
void update()
Definition: tlm_fifo.h:238
int m_num_readable
Definition: tlm_fifo.h:165
bool nb_poke(const T &, int n=0)
Definition: tlm_fifo_peek.h:85
int m_num_read_no_notify
Definition: tlm_fifo.h:169
circular_buffer< T > buffer
Definition: tlm_fifo.h:161
void init(int)
Definition: tlm_fifo.h:212
sc_core::sc_event m_data_read_event
Definition: tlm_fifo.h:171
bool nb_can_put(tlm_tag< T > *=0) const
bool nb_peek(T &) const
Definition: tlm_fifo_peek.h:45
virtual ~tlm_fifo()
Definition: tlm_fifo.h:70
tlm_fifo(const char *name_, int size_=1)
Definition: tlm_fifo.h:61
const sc_core::sc_event & ok_to_put(tlm_tag< T > *=0) const
Definition: tlm_fifo.h:99
void nb_unbound(unsigned int n=16)
static const char *const kind_string
Definition: tlm_fifo.h:140
void nb_expand(unsigned int n=1)
sc_core::sc_event & read_event(tlm_tag< T > *=0)
Definition: tlm_fifo.h:147
SC_API const char * sc_gen_unique_name(const char *, bool preserve_first)
void put(const T &)
tlm_fifo(int size_=1)
Definition: tlm_fifo.h:54
bool nb_can_peek(tlm_tag< T > *=0) const
Definition: tlm_fifo_peek.h:77
T peek(tlm_tag< T > *=0) const
Definition: tlm_fifo_peek.h:28
bool nb_put(const T &)
int m_num_read
Definition: tlm_fifo.h:166
int used() const
Definition: tlm_fifo.h:116
bool nb_get(T &)
void debug() const
Definition: tlm_fifo.h:124
int m_num_written
Definition: tlm_fifo.h:167
int size() const
Definition: tlm_fifo.h:120
sc_core::sc_event m_data_written_event
Definition: tlm_fifo.h:172
void resize(int size)