cloudFPGA (cF) API  1.0
The documentation of the source code of cloudFPGA (cF)
iprx.cpp
Go to the documentation of this file.
1 
17 
43 
56 #include "iprx.hpp"
57 
58 using namespace hls;
59 
60 
64 #ifndef __SYNTHESIS__
65  extern bool gTraceEvent;
66 #endif
67 #define THIS_NAME "IPRX"
68 
69 #define TRACE_OFF 0x0000
70 #define TRACE_IBUF 1 << 1
71 #define TRACE_MPD 1 << 2
72 #define TRACE_ILC 1 << 3
73 #define TRACE_ICA 1 << 4
74 #define TRACE_ICC 1 << 5
75 #define TRACE_IID 1 << 6
76 #define TRACE_ICL 1 << 7
77 #define TRACE_IPR 1 << 8
78 #define TRACE_ALL 0xFFFF
79 
80 #define DEBUG_LEVEL (TRACE_OFF)
81 
82 
83 
95  stream<AxisEth> &siETH_Data,
96  stream<AxisEth> &soMPd_Data)
97 {
98  //-- DIRECTIVES FOR THIS PROCESS -------------------------------------------
99  #pragma HLS INLINE off
100  #pragma HLS PIPELINE II=1 enable_flush
101 
102  const char *myName = concat3(THIS_NAME, "/", "IBuf");
103 
104  if (!siETH_Data.empty() && !soMPd_Data.full()) {
105  AxisEth axisEth;
106  siETH_Data.read(axisEth);
107  if (not axisEth.isValid()) {
108  if (DEBUG_LEVEL & TRACE_IBUF) {
109  printWarn(myName, "Received an AxisChunk with an unexpected \'tkeep\' or \'tlast\' value.\n");
110  printAxisRaw(myName, "Aborting the frame after: ", AxisRaw(axisEth.getLE_TData(), axisEth.getLE_TKeep(), axisEth.getLE_TLast()));
111  }
112  soMPd_Data.write(AxisEth(axisEth.getLE_TData(), 0x00, 1));
113  }
114  else {
115  soMPd_Data.write(axisEth);
116  }
117  }
118 }
119 
120 
134  EthAddr piMMIO_MacAddr,
135  stream<AxisEth> &siIBuf_Data,
136  stream<AxisArp> &soARP_Data,
137  stream<AxisEth> &soILc_Data)
138 {
139  //-- DIRECTIVES FOR THIS PROCESS -------------------------------------------
140  #pragma HLS INLINE off
141  #pragma HLS PIPELINE II=1 enable_flush
142 
143  const char *myName = concat3(THIS_NAME, "/", "MPd");
144 
145  //-- STATIC CONTROL VARIABLES (with RESET) ---------------------------------
146  static enum FsmStates { S0=0, S1 } mpd_fsmState=S0;
147  #pragma HLS RESET variable=mpd_fsmState
148  static ap_uint<2> mpd_chunkCount=0;
149  #pragma HLS RESET variable=mpd_chunkCount
150 
151  //-- STATIC DATAFLOW VARIABLES ---------------------------------------------
152  static EtherType mpd_etherType;
153  static AxisEth mpd_prevChunk;
154 
155  //-- DYNAMIC VARIABLES -----------------------------------------------------
156  AxisEth currChunk;
157 
158  switch (mpd_fsmState) {
159  case S0:
160  if (!siIBuf_Data.empty() && !soARP_Data.full() && !soILc_Data.full()) {
161  siIBuf_Data.read(currChunk);
162  switch (mpd_chunkCount) {
163  case 0:
164  // Compare MAC_DA with our MMIO_MacAddress and with BROADCAST
165  // [TODO - Is this really needed given ARP ?]
166  if (currChunk.getEthDstAddr() != piMMIO_MacAddr &&
167  currChunk.getEthDstAddr() != 0xFFFFFFFFFFFF) {
168  mpd_etherType = CMD_DROP;
169  printInfo(myName, "Requesting current frame with MAC destination address = 0x%16.16lX (0x%16.16lX) to be dropped\n",
170  currChunk.getEthDstAddr().to_long(), currChunk.getLE_EthDstAddr().to_long());
171  }
172  else {
173  mpd_etherType = CMD_KEEP;
174  }
175  mpd_chunkCount++;
176  break;
177  default:
178  if (mpd_chunkCount == 1) {
179  if (mpd_etherType != CMD_DROP) {
180  mpd_etherType = currChunk.getEtherType();
181  }
182  mpd_chunkCount++;
183  }
184  if (mpd_etherType == ETH_ETHERTYPE_ARP) {
185  soARP_Data.write(mpd_prevChunk);
186  }
187  else if (mpd_etherType == ETH_ETHERTYPE_IP4) {
188  soILc_Data.write(mpd_prevChunk);
189  }
190  break;
191  }
192  mpd_prevChunk = currChunk;
193  if (currChunk.getLE_TLast()) {
194  mpd_chunkCount = 0;
195  mpd_fsmState = S1;
196  }
197  }
198  break;
199  case S1:
200  if( !soARP_Data.full() && !soILc_Data.full()){
201  if (mpd_etherType == ETH_ETHERTYPE_ARP) {
202  soARP_Data.write(mpd_prevChunk);
203  }
204  else if (mpd_etherType == ETH_ETHERTYPE_IP4) {
205  soILc_Data.write(mpd_prevChunk);
206  }
207  mpd_fsmState = S0;
208  }
209  break;
210 
211  } // End of: switch
212 }
213 
214 
227  stream<AxisEth> &siMPd_Data,
228  stream<AxisEth> &soICa_Data)
229 {
230  //-- DIRECTIVES FOR THIS PROCESS -------------------------------------------
231  #pragma HLS INLINE off
232  #pragma HLS PIPELINE II=1 enable_flush
233 
234  const char *myName = concat3(THIS_NAME, "/", "ILc");
235 
236  //-- STATIC CONTROL VARIABLES (with RESET) ---------------------------------
237  static ap_uint<2> ilc_leftToWrite=0;
238  #pragma HLS RESET variable=ilc_leftToWrite
239  static enum FsmStates {FSM_IDLE=0, FSM_SIZECHECK, FSM_STREAM} ilc_fsmState=FSM_IDLE;
240  #pragma HLS RESET variable=ilc_fsmState
241  static ap_uint<2> ilc_chunkCount=0;
242  #pragma HLS RESET variable=ilc_chunkCount
243  static ap_uint<1> ilc_filterPacket=0;
244  #pragma HLS RESET variable=ilc_filterPacket
245 
246  //-- STATIC DATAFLOW VARIABLES ---------------------------------------------
247  static ap_shift_reg<AxisEth, 2> chunkBuffer; // A shift reg. holding 2 AxisChunks
248 
249  //-- DYNAMIC VARIABLES -----------------------------------------------------
250  AxisEth tempChunk;
251  Ip4TotalLen ip4TotLen;
252 
253  if (ilc_leftToWrite == 0) {
254  if (!siMPd_Data.empty() && !soICa_Data.full()) {
255  AxisEth currChunk = siMPd_Data.read();
256  switch (ilc_fsmState) {
257  case FSM_IDLE:
258  // Read head of shift reg, shift up one, and load current chunk into location 0
259  chunkBuffer.shift(currChunk);
260  if (ilc_chunkCount == 1) {
261  ilc_fsmState = FSM_SIZECHECK;
262  }
263  ilc_chunkCount++;
264  break;
265  case FSM_SIZECHECK:
266  // Check the IPv4/TotalLength field ([FIXME - Consider removing.])
267  ip4TotLen = currChunk.getIp4TotalLen();
268  if (ip4TotLen > MaxDatagramSize) {
269  ilc_filterPacket = 1;
270  printWarn(myName, "Current frame will be discarded because frame is too long!\n");
271  }
272  else {
273  ilc_filterPacket = 0;
274  if (DEBUG_LEVEL & TRACE_ILC) {
275  printInfo(myName, "Start of IPv4 packet - Total length = %d bytes.\n", ip4TotLen.to_int());
276  }
277  }
278  // Read head of shift reg, shift up one, and load current chunk into location 0
279  tempChunk = chunkBuffer.shift(currChunk);
280  if (ilc_filterPacket == 0) {
281  soICa_Data.write(tempChunk);
282  }
283  ilc_fsmState = FSM_STREAM;
284  break;
285  case FSM_STREAM:
286  tempChunk = chunkBuffer.shift(currChunk);
287  if (ilc_filterPacket == 0) {
288  soICa_Data.write(tempChunk);
289  }
290  break;
291  } // End of: switch
292 
293  if (currChunk.getLE_TLast()) {
294  ilc_chunkCount = 0;
295  ilc_leftToWrite = 2;
296  ilc_fsmState = FSM_IDLE;
297  }
298  }
299  }
300  else if (ilc_leftToWrite != 0 && !soICa_Data.full() ) {
301  tempChunk = chunkBuffer.shift(AxisEth(0, 0, 0));
302  if (ilc_filterPacket == 0) {
303  soICa_Data.write(tempChunk);
304  }
305  ilc_leftToWrite--;
306  }
307 }
308 
309 
324  Ip4Addr piMMIO_Ip4Address,
325  stream<AxisEth> &siILc_Data,
326  stream<AxisIp4> &soIId_Data,
327  stream<Ip4Version> &soIId_IpVer,
328  stream<CmdBit> &soIId_DropCmd,
329  stream<SubSums> &soICc_SubSums)
330 {
331  //-- DIRECTIVES FOR THIS PROCESS -------------------------------------------
332  #pragma HLS INLINE off
333  #pragma HLS PIPELINE II=1 enable_flush
334 
335  const char *myName = concat3(THIS_NAME, "/", "ICa");
336 
337  //-- STATIC CONTROL VARIABLES (with RESET) ---------------------------------
338  static bool ica_wasLastChunk=false;
339  #pragma HLS RESET variable=ica_wasLastChunk
340  static ap_uint<3> ica_chunkCount=0;
341  #pragma HLS RESET variable=ica_chunkCount
342 
343  //-- STATIC DATAFLOW VARIABLES --------------------------------------------
344  static ap_uint<17> ica_ipHdrSums[4];
345  static ap_uint<8> ica_ipHdrLen;
346  static LE_Ip4Addr ica_dstIpAddress;
347  static AxisEth ica_prevChunk;
348 
349  //-- DYNAMIC VARIABLES -----------------------------------------------------
350  AxisEth currChunk;
351  AxisIp4 sendChunk;
352  ap_uint<16> ip4FlagsAndFragOff;
353  bool ipAddrMatch;
354 
355  currChunk.setLE_TLast(0);
356  if (!siILc_Data.empty() && !ica_wasLastChunk && !soIId_IpVer.full() &&
357  !soIId_DropCmd.full() && !soICc_SubSums.full() && !soIId_Data.full()) {
358  siILc_Data.read(currChunk);
359 
360  switch (ica_chunkCount) {
361  case 0:
362  // Skip because chunk contains MAC_SA[1:0] | MAC_DA[5:0]
363  for (int i=0; i<4 ;++i) {
364  ica_ipHdrSums[i] = 0;
365  }
366  ica_chunkCount++;
367  break;
368  case 1:
369  // Retrieve the IP version field
370  soIId_IpVer.write(currChunk.getIp4Version());
371  // Retrieve the Internet Header Length
372  ica_ipHdrLen = currChunk.getIp4HdrLen();
373  // Retrieve the first two bytes of the IPv4 header
374  ica_ipHdrSums[3].range(15,12) = currChunk.getIp4Version();
375  ica_ipHdrSums[3].range(11, 8) = currChunk.getIp4HdrLen();
376  ica_ipHdrSums[3].range( 7, 0) = currChunk.getIp4ToS();
377  ica_chunkCount++;
378  break;
379  case 2:
380  // Check for fragmentation in this cycle. Need to check the MF flag.
381  // If set, then drop. If not set, then check the fragment offset and
382  // if it is non-zero then drop.
383  ip4FlagsAndFragOff = byteSwap16(currChunk.getLE_TData().range(47, 32));
384  if (ip4FlagsAndFragOff.range(12, 0) != 0 || ip4FlagsAndFragOff.bit(13) != 0) {
385  soIId_DropCmd.write(CMD_DROP);
386  if (ip4FlagsAndFragOff.bit(13) != 0) {
387  printWarn(myName, "The More Fragments (MF) is set but IP fragmentation is not supported (yet).\n");
388  }
389  if (ip4FlagsAndFragOff.range(12, 0) != 0) {
390  printWarn(myName, "Fragment offset is set but not supported (yet) !!!\n");
391  }
392  }
393  else {
394  soIId_DropCmd.write(CMD_KEEP);
395  }
396  for (int i = 0; i < 4; i++) {
397  #pragma HLS unroll
398  ica_ipHdrSums[i] += byteSwap16(currChunk.getLE_TData().range(i*16+15, i*16));
399  ica_ipHdrSums[i] = (ica_ipHdrSums[i] + (ica_ipHdrSums[i] >> 16)) & 0xFFFF;
400  }
401  ica_ipHdrLen -= 2;
402  ica_chunkCount++;
403  break;
404  case 3:
405  ica_dstIpAddress.range(31, 16) = currChunk.getIp4DstAddrHi();
406  for (int i = 0; i < 4; i++) {
407  #pragma HLS unroll
408  ica_ipHdrSums[i] += byteSwap16(currChunk.getLE_TData().range(i*16+15, i*16));
409  ica_ipHdrSums[i] = (ica_ipHdrSums[i] + (ica_ipHdrSums[i] >> 16)) & 0xFFFF;
410  }
411  ica_ipHdrLen -= 2;
412  ica_chunkCount++;
413  break;
414 
415  default:
416  if (ica_chunkCount == 4) {
417  ica_dstIpAddress(15, 0) = currChunk.getIp4DstAddrLo();
418  }
419  switch (ica_ipHdrLen) {
420  case 0:
421  break;
422  case 1:
423  // Sum up part0
424  ica_ipHdrSums[0] += currChunk.getIp4DstAddrLo();
425  ica_ipHdrSums[0] = (ica_ipHdrSums[0] + (ica_ipHdrSums[0] >> 16)) & 0xFFFF;
426  ica_ipHdrLen = 0;
427  // Assess destination IP address (FYI - IP Broadcast addresses are dropped)
428  if (ica_dstIpAddress == piMMIO_Ip4Address) {
429  ipAddrMatch = true;
430  }
431  else {
432  ipAddrMatch = false;
433  }
434  soICc_SubSums.write(SubSums(ica_ipHdrSums, ipAddrMatch));
435  break;
436  case 2:
437  // Sum up parts 0-2
438  for (int i = 0; i < 4; i++) {
439  #pragma HLS unroll
440  ica_ipHdrSums[i] += byteSwap16(currChunk.getLE_TData().range(i*16+15, i*16));
441  ica_ipHdrSums[i] = (ica_ipHdrSums[i] + (ica_ipHdrSums[i] >> 16)) & 0xFFFF;
442  }
443  ica_ipHdrLen = 0;
444  // Assess destination IP address (FYI - IP Broadcast addresses are dropped)
445  if (ica_dstIpAddress == piMMIO_Ip4Address) {
446  // || ica_dstIpAddress == 0xFFFFFFFF) {
447  ipAddrMatch = true;
448  }
449  else {
450  ipAddrMatch = false;
451  }
452  soICc_SubSums.write(SubSums(ica_ipHdrSums, ipAddrMatch));
453  break;
454  default:
455  // Sum up everything
456  for (int i = 0; i < 4; i++) {
457  #pragma HLS unroll
458  ica_ipHdrSums[i] += byteSwap16(currChunk.getLE_TData().range(i*16+15, i*16));
459  ica_ipHdrSums[i] = (ica_ipHdrSums[i] + (ica_ipHdrSums[i] >> 16)) & 0xFFFF;
460  }
461  ica_ipHdrLen -= 2;
462  break;
463  }
464  break;
465  } // End of: switch(ica_chunkCount)f
466 
467  if (ica_chunkCount > 2) {
468  // Send AxisIp4 chunks while re-aligning the outgoing chunks
469  sendChunk = AxisIp4((currChunk.getLE_TData().range(47, 0), ica_prevChunk.getLE_TData().range(63, 48)),
470  (currChunk.getLE_TKeep().range( 5, 0), ica_prevChunk.getLE_TKeep().range( 7, 6)),
471  (currChunk.getLE_TKeep()[6] == 0));
472  soIId_Data.write(sendChunk);
473  }
474  ica_prevChunk = currChunk;
475  if (currChunk.getLE_TLast()) {
476  ica_chunkCount = 0;
477  ica_wasLastChunk = !sendChunk.getLE_TLast();
478  }
479  }
480  else if(ica_wasLastChunk && !soIId_Data.full()) {
481  // Send remaining Chunk;
482  sendChunk = AxisIp4(ica_prevChunk.getLE_TData().range(63, 48),
483  ica_prevChunk.getLE_TKeep().range( 7, 6),
484  TLAST);
485  soIId_Data.write(sendChunk);
486  ica_wasLastChunk = false;
487  }
488 }
489 
490 
505  stream<AxisIp4> &siICa_Data,
506  stream<Ip4Version> &siICa_IpVer,
507  stream<ValBit> &siICa_DropFrag,
508  stream<ValBit> &siICc_CsumValid,
509  stream<AxisIp4> &soICl_Data)
510 {
511  //-- DIRECTIVES FOR THIS PROCESS -------------------------------------------
512  #pragma HLS INLINE off
513  #pragma HLS PIPELINE II=1 enable_flush
514 
515  const char *myName = concat3(THIS_NAME, "/", "IId");
516 
517  //-- STATIC CONTROL VARIABLES (with RESET) ---------------------------------
518  static enum FsmStates {FSM_IDLE=0, FSM_FWD, FSM_DROP} iid_fsmState=FSM_IDLE;
519  #pragma HLS RESET variable=iid_fsmState
520 
521  //-- DYNAMIC VARIABLES -----------------------------------------------------
522  AxisIp4 currChunk = AxisIp4(0, 0, 0);
523 
524  switch(iid_fsmState) {
525  case FSM_IDLE:
526  if (!siICc_CsumValid.empty() && !siICa_IpVer.empty() && !siICa_DropFrag.empty() &&
527  !siICa_Data.empty() && !soICl_Data.full()) {
528  siICa_Data.read(currChunk);
529  // Assess validity of the current IPv4 packet
530  ValBit csumValid = (siICc_CsumValid.read() == 1); // CSUM is valid
531  ValBit isIpv4Pkt = (siICa_IpVer.read() == 4); // IP Version is 4
532  ValBit doKeepPkt = (siICa_DropFrag.read() == CMD_KEEP); // Do not drop
533  ap_uint<2> valid = (csumValid + isIpv4Pkt + doKeepPkt);
534  if (valid != 3) {
535  iid_fsmState = FSM_DROP;
536  printWarn(myName, "The current IP packet will be dropped because:\n");
537  printWarn(myName, " csumValid=%d | isIpv4Pkt=%d | doKeepPkt=%d\n",
538  csumValid.to_int(), isIpv4Pkt.to_int(), doKeepPkt.to_int());
539  }
540  else {
541  soICl_Data.write(currChunk);
542  iid_fsmState = FSM_FWD;
543  }
544  }
545  break;
546  case FSM_FWD:
547  if(!siICa_Data.empty() && !soICl_Data.full()) {
548  siICa_Data.read(currChunk);
549  soICl_Data.write(currChunk);
550  if (currChunk.getLE_TLast()) {
551  iid_fsmState = FSM_IDLE;
552  }
553  }
554  break;
555  case FSM_DROP:
556  if(!siICa_Data.empty()){
557  siICa_Data.read(currChunk);
558  if (currChunk.getLE_TLast()) {
559  iid_fsmState = FSM_IDLE;
560  }
561  }
562  break;
563  }
564 }
565 
566 
577  stream<AxisIp4> &siIId_Data,
578  stream<AxisIp4> &soIPr_Data)
579 {
580  //-- DIRECTIVES FOR THIS PROCESS -------------------------------------------
581  #pragma HLS INLINE off
582  #pragma HLS PIPELINE II=1 enable_flush
583 
584  const char *myName = concat3(THIS_NAME, "/", "ICl");
585 
586  //-- STATIC CONTROL VARIABLES (with RESET) ---------------------------------
587  static enum FsmStates {FSM_FWD=0, FSM_DROP} icl_fsmState=FSM_FWD;
588  #pragma HLS RESET variable=icl_fsmState
589  static ap_uint<13> icl_chunkCount=0; // Ip4TotalLen/8
590  #pragma HLS RESET variable=icl_chunkCount
591 
592  //-- STATIC DATAFLOW VARIABLES ---------------------------------------------
593  static Ip4TotalLen icl_ip4TotalLength;
594 
595  switch(icl_fsmState){
596  case FSM_FWD:
597  if (!siIId_Data.empty() && !soIPr_Data.full()) {
598  AxisIp4 currChunk = siIId_Data.read();
599  switch (icl_chunkCount) {
600  case 0:
601  icl_ip4TotalLength = currChunk.getIp4TotalLen();
602  break;
603  default:
604  if (((icl_chunkCount+1)*8) >= icl_ip4TotalLength) {
605  if (currChunk.getLE_TLast() == 0) {
606  icl_fsmState = FSM_DROP;
607  }
608  currChunk.setLE_TLast(TLAST);
609  ap_uint<4> leftLength = icl_ip4TotalLength - (icl_chunkCount*8);
610  currChunk.setLE_TKeep(lenToLE_tKeep(leftLength));
611  }
612  break;
613  } // End of: switch(icl_chunkCount)
614  soIPr_Data.write(currChunk);
615  icl_chunkCount++;
616  if (currChunk.getLE_TLast()) {
617  icl_chunkCount = 0;
618  }
619  }
620  break;
621  case FSM_DROP:
622  if (!siIId_Data.empty()) {
623  AxisIp4 currChunk = siIId_Data.read();
624  if (currChunk.getLE_TLast()) {
625  icl_fsmState = FSM_FWD;
626  }
627  }
628  break;
629 
630  } // End of: switch(icl_fsmState)
631 }
632 
633 
644  stream<SubSums> &siICa_SubSums,
645  stream<ValBit> &soIId_CsumValid)
646 {
647  //-- DIRECTIVES FOR THIS PROCESS -------------------------------------------
648  #pragma HlS INLINE off
649  #pragma HLS PIPELINE II=1 enable_flush
650 
651  const char *myName = concat3(THIS_NAME, "/", "ICc");
652 
653  if (!siICa_SubSums.empty() && !soIId_CsumValid.full()) {
654  SubSums ipHdrSums = siICa_SubSums.read();
655 
656  ipHdrSums.sum0 += ipHdrSums.sum2;
657  ipHdrSums.sum1 += ipHdrSums.sum3;
658  ipHdrSums.sum0 = (ipHdrSums.sum0 + (ipHdrSums.sum0 >> 16)) & 0xFFFF;
659  ipHdrSums.sum1 = (ipHdrSums.sum1 + (ipHdrSums.sum1 >> 16)) & 0xFFFF;
660  ipHdrSums.sum0 += ipHdrSums.sum1;
661  ipHdrSums.sum0 = (ipHdrSums.sum0 + (ipHdrSums.sum0 >> 16)) & 0xFFFF;
662  ipHdrSums.sum0 = ~ipHdrSums.sum0;
663  if (ipHdrSums.sum0(15, 0) != 0x0000) {
664  printError(myName, "Bad IP header checksum: Expected 0x0000 - Computed 0x%4.4X\n", ipHdrSums.sum0(15, 0).to_int());
665  }
666  soIId_CsumValid.write((ipHdrSums.sum0(15, 0) == 0x0000) && ipHdrSums.ipMatch);
667  }
668 }
669 
670 
690  stream<AxisIp4> &siICl_Data,
691  stream<AxisIp4> &soICMP_Data,
692  stream<AxisIp4> &soICMP_Derr,
693  stream<AxisIp4> &soUOE_Data,
694  stream<AxisIp4> &soTOE_Data)
695 {
696  //-- DIRECTIVES FOR THIS PROCESS -------------------------------------------
697  #pragma HLS INLINE off
698  #pragma HLS PIPELINE II=1 enable_flush
699 
700  const char *myName = concat3(THIS_NAME, "/", "IPr");
701 
702  //-- STATIC CONTROL VARIABLES (with RESET) ---------------------------------
703  static enum FsmStates { FSM_IDLE=0, FSM_LAST} ipr_fsmState=FSM_IDLE;
704  #pragma HLS RESET variable=ipr_fsmState
705  static ap_uint<2> ipr_chunkCount=0;
706  #pragma HLS RESET variable=ipr_chunkCount
707  static bool ipr_leftToWrite=false;
708  #pragma HLS RESET variable=ipr_leftToWrite
709 
710  //-- STATIC DATAFLOW VARIABLES ---------------------------------------------
711  static StsBit ipr_ttlExpired;
712  static Ip4Prot ipr_ipProtocol;
713  static AxisIp4 ipr_prevChunk;
714 
715  //-- DYNAMIC VARIABLES -----------------------------------------------------
716  AxisIp4 currChunk;
717 
718  switch (ipr_fsmState) {
719  case FSM_IDLE:
720  if (!siICl_Data.empty() &&
721  !soICMP_Derr.full() && !soICMP_Data.full() &&
722  !soUOE_Data.full() && !soTOE_Data.full()) {
723  siICl_Data.read(currChunk);
724  switch (ipr_chunkCount) {
725  case 0:
726  ipr_chunkCount++;
727  break;
728  default:
729  if (ipr_chunkCount == 1) {
730  if (currChunk.getIp4TtL() == 1) {
731  ipr_ttlExpired = 1;
732  }
733  else {
734  ipr_ttlExpired = 0;
735  }
736  ipr_ipProtocol = currChunk.getIp4Prot();
737  ipr_chunkCount++;
738  }
739  if (ipr_ttlExpired == 1) {
740  // Forward the current IP packet to ICMP for building the error message
741  soICMP_Derr.write(ipr_prevChunk);
742  }
743  else {
744  switch (ipr_ipProtocol) {
745  // FYI - There is no default case. If the current packet
746  // does not match any case, it is automatically dropped.
747  case IP4_PROT_ICMP:
748  soICMP_Data.write(ipr_prevChunk);
749  break;
750  case IP4_PROT_UDP:
751  soUOE_Data.write(ipr_prevChunk);
752  break;
753  case IP4_PROT_TCP:
754  soTOE_Data.write(ipr_prevChunk);
755  break;
756  }
757  }
758  break;
759  }
760  ipr_prevChunk = currChunk;
761  if (currChunk.getLE_TLast()) {
762  ipr_chunkCount = 0;
763  ipr_leftToWrite = true;
764  ipr_fsmState = FSM_LAST;
765  }
766  }
767  break;
768  case FSM_LAST:
769  if (!soICMP_Derr.full() &&
770  !soICMP_Data.full() && !soUOE_Data.full() && !soTOE_Data.full() ) {
771  ap_uint<log2Ceil<8>::val> bitCounter = 0;
772  bitCounter = ipr_prevChunk.getLen();
773  if (ipr_prevChunk.getLE_TKeep() != 0xFF) {
774  ipr_prevChunk.setLE_TData(0, 63, 64-((8-bitCounter.to_int())*8));
775  }
776  if (ipr_ttlExpired == 1) {
777  soICMP_Derr.write(ipr_prevChunk);
778  }
779  else {
780  switch (ipr_ipProtocol) {
781  case IP4_PROT_ICMP:
782  soICMP_Data.write(ipr_prevChunk);
783  break;
784  case IP4_PROT_UDP:
785  soUOE_Data.write(ipr_prevChunk);
786  break;
787  case IP4_PROT_TCP:
788  soTOE_Data.write(ipr_prevChunk);
789  break;
790  }
791  }
792  ipr_leftToWrite = false;
793  ipr_fsmState = FSM_IDLE;
794  }
795  break;
796  }
797 }
798 
799 
800 
826 void iprx(
827  //------------------------------------------------------
828  //-- MMIO Interfaces
829  //------------------------------------------------------
830  EthAddr piMMIO_MacAddress,
831  Ip4Addr piMMIO_Ip4Address,
832  //------------------------------------------------------
833  //-- ETHernet MAC Layer Interface
834  //------------------------------------------------------
835  stream<AxisEth> &siETH_Data,
836  //------------------------------------------------------
837  //-- ARP Interface
838  //------------------------------------------------------
839  stream<AxisArp> &soARP_Data,
840  //------------------------------------------------------
841  //-- ICMP Interfaces
842  //------------------------------------------------------
843  stream<AxisIp4> &soICMP_Data,
844  stream<AxisIp4> &soICMP_Derr,
845  //------------------------------------------------------
846  //-- UOE Interface
847  //------------------------------------------------------
848  stream<AxisIp4> &soUOE_Data,
849  //------------------------------------------------------
850  //-- TOE Interface
851  //------------------------------------------------------
852  stream<AxisIp4> &soTOE_Data)
853 {
854  //-- DIRECTIVES FOR THIS PROCESS -------------------------------------------
855  #pragma HLS DATAFLOW
856  #pragma HLS INLINE
857  #pragma HLS INTERFACE ap_ctrl_none port=return
858 
859  //--------------------------------------------------------------------------
860  //-- LOCAL STREAMS (Sorted by the name of the modules which generate them)
861  //--------------------------------------------------------------------------
862 
863  //-- Input Buffer (IBuf)
864  static stream<AxisEth> ssIBufToMPd_Data ("ssIBufToMPd_Data");
865  #pragma HLS STREAM variable=ssIBufToMPd_Data depth=8192
866 
867  //-- MAC Protocol Detector (MPd)
868  static stream<AxisEth> ssMPdToILc_Data ("ssMPdToILc_Data");
869  #pragma HLS STREAM variable=ssMPdToILc_Data depth=32
870 
871  //-- IPv4 Length Checker (ILc)
872  static stream<AxisEth> ssILcToICa_Data ("ssILcToICa_Data");
873  #pragma HLS STREAM variable=ssILcToICa_Data depth=32
874 
875  //-- IPv4 Checksum Accumulator (ICa)
876  static stream<AxisIp4> ssICaToIId_Data ("ssICaToIId_Data");
877  #pragma HLS STREAM variable=ssICaToIId_Data depth=1024 // Must hold IP header for checksum checking
878  static stream<Ip4Version> ssICaToIId_IpVer ("ssICaToIId_IpVer");
879  #pragma HLS STREAM variable=ssICaToIId_IpVer depth=32
880  static stream<CmdBit> ssICaToIId_DropFrag ("ssICaToIId_DropFrag");
881  #pragma HLS STREAM variable=ssICaToIId_DropFrag depth=32
882  static stream<SubSums> ssICaToICc_SubSums ("ssICaToICc_SubSums");
883  #pragma HLS DATA_PACK variable=ssICaToICc_SubSums
884  #pragma HLS STREAM variable=ssICaToICc_SubSums depth=32
885 
886  //-- IPv4 Invalid Dropper (IId)
887  static stream<AxisIp4> ssIIdToICl_Data ("ssIIdToICl_Data");
888  #pragma HLS DATA_PACK variable=ssIIdToICl_Data
889  #pragma HLS STREAM variable=ssIIdToICl_Data depth=32
890 
891  //-- IPv4 Cut Length (ICl)
892  static stream<AxisIp4> ssIClToIPr_Data ("ssIClToIPr_Data");
893  #pragma HLS DATA_PACK variable=ssIClToIPr_Data
894  #pragma HLS STREAM variable=ssIClToIPr_Data depth=32
895 
896  //-- IPv4 Checksum Checker
897  static stream<ValBit> ssICcToIId_CsumVal ("ssICcToIId_CsumVal");
898  #pragma HLS STREAM variable=ssICcToIId_CsumVal depth=32
899 
900  //-- PROCESS FUNCTIONS -----------------------------------------------------
901 
902  pInputBuffer(
903  siETH_Data,
904  ssIBufToMPd_Data);
905 
907  piMMIO_MacAddress,
908  ssIBufToMPd_Data,
909  soARP_Data,
910  ssMPdToILc_Data);
911 
913  ssMPdToILc_Data,
914  ssILcToICa_Data);
915 
917  piMMIO_Ip4Address,
918  ssILcToICa_Data,
919  ssICaToIId_Data,
920  ssICaToIId_IpVer,
921  ssICaToIId_DropFrag,
922  ssICaToICc_SubSums);
923 
925  ssICaToICc_SubSums,
926  ssICcToIId_CsumVal);
927 
929  ssICaToIId_Data,
930  ssICaToIId_IpVer,
931  ssICaToIId_DropFrag,
932  ssICcToIId_CsumVal,
933  ssIIdToICl_Data);
934 
935  pIpCutLength(
936  ssIIdToICl_Data,
937  ssIClToIPr_Data);
938 
940  ssIClToIPr_Data,
941  soICMP_Data,
942  soICMP_Derr,
943  soUOE_Data,
944  soTOE_Data);
945 
946 }
947 
948 
961 #if HLS_VERSION == 2017
962  void iprx_top(
963  //------------------------------------------------------
964  //-- MMIO Interfaces
965  //------------------------------------------------------
966  EthAddr piMMIO_MacAddress,
967  Ip4Addr piMMIO_Ip4Address,
968  //------------------------------------------------------
969  //-- ETHernet MAC Layer Interface
970  //------------------------------------------------------
971  stream<AxisEth> &siETH_Data,
972  //------------------------------------------------------
973  //-- ARP Interface
974  //------------------------------------------------------
975  stream<AxisArp> &soARP_Data,
976  //------------------------------------------------------
977  //-- ICMP Interfaces
978  //------------------------------------------------------
979  stream<AxisIp4> &soICMP_Data,
980  stream<AxisIp4> &soICMP_Derr,
981  //------------------------------------------------------
982  //-- UOE Interface
983  //------------------------------------------------------
984  stream<AxisIp4> &soUOE_Data,
985  //------------------------------------------------------
986  //-- TOE Interface
987  //------------------------------------------------------
988  stream<AxisIp4> &soTOE_Data)
989 {
990  //-- DIRECTIVES FOR THE INTERFACES -----------------------------------------
991  #pragma HLS INTERFACE ap_ctrl_none port=return
992 
993 
994 
995 
996 
997  #pragma HLS INTERFACE ap_stable register port=piMMIO_MacAddress
998  #pragma HLS INTERFACE ap_stable register port=piMMIO_Ip4Address
999 
1000  #pragma HLS RESOURCE core=AXI4Stream variable=siETH_Data metadata="-bus_bundle siETH_Data"
1001 
1002  #pragma HLS RESOURCE core=AXI4Stream variable=soARP_Data metadata="-bus_bundle soARP_Data"
1003 
1004  #pragma HLS RESOURCE core=AXI4Stream variable=soICMP_Data metadata="-bus_bundle soICMP_Data"
1005  #pragma HLS RESOURCE core=AXI4Stream variable=soICMP_Derr metadata="-bus_bundle soICMP_Derr"
1006 
1007  #pragma HLS RESOURCE core=AXI4Stream variable=soUOE_Data metadata="-bus_bundle soUOE_Data"
1008  #pragma HLS RESOURCE core=AXI4Stream variable=soTOE_Data metadata="-bus_bundle soTOE_Data"
1009 
1010  //-- DIRECTIVES FOR THIS PROCESS -------------------------------------------
1011  #pragma HLS DATAFLOW
1012 
1013  //-- MAIN IPRX PROCESS -----------------------------------------------------
1014  iprx(
1015  //-- MMIO Interfaces
1016  piMMIO_MacAddress,
1017  piMMIO_Ip4Address,
1018  //-- ETHernet MAC Layer Interface
1019  siETH_Data,
1020  //-- ARP Interface
1021  soARP_Data,
1022  //-- ICMP Interfaces
1023  soICMP_Data,
1024  soICMP_Derr,
1025  //-- UDP Interface
1026  soUOE_Data,
1027  //-- TOE Interface
1028  soTOE_Data);
1029 
1030 }
1031 #else
1032  void iprx_top(
1033  //------------------------------------------------------
1034  //-- MMIO Interfaces
1035  //------------------------------------------------------
1036  EthAddr piMMIO_MacAddress,
1037  Ip4Addr piMMIO_Ip4Address,
1038  //------------------------------------------------------
1039  //-- ETHernet MAC Layer Interface
1040  //------------------------------------------------------
1041  stream<AxisRaw> &siETH_Data,
1042  //------------------------------------------------------
1043  //-- ARP Interface
1044  //------------------------------------------------------
1045  stream<AxisRaw> &soARP_Data,
1046  //------------------------------------------------------
1047  //-- ICMP Interfaces
1048  //------------------------------------------------------
1049  stream<AxisRaw> &soICMP_Data,
1050  stream<AxisRaw> &soICMP_Derr,
1051  //------------------------------------------------------
1052  //-- UOE Interface
1053  //------------------------------------------------------
1054  stream<AxisRaw> &soUOE_Data,
1055  //------------------------------------------------------
1056  //-- TOE Interface
1057  //------------------------------------------------------
1058  stream<AxisRaw> &soTOE_Data)
1059 {
1060 
1061  //-- DIRECTIVES FOR THE INTERFACES -----------------------------------------
1062  #pragma HLS INTERFACE ap_ctrl_none port=return
1063 
1064  #pragma HLS INTERFACE ap_stable port=piMMIO_MacAddress name=piMMIO_MacAddress
1065  #pragma HLS INTERFACE ap_stable port=piMMIO_Ip4Address name=piMMIO_Ip4Address
1066 
1067  #pragma HLS INTERFACE axis off port=siETH_Data name=siETH_Data
1068 
1069  #pragma HLS INTERFACE axis off port=soARP_Data name=soARP_Data
1070 
1071  #pragma HLS INTERFACE axis off port=soICMP_Data name=soICMP_Data
1072  #pragma HLS INTERFACE axis off port=soICMP_Derr name=soICMP_Derr
1073 
1074  #pragma HLS INTERFACE axis off port=soUOE_Data name=soUOE_Data
1075  #pragma HLS INTERFACE axis off port=soTOE_Data name=soTOE_Data
1076 
1077  //-- DIRECTIVES FOR THIS PROCESS -------------------------------------------
1078  #pragma HLS DATAFLOW disable_start_propagation
1079 
1080  //-- LOCAL INPUT and OUTPUT STREAMS ----------------------------------------
1081  static stream<AxisEth> ssiETH_Data;
1082  static stream<AxisArp> ssoARP_Data;
1083  static stream<AxisIp4> ssoICMP_Data;
1084  static stream<AxisIp4> ssoICMP_Derr;
1085  static stream<AxisIp4> ssoUOE_Data;
1086  static stream<AxisIp4> ssoTOE_Data;
1087 
1088  //-- INPUT STREAM CASTING --------------------------------------------------
1089  pAxisRawCast(siETH_Data, ssiETH_Data);
1090 
1091  //-- MAIN IPRX PROCESS -----------------------------------------------------
1092  iprx(
1093  //-- MMIO Interfaces
1094  piMMIO_MacAddress,
1095  piMMIO_Ip4Address,
1096  //-- ETHernet MAC Layer Interface
1097  ssiETH_Data,
1098  //-- ARP Interface
1099  ssoARP_Data,
1100  //-- ICMP Interfaces
1101  ssoICMP_Data,
1102  ssoICMP_Derr,
1103  //-- UDP Interface
1104  ssoUOE_Data,
1105  //-- TOE Interface
1106  ssoTOE_Data);
1107 
1108  //-- OUTPUT STREAM CASTING -------------------------------------------------
1109  pAxisRawCast(ssoARP_Data, soARP_Data);
1110  pAxisRawCast(ssoICMP_Data, soICMP_Data);
1111  pAxisRawCast(ssoICMP_Derr, soICMP_Derr);
1112  pAxisRawCast(ssoUOE_Data, soUOE_Data);
1113  pAxisRawCast(ssoTOE_Data, soTOE_Data);
1114 
1115 }
1116 #endif // HLS_VERSION
1117 
Ip4HdrLen getIp4HdrLen()
Definition: AxisEth.hpp:237
Ip4DstAddrHi getIp4DstAddrHi()
Definition: AxisEth.hpp:268
EtherType getEtherType()
Definition: AxisEth.hpp:172
Ip4Version getIp4Version()
Definition: AxisEth.hpp:234
Ip4DstAddrLo getIp4DstAddrLo()
Definition: AxisEth.hpp:270
LE_EthAddr getLE_EthDstAddr()
Definition: AxisEth.hpp:176
Ip4TotalLen getIp4TotalLen()
Definition: AxisEth.hpp:243
EthAddr getEthDstAddr()
Definition: AxisEth.hpp:161
Ip4ToS getIp4ToS()
Definition: AxisEth.hpp:240
Ip4TtL getIp4TtL()
Definition: AxisIp4.hpp:218
Ip4TotalLen getIp4TotalLen()
Definition: AxisIp4.hpp:205
Ip4Prot getIp4Prot()
Definition: AxisIp4.hpp:221
LE_tKeep getLE_TKeep(int leHi=64/8-1, int leLo=0) const
Definition: AxisRaw.hpp:264
LE_tData getLE_TData(int leHi=64 -1, int leLo=0) const
Definition: AxisRaw.hpp:260
void setLE_TLast(LE_tLast last)
Definition: AxisRaw.hpp:280
void setLE_TData(LE_tData data, int leHi=64 -1, int leLo=0)
Definition: AxisRaw.hpp:272
int getLen() const
Definition: AxisRaw.hpp:411
void setLE_TKeep(LE_tKeep keep, int leHi=64/8-1, int leLo=0)
Definition: AxisRaw.hpp:276
bool isValid() const
Definition: AxisRaw.hpp:434
LE_tLast getLE_TLast() const
Definition: AxisRaw.hpp:268
Definition: iprx.hpp:73
ap_uint< 17 > sum1
Definition: iprx.hpp:76
ap_uint< 17 > sum0
Definition: iprx.hpp:75
bool ipMatch
Definition: iprx.hpp:79
ap_uint< 17 > sum2
Definition: iprx.hpp:77
ap_uint< 17 > sum3
Definition: iprx.hpp:78
#define FSM_IDLE
Definition: harris.hpp:79
void pIpCutLength(stream< AxisIp4 > &siIId_Data, stream< AxisIp4 > &soIPr_Data)
Definition: iprx.cpp:576
#define TRACE_IBUF
Definition: iprx.cpp:70
void pIpLengthChecker(stream< AxisEth > &siMPd_Data, stream< AxisEth > &soICa_Data)
Definition: iprx.cpp:226
const UdpLen MaxDatagramSize
Definition: iprx.hpp:68
void pIpInvalidDropper(stream< AxisIp4 > &siICa_Data, stream< Ip4Version > &siICa_IpVer, stream< ValBit > &siICa_DropFrag, stream< ValBit > &siICc_CsumValid, stream< AxisIp4 > &soICl_Data)
Definition: iprx.cpp:504
void iprx(EthAddr piMMIO_MacAddress, Ip4Addr piMMIO_Ip4Address, stream< AxisEth > &siETH_Data, stream< AxisArp > &soARP_Data, stream< AxisIp4 > &soICMP_Data, stream< AxisIp4 > &soICMP_Derr, stream< AxisIp4 > &soUOE_Data, stream< AxisIp4 > &soTOE_Data)
Main process of the IP Receive handler (IPRX).
Definition: iprx.cpp:826
#define TRACE_ILC
Definition: iprx.cpp:72
bool gTraceEvent
Definition: tb_nal.cpp:151
void iprx_top(EthAddr piMMIO_MacAddress, Ip4Addr piMMIO_Ip4Address, stream< AxisRaw > &siETH_Data, stream< AxisRaw > &soARP_Data, stream< AxisRaw > &soICMP_Data, stream< AxisRaw > &soICMP_Derr, stream< AxisRaw > &soUOE_Data, stream< AxisRaw > &soTOE_Data)
Top of IP Receive handler (IPRX)
Definition: iprx.cpp:1032
void pInputBuffer(stream< AxisEth > &siETH_Data, stream< AxisEth > &soMPd_Data)
Definition: iprx.cpp:94
#define THIS_NAME
Definition: iprx.cpp:67
void pMacProtocolDetector(EthAddr piMMIO_MacAddr, stream< AxisEth > &siIBuf_Data, stream< AxisArp > &soARP_Data, stream< AxisEth > &soILc_Data)
Definition: iprx.cpp:133
void pIpChecksumChecker(stream< SubSums > &siICa_SubSums, stream< ValBit > &soIId_CsumValid)
Definition: iprx.cpp:643
void pIpPacketRouter(stream< AxisIp4 > &siICl_Data, stream< AxisIp4 > &soICMP_Data, stream< AxisIp4 > &soICMP_Derr, stream< AxisIp4 > &soUOE_Data, stream< AxisIp4 > &soTOE_Data)
Definition: iprx.cpp:689
#define DEBUG_LEVEL
Definition: iprx.cpp:80
void pIpChecksumAccumulator(Ip4Addr piMMIO_Ip4Address, stream< AxisEth > &siILc_Data, stream< AxisIp4 > &soIId_Data, stream< Ip4Version > &soIId_IpVer, stream< CmdBit > &soIId_DropCmd, stream< SubSums > &soICc_SubSums)
Definition: iprx.cpp:323
#define IP4_PROT_ICMP
Definition: nts_types.hpp:183
ap_uint< 8 > Ip4Prot
Definition: AxisIp4.hpp:164
ap_uint< 48 > EthAddr
Definition: AxisEth.hpp:120
#define printError(callerName, format,...)
A macro to print an error message.
Definition: nts_utils.hpp:195
ap_uint< 32 > LE_Ip4Addr
Definition: AxisIp4.hpp:149
LE_tKeep lenToLE_tKeep(ap_uint< 4 > noValidBytes)
A function to set a number of '1' in an 8-bit field. It is used here to set the number of valid bytes...
Definition: nts_utils.cpp:307
ap_uint< 1 > StsBit
Definition: nts_types.hpp:116
#define IP4_PROT_UDP
Definition: nts_types.hpp:185
void printAxisRaw(const char *callerName, AxisRaw chunk)
Prints an Axis raw data chunk (used for debugging).
Definition: nts_utils.cpp:46
ap_uint< 32 > Ip4Addr
Definition: AxisIp4.hpp:169
ap_uint< 1 > ValBit
Definition: nts_types.hpp:117
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
#define CMD_DROP
Definition: nts_types.hpp:61
#define IP4_PROT_TCP
Definition: nts_types.hpp:184
#define ETH_ETHERTYPE_ARP
Definition: nts_types.hpp:156
#define CMD_KEEP
Definition: nts_types.hpp:62
#define printInfo(callerName, format,...)
A macro to print an information message.
Definition: nts_utils.hpp:169
ap_uint< 16 > Ip4TotalLen
Definition: AxisIp4.hpp:159
#define printWarn(callerName, format,...)
A macro to print a warning message.
Definition: nts_utils.hpp:182
#define concat3(firstCharConst, secondCharConst, thirdCharConst)
Definition: nts_utils.hpp:161
#define ETH_ETHERTYPE_IP4
Definition: nts_types.hpp:155
#define TLAST
Definition: AxisRaw.hpp:116
ap_uint< 16 > EtherType
Definition: AxisEth.hpp:122
: IP Receiver packet handler (IPRX).
ap_uint< 16 > byteSwap16(ap_uint< 16 > inputVector)
Definition: udp.cpp:82