Commit | Line | Data |
---|---|---|
86530b38 AT |
1 | |
2 | /***************************************************************************** | |
3 | ||
4 | The following code is derived, directly or indirectly, from the SystemC | |
5 | source code Copyright (c) 1996-2004 by all Contributors. | |
6 | All Rights reserved. | |
7 | ||
8 | The contents of this file are subject to the restrictions and limitations | |
9 | set forth in the SystemC Open Source License Version 2.4 (the "License"); | |
10 | You may not use this file except in compliance with such restrictions and | |
11 | limitations. You may obtain instructions on how to receive a copy of the | |
12 | License at http://www.systemc.org/. Software distributed by Contributors | |
13 | under the License is distributed on an "AS IS" basis, WITHOUT WARRANTY OF | |
14 | ANY KIND, either express or implied. See the License for the specific | |
15 | language governing rights and limitations under the License. | |
16 | ||
17 | *****************************************************************************/ | |
18 | ||
19 | ||
20 | #ifndef TLM_FIFO_HEADER | |
21 | #define TLM_FIFO_HEADER | |
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.h> | |
38 | ||
39 | #include "tlm_core/tlm_interfaces/tlm_fifo_ifs.h" | |
40 | #include "tlm_core/tlm_fifo/circular_buffer.h" | |
41 | ||
42 | ||
43 | ||
44 | template <class T> | |
45 | class tlm_fifo : | |
46 | public virtual tlm_fifo_get_if<T>, | |
47 | public virtual tlm_fifo_put_if<T>, | |
48 | public sc_prim_channel | |
49 | { | |
50 | public: | |
51 | ||
52 | // constructors | |
53 | ||
54 | explicit tlm_fifo( int size_ = 1 ) | |
55 | : sc_prim_channel( sc_gen_unique_name( "fifo" ) ) { | |
56 | ||
57 | init( size_ ); | |
58 | ||
59 | } | |
60 | ||
61 | explicit tlm_fifo( const char* name_, int size_ = 1 ) | |
62 | : sc_prim_channel( name_ ) { | |
63 | ||
64 | init( size_ ); | |
65 | ||
66 | } | |
67 | ||
68 | // destructor | |
69 | ||
70 | virtual ~tlm_fifo() { | |
71 | ||
72 | if( buffer != 0 ) delete buffer; | |
73 | ||
74 | } | |
75 | ||
76 | // tlm get interface | |
77 | ||
78 | T get( tlm_tag<T> *t = 0 ); | |
79 | ||
80 | bool nb_get( T& ); | |
81 | bool nb_can_get( tlm_tag<T> *t = 0 ) const; | |
82 | const sc_event &ok_to_get( tlm_tag<T> *t = 0 ) const { | |
83 | return m_data_written_event; | |
84 | } | |
85 | ||
86 | // tlm peek interface | |
87 | ||
88 | T peek( tlm_tag<T> *t = 0 ) const; | |
89 | ||
90 | bool nb_peek( T& ) const; | |
91 | bool nb_can_peek( tlm_tag<T> *t = 0 ) const; | |
92 | const sc_event &ok_to_peek( tlm_tag<T> *t = 0 ) const { | |
93 | return m_data_written_event; | |
94 | } | |
95 | ||
96 | // tlm put interface | |
97 | ||
98 | void put( const T& ); | |
99 | ||
100 | bool nb_put( const T& ); | |
101 | bool nb_can_put( tlm_tag<T> *t = 0 ) const; | |
102 | ||
103 | const sc_event& ok_to_put( tlm_tag<T> *t = 0 ) const { | |
104 | return m_data_read_event; | |
105 | } | |
106 | ||
107 | // resize if | |
108 | ||
109 | void nb_expand( unsigned int n = 1 ); | |
110 | void nb_unbound( unsigned int n = 16 ); | |
111 | ||
112 | bool nb_reduce( unsigned int n = 1 ); | |
113 | bool nb_bound( unsigned int n ); | |
114 | ||
115 | // debug interface | |
116 | ||
117 | bool nb_peek( T & , int n ) const; | |
118 | bool nb_poke( const T & , int n = 0 ); | |
119 | ||
120 | int used() const { | |
121 | return m_num_readable - m_num_read; | |
122 | } | |
123 | ||
124 | int size() const { | |
125 | return m_size; | |
126 | } | |
127 | ||
128 | void debug() const { | |
129 | ||
130 | if( is_empty() ) cout << "empty" << endl; | |
131 | if( is_full() ) cout << "full" << endl; | |
132 | ||
133 | cout << "size " << size() << " - " << used() << " used " << endl; | |
134 | cout << "readable " << m_num_readable << endl; | |
135 | cout << "written/read " << m_num_written << "/" << m_num_read << endl; | |
136 | ||
137 | } | |
138 | ||
139 | // support functions | |
140 | ||
141 | static const char* const kind_string; | |
142 | ||
143 | const char* kind() const | |
144 | { return kind_string; } | |
145 | ||
146 | ||
147 | friend class tlm_annotated::tlm_annotated_fifo<T>; | |
148 | ||
149 | private: // some methods to support tlm_annotated_fifo ! | |
150 | ||
151 | bool nb_can_put( int count , tlm_tag<T> *t = 0 ) const { | |
152 | if( m_size < 0 ) { | |
153 | return true; | |
154 | } | |
155 | return m_num_readable + m_num_written + count <= m_size; | |
156 | } | |
157 | ||
158 | bool nb_get_no_notify( T& ); | |
159 | ||
160 | protected: | |
161 | sc_event &read_event( tlm_tag<T> *t = 0 ) { | |
162 | return m_data_read_event; | |
163 | } | |
164 | ||
165 | protected: | |
166 | ||
167 | void update(); | |
168 | ||
169 | // support methods | |
170 | ||
171 | void init( int ); | |
172 | ||
173 | protected: | |
174 | ||
175 | circular_buffer<T> *buffer; | |
176 | ||
177 | int m_size; // logical size of fifo | |
178 | ||
179 | int m_num_readable; // #samples readable | |
180 | int m_num_read; // #samples read during this delta cycle | |
181 | int m_num_written; // #samples written during this delta cycle | |
182 | bool m_expand; // has an expand occurred during this delta cycle ? | |
183 | int m_num_read_no_notify; // #samples read without notify during this delta cycle | |
184 | ||
185 | sc_event m_data_read_event; | |
186 | sc_event m_data_written_event; | |
187 | ||
188 | private: | |
189 | ||
190 | // disabled | |
191 | tlm_fifo( const tlm_fifo<T>& ); | |
192 | tlm_fifo& operator = ( const tlm_fifo<T>& ); | |
193 | ||
194 | // | |
195 | // use nb_can_get() and nb_can_put() rather than the following two | |
196 | // private functions | |
197 | // | |
198 | ||
199 | bool is_empty() const { | |
200 | return used() == 0; | |
201 | } | |
202 | ||
203 | bool is_full() const { | |
204 | return size() == m_num_readable + m_num_written; | |
205 | } | |
206 | ||
207 | }; | |
208 | ||
209 | template <typename T> | |
210 | const char* const tlm_fifo<T>::kind_string = "tlm_fifo"; | |
211 | ||
212 | ||
213 | /****************************************************************** | |
214 | // | |
215 | // init and update | |
216 | // | |
217 | ******************************************************************/ | |
218 | ||
219 | template< typename T > | |
220 | inline | |
221 | void | |
222 | tlm_fifo<T>::init( int size_ ) { | |
223 | ||
224 | if( size_ > 0 ) { | |
225 | buffer = new circular_buffer<T>( size_); | |
226 | } | |
227 | ||
228 | else if( size_ < 0 ) { | |
229 | buffer = new circular_buffer<T>( -size_ ); | |
230 | } | |
231 | ||
232 | else { | |
233 | buffer = new circular_buffer<T>( 16 ); | |
234 | } | |
235 | ||
236 | m_size = size_; | |
237 | m_num_readable = 0; | |
238 | m_num_read = 0; | |
239 | m_num_written = 0; | |
240 | m_expand = false; | |
241 | m_num_read_no_notify = false; | |
242 | ||
243 | } | |
244 | ||
245 | template < typename T> | |
246 | inline | |
247 | void | |
248 | tlm_fifo<T>::update() | |
249 | { | |
250 | if( m_num_read > m_num_read_no_notify || m_expand ) { | |
251 | m_data_read_event.notify( SC_ZERO_TIME ); | |
252 | } | |
253 | ||
254 | if( m_num_written > 0 ) { | |
255 | m_data_written_event.notify( SC_ZERO_TIME ); | |
256 | } | |
257 | ||
258 | m_expand = false; | |
259 | m_num_read = 0; | |
260 | m_num_written = 0; | |
261 | m_num_readable = buffer->used(); | |
262 | m_num_read_no_notify = 0; | |
263 | ||
264 | } | |
265 | ||
266 | #include "tlm_core/tlm_fifo/tlm_fifo_put_get.h" | |
267 | #include "tlm_core/tlm_fifo/tlm_fifo_peek.h" | |
268 | #include "tlm_core/tlm_fifo/tlm_fifo_resize.h" | |
269 | ||
270 | #endif | |
271 |