MatchLib
All Classes Namespaces Files Functions Modules Pages
fifo.h
1/*
2 * Copyright (c) 2017-2022, NVIDIA CORPORATION. All rights reserved.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License")
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16#ifndef FIFO_H
17#define FIFO_H
18
19#include <nvhls_types.h>
20#include <mem_array.h>
21#include <nvhls_assert.h>
64template <typename DataType, unsigned int FifoLen, unsigned int NumBanks = 1>
65class FIFO {
66
67 public:
68 static const int BankSelWidth =
69 (NumBanks == 1) ? 1 : nvhls::nbits<NumBanks - 1>::val;
70 static const int AddrWidth =
71 (FifoLen == 1) ? 1 : nvhls::nbits<FifoLen - 1>::val;
72 typedef NVUINTW(BankSelWidth) BankIdx;
73 typedef NVUINTW(AddrWidth) FifoIdx;
74 typedef NVUINTW(AddrWidth+1) FifoIdxPlusOne;
75
76 FifoIdx head[NumBanks]; // where to read from
77 FifoIdx tail[NumBanks]; // where to write to
78 // FifoLen is number of entries in each bank
80 bool last_action_was_push[NumBanks];
81 static const int width = mem_array_sep<DataType, FifoLen * NumBanks, NumBanks>::width + 2 * NumBanks * AddrWidth + NumBanks;
82
83 // Function to do modulo increment of pointer
84 FifoIdx ModIncr(FifoIdx curr_idx) {
85 if (curr_idx == FifoLen - 1) {
86 return 0;
87 }
88 return curr_idx + 1;
89 }
90
91 // Constructor
92 FIFO() {
93#pragma hls_unroll yes
94 for (unsigned i = 0; i < NumBanks; i++) {
95 head[i] = 0;
96 tail[i] = 0;
97 last_action_was_push[i] = false;
98 }
99 }
100
101 // Function to push data to FIFO
102 void push(DataType wr_data, BankIdx bidx = 0) {
103 NVHLS_ASSERT_MSG(!isFull(bidx), "Pushing data to full FIFO");
104 FifoIdx tail_local = tail[bidx];
105 fifo_body.write(tail_local, bidx, wr_data);
106 tail[bidx] = ModIncr(tail_local);
107 last_action_was_push[bidx] = true;
108 }
109
110 // Function to pop data from FIFO
111 DataType pop(BankIdx bidx = 0) {
112 NVHLS_ASSERT_MSG(!isEmpty(bidx), "Popping data from empty FIFO");
113 FifoIdx head_local = head[bidx];
114 DataType rd_data = fifo_body.read(head_local, bidx);
115 head[bidx] = ModIncr(head_local);
116 last_action_was_push[bidx] = false;
117 return rd_data;
118 }
119
120 // Function to increment the head pointer (emulate a pop)
121 void incrHead(BankIdx bidx = 0) {
122 NVHLS_ASSERT_MSG(!isEmpty(bidx), "Incrementing Head of empty FIFO");
123 FifoIdx head_local = head[bidx];
124 head[bidx] = ModIncr(head_local);
125 last_action_was_push[bidx] = false;
126 }
127
128 // Function to peek from FIFO
129 DataType peek(BankIdx bidx = 0) {
130 NVHLS_ASSERT_MSG(!isEmpty(bidx), "Peeking data from empty FIFO");
131 FifoIdx head_local = head[bidx];
132 return fifo_body.read(head_local, bidx);
133 }
134
135 // Checks if FIFO is empty
136 bool isEmpty(BankIdx bidx = 0) {
137 FifoIdx head_local = head[bidx];
138 FifoIdx tail_local = tail[bidx];
139 return (tail_local == head_local) && (!last_action_was_push[bidx]);
140 }
141
142 // Checks if FIFO is full
143 bool isFull(BankIdx bidx = 0) {
144 FifoIdx head_local = head[bidx];
145 FifoIdx tail_local = tail[bidx];
146 return (tail_local == head_local) && (last_action_was_push[bidx]);
147 }
148
149 // Returns number of entries filled in FIFO
150 FifoIdxPlusOne NumFilled(BankIdx bidx = 0) {
151 FifoIdx head_local = head[bidx];
152 FifoIdx tail_local = tail[bidx];
153 if (isEmpty(bidx)) {
154 return 0;
155 }
156 if (isFull(bidx)) {
157 return FifoLen;
158 }
159 if (head_local < tail_local) {
160 return (tail_local - head_local);
161 } else {
162 return (FifoLen - head_local + tail_local);
163 }
164 }
165
166 // Returns number of empty entries in FIFO
167 FifoIdxPlusOne NumAvailable(BankIdx bidx = 0) {
168 return (FifoLen - NumFilled(bidx));
169 }
170
171 // Reset head and tail pointers
172 void reset() {
173#pragma hls_unroll yes
174 for (unsigned i = 0; i < NumBanks; i++) {
175 head[i] = 0;
176 tail[i] = 0;
177 last_action_was_push[i] = false;
178 }
179 }
180
181 FifoIdx get_head(BankIdx bidx = 0) { return head[bidx]; }
182 FifoIdx get_tail(BankIdx bidx = 0) { return tail[bidx]; }
183
184 template<unsigned int Size>
185 void Marshall(Marshaller<Size>& m) {
186 for (unsigned i = 0; i < NumBanks; i++) {
187 m & head[i];
188 }
189 for (unsigned i = 0; i < NumBanks; i++) {
190 m & tail[i];
191 }
192 m & fifo_body;
193 for (unsigned i = 0; i < NumBanks; i++) {
194 m & last_action_was_push[i];
195 }
196 }
197
198}; // end FIFO class
199
200template <typename DataType, unsigned int NumBanks>
201class FIFO<DataType, 0, NumBanks> { // 0 entries, NumBanks
202 // make sure no one is accessing a fifo with 0 entries ever
203 // it will still be fine to create it
204 static const int BankSelWidth =
205 (NumBanks == 1) ? 1 : nvhls::nbits<NumBanks - 1>::val;
206
207 public:
208 typedef NVUINTW(BankSelWidth) BankIdx;
209 typedef NVUINTW(1) FifoIdx;
210 FIFO() {}
211
212 void push(DataType wr_data, BankIdx bidx = 0) {NVHLS_ASSERT_MSG(0, "FIFO size is zero");}
213
214 DataType pop(BankIdx bidx = 0) { NVHLS_ASSERT_MSG(0, "FIFO size is zero"); return DataType(); }
215
216 void incrHead(BankIdx bidx = 0) {NVHLS_ASSERT_MSG(0, "FIFO size is zero"); }
217
218 DataType peek(BankIdx bidx = 0) { NVHLS_ASSERT_MSG(0, "FIFO size is zero"); return DataType(); }
219
220 bool isEmpty(BankIdx bidx = 0) {NVHLS_ASSERT_MSG(0, "FIFO size is zero"); return true; }
221
222 bool isFull(BankIdx bidx = 0) {NVHLS_ASSERT_MSG(0, "FIFO size is zero"); return true; }
223
224 FifoIdx NumFilled(BankIdx bidx = 0) {NVHLS_ASSERT_MSG(0, "FIFO size is zero"); return 0; }
225
226 FifoIdx NumAvailable(BankIdx bidx = 0) {NVHLS_ASSERT_MSG(0, "FIFO size is zero"); return 0; }
227
228 void reset() {}
229};
230
238template <typename DataType>
239class FIFO<DataType, 1, 1> {
240 DataType data;
241 bool valid;
242
243 public:
244 static const int width = Wrapped<DataType>::width + 1;
245 typedef NVUINTW(1) T; //redundant
246
247 FIFO() {reset();}
248
249 inline void push(DataType wr_data, T bidx = 0)
250 {
251 NVHLS_ASSERT_MSG(!isFull(), "Pushing data to full FIFO");
252 data = wr_data;
253 valid = true;
254 }
255
256 inline DataType pop(T bidx = 0)
257 {
258 incrHead();
259 return data;
260 }
261
262 inline void incrHead(T bidx = 0)
263 {
264 NVHLS_ASSERT_MSG(!isEmpty(), "Incrementing head of empty FIFO");
265 valid = false;
266 }
267
268 inline DataType peek(T bidx = 0)
269 {
270 NVHLS_ASSERT_MSG(!isEmpty(), "Peeking data from empty FIFO");
271 return data;
272 }
273
274 inline bool isEmpty(T bidx = 0)
275 {
276 return !valid;
277 }
278
279 inline bool isFull(T bidx = 0)
280 {
281 return valid;
282 }
283
284 inline T NumFilled(T bidx = 0) {
285 return valid;
286 }
287
288 inline T NumAvailable(T bidx = 0) {
289 return !valid;
290 }
291
292 inline void reset()
293 {
294 valid = false;
295 }
296 template<unsigned int Size>
297 void Marshall(Marshaller<Size>& m) {
298 m & valid;
299 m & data;
300 }
301};
310template <typename DataType, unsigned int NumBanks>
311class FIFO<DataType, 1, NumBanks> {
312 DataType data[NumBanks];
313 bool valid[NumBanks];
314 static const int width = NumBanks * Wrapped<DataType>::width + NumBanks;
315
316 public:
317 static const int BankSelWidth =
318 (NumBanks == 1) ? 1 : nvhls::nbits<NumBanks - 1>::val;
319 typedef NVUINTW(BankSelWidth) BankIdx;
320 typedef NVUINTW(1) T;
321
322 FIFO() {
323 reset();
324 }
325
326 inline void push(DataType wr_data, BankIdx bidx = 0) {
327 NVHLS_ASSERT_MSG(!isFull(bidx), "Pushing data to full FIFO");
328 data[bidx] = wr_data;
329 valid[bidx] = true;
330 }
331
332 inline DataType pop(BankIdx bidx = 0) {
333 incrHead(bidx);
334 return data[bidx];
335 }
336
337 inline void incrHead(BankIdx bidx = 0) {
338 NVHLS_ASSERT_MSG(!isEmpty(bidx), "Incrementing Head of empty FIFO");
339 valid[bidx] = false;
340 }
341
342 inline DataType peek(BankIdx bidx = 0) {
343 NVHLS_ASSERT_MSG(!isEmpty(bidx), "Peeking data from empty FIFO");
344 return data[bidx];
345 }
346
347 inline bool isEmpty(BankIdx bidx = 0) {
348 return !valid[bidx];
349 }
350
351 inline bool isFull(BankIdx bidx = 0) {
352 return valid[bidx];
353 }
354
355 inline T NumFilled(T bidx = 0) {
356 return valid;
357 }
358
359 inline T NumAvailable(T bidx = 0) {
360 return !valid;
361 }
362
363 inline void reset() {
364 #pragma hls_unroll yes
365 for(unsigned i=0; i<NumBanks; i++) {
366 valid[i] = false;
367 }
368 }
369 template<unsigned int Size>
370 void Marshall(Marshaller<Size>& m) {
371 for (unsigned i = 0; i < NumBanks; i++) {
372 m & valid[i];
373 }
374 for (unsigned i = 0; i < NumBanks; i++) {
375 m & data[i];
376 }
377 }
378};
379
380#endif // end #define FIFO_H macro
Configurable FIFO class.
Definition fifo.h:65
Abstract Memory Class.
Definition mem_array.h:83
#define NVHLS_ASSERT_MSG(X, MSG)
#define NVUINTW(width)
Definition nvhls_types.h:35
Compute number of bits to represent a constant.
Definition nvhls_int.h:118