cloudFPGA (cF) API  1.0
The documentation of the source code of cloudFPGA (cF)
AxisRaw.hpp
Go to the documentation of this file.
1 /*
2  * Copyright 2016 -- 2021 IBM Corporation
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 
17 
97 #ifndef _AXIS_RAW_H_
98 #define _AXIS_RAW_H_
99 
100 #include <cassert>
101 #include <iostream>
102 #include <hls_stream.h>
103 
104 #include "ap_int.h"
105 
106 
110 
113 #define AXIS_RAW_WIDTH_AT_10GE 64
114 #define ARW AXIS_RAW_WIDTH_AT_10GE
115 
116 #define TLAST 1
117 
118 
122 typedef ap_uint<ARW> LE_tData;
123 typedef ap_uint<ARW/2> LE_tDataHalf;
124 typedef ap_uint<ARW/8> LE_tKeep;
125 typedef ap_uint<1> LE_tLast; // Added for consistency
126 typedef ap_uint<ARW> tData;
127 typedef ap_uint<ARW/2> tDataHalf;
128 typedef ap_uint<ARW/8> tKeep;
129 typedef ap_uint<ARW/16> tKeepHalf;
130 typedef ap_uint<1> tLast;
131 
132 
147 template <class TypeIn, class TypeOut>
149  hls::stream<TypeIn>& si,
150  hls::stream<TypeOut>& so)
151 {
152  #pragma HLS PIPELINE II=1 enable_flush
153  #pragma HLS INLINE off
154 
155  if (!si.empty()) {
156  so.write(si.read());
157  }
158 }
159 
160 
170 class AxisRaw {
171 
172  protected:
176 
177  public:
178  AxisRaw() {}
180  tdata(tdata), tkeep(tkeep), tlast(tlast) {}
181 
182 
186  /* Get a range of the 'tdata' member in Big-Endian (BE) order
187  * +---------------+---------------+---------------+---------------+
188  * tdata |ARW-1 (Little-Endian) 0|
189  * +---------------+---------------+---------------+---------------+
190  */
191  tData getTData(int leHi=ARW-1, int leLo=0) const {
192  switch (leHi-leLo) {
193  case 64-1 : return byteSwap64(tdata.range(leHi, leLo)); break;
194  case 32-1 : return byteSwap32(tdata.range(leHi, leLo)); break;
195  case 16-1 : return byteSwap16(tdata.range(leHi, leLo)); break;
196  case 8-1 : return (tdata.range(leHi, leLo)); break;
197  default : break;
198  }
199  std::cout << "ASSERT - AxisRaw::getTData() - Unsupported range.\n"; assert(false);
200  return tdata;
201  }
202  /* Get a range of the 'tkeep' member in Big-Endian (BE) order
203  * +---------------+---------------+
204  * tkeep |ARW/8-1 (LE) 0|
205  * +---------------+---------------+
206  */
207  tKeep getTKeep(int leHi=ARW/8-1, int leLo=0) const {
208  switch (leHi-leLo) {
209  case 8-1 : return bitSwap8(tkeep.range(leHi, leLo)); break;
210  case 4-1 : return bitSwap4(tkeep.range(leHi, leLo)); break;
211  case 2-1 : return bitSwap2(tkeep.range(leHi, leLo)); break;
212  case 1-1 : return (tkeep[leLo]); break;
213  default : break;
214  }
215  std::cout << "ASSERT - AxisRaw::getTKeep() - Unsupported range.\n"; assert(false);
216  return tkeep;
217  }
218  // Get the 'tlast' member
219  tLast getTLast() const {
220  return tlast;
221  }
222 
223  /* Set the 'tdata' member from a parameter encoded in Big-Endian (BE) order
224  * +---------------+---------------+---------------+---------------+
225  * tdata |ARW-1 (Little-Endian) 0|
226  * +---------------+---------------+---------------+---------------+
227  */
229  switch (ARW) {
230  case 64 : tdata = byteSwap64(data); break;
231  default : std::cout << "ASSERT - AxisRaw::setTData() - Unsupported Axis raw width.\n"; break;
232  }
233  }
234  /* Set the 'tkeep' member from a parameter encoded in Big-Endian (BE) order
235  * +---------------+---------------+
236  * tkeep |ARW/8-1 (LE) 0|
237  * +---------------+---------------+
238  */
239  void setTKeep(tKeep keep) {
240  switch (ARW) {
241  case 64 : tkeep = bitSwap8(keep); break;
242  default : std::cout << "ASSERT - AxisRaw::setTKeep() - Unsupported Axis raw width.\n"; break;
243  }
244  }
245  // Set the 'tlast' member
246  void setTLast(tLast last) {
247  tlast = last;
248  if (last) { // [FIXME-Remove and create a 'setTLastAndClear()]
249  // Always zero the bytes which have their tkeep-bit cleared.
250  // This simplifies the computation of the various checksums and
251  // unifies the overall AxisRaw processing and verification.
253  }
254  }
255 
256 
259  // Return the 'tdata' field in Little-Endian order
260  LE_tData getLE_TData(int leHi=ARW-1, int leLo=0) const {
261  return tdata.range(leHi, leLo);
262  }
263  // Get the 'tkeep' field with respect to the 'tdata' field encoded in Little-Endian order
264  LE_tKeep getLE_TKeep(int leHi=ARW/8-1, int leLo=0) const {
265  return tkeep.range(leHi, leLo);
266  }
267  // Get the tlast bit
269  return tlast;
270  }
271  // Set the 'tdata' field with a 'data' encoded in Little-Endian order
272  void setLE_TData(LE_tData data, int leHi=ARW-1, int leLo=0) {
273  tdata.range(leHi, leLo) = data.range(leHi-leLo, 0);
274  }
275  // Set the 'tkeep' field with respect to the 'tdata' field encoded in Little-Endian order
276  void setLE_TKeep(LE_tKeep keep, int leHi=ARW/8-1, int leLo=0) {
277  tkeep.range(leHi, leLo) = keep;
278  }
279  // Set the tlast field
280  void setLE_TLast(LE_tLast last) {
281  tlast = last;
282  }
283 
284 
288  /* Get higher-half part of member 'tdata' and return it in BE order
289  * +---------------+---------------+---------------+---------------+
290  * tdata |ARW-1 Lower-Half (LE) Higher-Half 0|
291  * +---------------+---------------+---------------+---------------+
292  */
294  return getTData(ARW/2-1, 0);
295  }
296  /* Get lower-half part of member 'tdata' and return it in BE order
297  * +---------------+---------------+---------------+---------------+
298  * tdata |ARW-1 Lower-Half (LE) Higher-Half 0|
299  * +---------------+---------------+---------------+---------------+
300  */
302  return getTData(ARW-1, ARW/2);
303  }
304  /* Get higher-half part of member 'tkeep' and return it in BE order
305  * +----------------------+-------------------+
306  * tkeep |ARW/8-1 Lower-Half (LE) Higher-Half 0|
307  * +----------------------+-------------------+
308  */
310  return getTKeep(ARW/8/2-1, 0);
311  }
312  /* Get lower-half part of member 'tkeep' and return it in BE order
313  * +----------------------+-------------------+
314  * tkeep |ARW/8-1 Lower-Half (LE) Higher-Half 0|
315  * +----------------------+-------------------+
316  */
318  return getTKeep(ARW/8-1, ARW/8/2);
319  }
320 
321  /* Set higher-half part of 'tdata' from a parameter encoded in BE order
322  * +---------------+---------------+---------------+---------------+
323  * tdata |ARW-1 Lower-Half (LE) Higher-Half 0|
324  * +---------------+---------------+---------------+---------------+
325  */
326  void setTDataHi(tDataHalf halfData) {
327  switch (ARW) {
328  case 64 : tdata.range(ARW/2-1, 0) = byteSwap32(halfData); break;
329  default : std::cout << "ASSERT - AxisRaw::setTDataHi() - Unsupported Axis raw width.\n"; break;
330  }
331  }
332  /* Set lower-half part of 'tdata' from a parameter encoded in BE order
333  * +---------------+---------------+---------------+---------------+
334  * tdata |ARW-1 Lower-Half (LE) Higher-Half 0|
335  * +---------------+---------------+---------------+---------------+
336  */
337  void setTDataLo(tDataHalf halfData) {
338  switch (ARW) {
339  case 64 : tdata.range(ARW-1, ARW/2) = byteSwap32(halfData); break;
340  default : std::cout << "ASSERT - AxisRaw::setTDataLo() - Unsupported Axis raw width.\n"; break;
341  }
342  }
343  /* Set higher-half part of 'tkeep' from a parameter encoded in BE order
344  * +----------------------+-------------------+
345  * tkeep |ARW/8-1 Lower-Half (LE) Higher-Half 0|
346  * +----------------------+-------------------+
347  */
348  void setTKeepHi(tKeepHalf halfKeep) {
349  switch (ARW) {
350  case 64 : tkeep(ARW/8/2-1, 0) = bitSwap4(halfKeep); break;
351  default : std::cout << "ASSERT - AxisRaw::setTKeepHi() - Unsupported Axis raw width.\n"; break;
352  }
353  }
354  /* Set lower-half part of 'tkeep' from a parameter encoded in BE order
355  * +----------------------+-------------------+
356  * tkeep |ARW/8-1 Lower-Half (LE) Higher-Half 0|
357  * +----------------------+-------------------+
358  */
359  void setTKeepLo(tKeepHalf halfKeep) {
360  switch (ARW) {
361  case 64 : tkeep(ARW/8-1, ARW/8/2) = bitSwap4(halfKeep); break;
362  default : std::cout << "ASSERT - AxisRaw::setTKeepLo() - Unsupported Axis raw width.\n"; break;
363  }
364  }
365 
366 
369  // Get the 'tdata' field in Little-Endian order and return its upper-half part (.i.e data(31,0))
371  return getLE_TData().range(31, 0); // [TODO]
372  }
373  // Get the 'tdata' field in Little-Endian order and return its lower-half part (.i.e, data(63,32)
375  return getLE_TData().range(63, 32); // [TODO]
376  }
377 
378  // Set the 'tdata' field with the upper-half part of a 'data' encoded in Little-Endian order (.i.e, data(31,0))
380  tdata.range(31, 0) = data.range(31, 0); // [TODO]
381  }
382  // Set the 'tdata' field with the lower-half part of a 'data' encoded in Little-Endian order (.i.e, data(63,32))
384  tdata.range(63, 32) = data.range(63, 32); // [TODO]
385  }
386 
387 
390  // Zero the bytes which have their tkeep-bit cleared
392  //for (int i=0, leHi=ARW/8-1, leLo=0; i<ARW/8; i++) { // ARW/8 = noBytes
393  // #pragma HLS UNROLL factor=8
394  // if (tkeep[i] == 0) {
395  // tdata.range(leHi+8*i, leLo+8*i) = 0x00;
396  // }
397  int leHi=ARW/8-1;
398  int leLo=0;
399  switch(this->tkeep){
400  case 0x00: tdata.range(leHi+8*0, leLo+8*0) = 0x00; // No break here
401  case 0x01: tdata.range(leHi+8*1, leLo+8*1) = 0x00; // No break here
402  case 0x03: tdata.range(leHi+8*2, leLo+8*2) = 0x00; // No break here
403  case 0x07: tdata.range(leHi+8*3, leLo+8*3) = 0x00; // No break here
404  case 0x0F: tdata.range(leHi+8*4, leLo+8*4) = 0x00; // No break here
405  case 0x1F: tdata.range(leHi+8*5, leLo+8*5) = 0x00; // No break here
406  case 0x3F: tdata.range(leHi+8*6, leLo+8*6) = 0x00; // No break here
407  case 0x7F: tdata.range(leHi+8*7, leLo+8*7) = 0x00; // No break here
408  }
409  }
410  // Get the length of this chunk (in bytes)
411  int getLen() const {
412  return keepToLen();
413  }
414  // Get the length of the higher-half part of this chunk (in bytes)
415  int getLenHi() {
416  if (keepToLen() > ARW/8/2) {
417  return (ARW/8/2);
418  }
419  else {
420  return keepToLen();
421  }
422  }
423  // Get the length of the lower-half part of this chunk (in bytes)
424  int getLenLo() {
425  if (keepToLen() > ARW/8/2) {
426  return (keepToLen()-ARW/8/2);
427  }
428  else {
429  return 0;
430  }
431  }
432 
433  // Assess the consistency of 'tkeep' and 'tlast'
434  bool isValid() const {
435  if (((tlast == 0) and (tkeep != 0xFF)) or
436  ((tlast == 1) and (keepToLen() == 0))) {
437  return false;
438  }
439  return true;
440  }
441  // Overload = operator to direct assignment from an AxisRaw
442  // AxisApp& operator= (const AxisRaw& _axisRaw) {
443  // this->tdata = _axisRaw.getLE_TData();
444  // this->tkeep = _axisRaw.getLE_TKeep();
445  // this->tlast = _axisRaw.getLE_TLast();
446  // return *this;
447  // }
448 
449  protected:
450  // Return the number of valid bytes
451  int keepToLen() const {
452  switch(this->tkeep){
453  case 0x01: return 1; break;
454  case 0x03: return 2; break;
455  case 0x07: return 3; break;
456  case 0x0F: return 4; break;
457  case 0x1F: return 5; break;
458  case 0x3F: return 6; break;
459  case 0x7F: return 7; break;
460  case 0xFF: return 8; break;
461  }
462  return 0;
463  }
464 
465  private:
466  // Reverse the bits within a pair.
467  ap_uint<2> bitSwap2(ap_uint<2> inputVector) const {
468  return (inputVector.range(0,1));
469  }
470  // Reverse the bits within a nibble.
471  ap_uint<4> bitSwap4(ap_uint<4> inputVector) const {
472  return (inputVector.range(0,3));
473  }
474  // Reverse the bits within a byte.
475  ap_uint<8> bitSwap8(ap_uint<8> inputVector) const {
476  return (inputVector.range(0,7));
477  }
478  // Swap the two bytes of a word (.i.e, 16 bits).
479  ap_uint<16> byteSwap16(ap_uint<16> inputVector) const {
480  return (inputVector.range(7,0), inputVector(15, 8));
481  }
482  // Swap the four bytes of a double-word (.i.e, 32 bits).
483  ap_uint<32> byteSwap32(ap_uint<32> inpDWord) const {
484  return (inpDWord.range( 7, 0), inpDWord.range(15, 8),
485  inpDWord.range(23,16), inpDWord.range(31, 24));
486  }
487  // Swap the eight bytes of a quad-word (.i.e, 64 bits).
488  ap_uint<64> byteSwap64(ap_uint<64> inpQWord) const {
489  return (inpQWord.range( 7, 0), inpQWord(15, 8),
490  inpQWord.range(23,16), inpQWord(31, 24),
491  inpQWord.range(39,32), inpQWord(47, 40),
492  inpQWord.range(55,48), inpQWord(63, 56));
493  }
494 
495 };
496 
497 #endif
498 
void setTLast(tLast last)
Definition: AxisRaw.hpp:246
void setTDataHi(tDataHalf halfData)
Definition: AxisRaw.hpp:326
void setTDataLo(tDataHalf halfData)
Definition: AxisRaw.hpp:337
tData getTData(int leHi=64 -1, int leLo=0) const
Definition: AxisRaw.hpp:191
tLast getTLast() const
Definition: AxisRaw.hpp:219
AxisRaw(LE_tData tdata, LE_tKeep tkeep, LE_tLast tlast)
Definition: AxisRaw.hpp:179
tDataHalf getTDataLo() const
Definition: AxisRaw.hpp:301
LE_tKeep getLE_TKeep(int leHi=64/8-1, int leLo=0) const
Definition: AxisRaw.hpp:264
void setTKeepLo(tKeepHalf halfKeep)
Definition: AxisRaw.hpp:359
void clearUnusedBytes()
Definition: AxisRaw.hpp:391
tKeepHalf getTKeepHi() const
Definition: AxisRaw.hpp:309
int getLenHi()
Definition: AxisRaw.hpp:415
LE_tData tdata
Definition: AxisRaw.hpp:173
AxisRaw()
Definition: AxisRaw.hpp:178
LE_tData getLE_TData(int leHi=64 -1, int leLo=0) const
Definition: AxisRaw.hpp:260
LE_tDataHalf getLE_TDataLo() const
Definition: AxisRaw.hpp:374
void setLE_TDataLo(LE_tData data)
Definition: AxisRaw.hpp:383
void setLE_TLast(LE_tLast last)
Definition: AxisRaw.hpp:280
void setLE_TDataHi(LE_tData data)
Definition: AxisRaw.hpp:379
void setTKeepHi(tKeepHalf halfKeep)
Definition: AxisRaw.hpp:348
void setLE_TData(LE_tData data, int leHi=64 -1, int leLo=0)
Definition: AxisRaw.hpp:272
void setTKeep(tKeep keep)
Definition: AxisRaw.hpp:239
LE_tDataHalf getLE_TDataHi() const
Definition: AxisRaw.hpp:370
int getLen() const
Definition: AxisRaw.hpp:411
tKeep getTKeep(int leHi=64/8-1, int leLo=0) const
Definition: AxisRaw.hpp:207
void setTData(tData data)
Definition: AxisRaw.hpp:228
tDataHalf getTDataHi() const
Definition: AxisRaw.hpp:293
void setLE_TKeep(LE_tKeep keep, int leHi=64/8-1, int leLo=0)
Definition: AxisRaw.hpp:276
int keepToLen() const
Definition: AxisRaw.hpp:451
bool isValid() const
Definition: AxisRaw.hpp:434
LE_tKeep tkeep
Definition: AxisRaw.hpp:174
int getLenLo()
Definition: AxisRaw.hpp:424
tKeepHalf getTKeepLo() const
Definition: AxisRaw.hpp:317
LE_tLast getLE_TLast() const
Definition: AxisRaw.hpp:268
LE_tLast tlast
Definition: AxisRaw.hpp:175
ap_uint< 64 > data
Definition: tb_nal.cpp:832
ap_uint< 64/8 > tKeep
Definition: AxisRaw.hpp:128
ap_uint< 64 > tData
Definition: AxisRaw.hpp:126
ap_uint< 64 > LE_tData
Definition: AxisRaw.hpp:122
ap_uint< 1 > tLast
Definition: AxisRaw.hpp:130
#define ARW
Definition: AxisRaw.hpp:114
ap_uint< 64/8 > LE_tKeep
Definition: AxisRaw.hpp:124
void pAxisRawCast(hls::stream< TypeIn > &si, hls::stream< TypeOut > &so)
AxisRaw cast - Casts an AxisRaw stream to/from an AxisRaw derived class.
Definition: AxisRaw.hpp:148
ap_uint< 1 > LE_tLast
Definition: AxisRaw.hpp:125
ap_uint< 64/16 > tKeepHalf
Definition: AxisRaw.hpp:129
ap_uint< 64/2 > tDataHalf
Definition: AxisRaw.hpp:127
ap_uint< 64/2 > LE_tDataHalf
Definition: AxisRaw.hpp:123