MatchLib
nvhls_packet.h
1 /*
2  * Copyright (c) 2016-2019, 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 //========================================================================
17 // nvhls_packet.h
18 //========================================================================
19 // Packet and Flit class implementations
20 
21 #ifndef NVHLS_PACKET_H
22 #define NVHLS_PACKET_H
23 
24 #include <systemc.h>
25 #include <nvhls_types.h>
26 #include <nvhls_marshaller.h>
27 #include <nvhls_message.h>
28 
29 //------------------------------------------------------------------------
30 // Packet
31 //------------------------------------------------------------------------
32 // Packet-id acts as unique identifier for the flits of a packet.
33 // NOTE: 0 is default value. Initialize to value!=0.
34 //
35 // Dest denotes the packet destination
36 //
37 // For Source routing, Dest specifies the "route"
38 
39 enum RouterType { StoreForward, WormHole };
40 
69 template <int DataWidth, int DestWidthPerHop, int MaxHops = 1,
70  int PacketIdWidth = 0>
71 class Packet : public nvhls_message {
72  public:
73  Packet() { reset(); }
74 
75  Packet(const Packet& other) {
76  data = other.data;
77  dest = other.dest;
78  packet_id = other.packet_id;
79  }
80 
81  Packet& operator=(const Packet& other) {
82  data = other.data;
83  dest = other.dest;
84  packet_id = other.packet_id;
85  return *this;
86  }
87 
88  void reset() {
89  data = 0;
90  dest = 0;
91  packet_id = 0;
92  }
93 
94  enum {
95  data_width = DataWidth,
96  dest_width_per_hop = DestWidthPerHop,
97  dest_width = DestWidthPerHop * MaxHops,
98  packet_id_width = PacketIdWidth,
99  width = data_width + dest_width + packet_id_width,
100  data_start_bit = 0,
101  data_end_bit = data_width - 1,
102  dest_start_bit = data_end_bit + 1,
103  dest_end_bit = dest_start_bit + dest_width - 1,
104  packet_id_start_bit = dest_end_bit + 1,
105  packet_id_end_bit = packet_id_start_bit + packet_id_width - 1
106  };
107 
108  NVUINTW(data_width) data;
109  NVUINTW(dest_width) dest;
110  NVUINTW(packet_id_width) packet_id;
111 
112  template <unsigned int Size>
113  void Marshall(Marshaller<Size>& m) {
114  m& data;
115  m& dest;
116  m& packet_id;
117  }
118 };
119 
120 //-----------------------------------------------------------------------
121 // Packet (specialization without ID)
122 //-----------------------------------------------------------------------
123 template <int DataWidth, int DestWidthPerHop, int MaxHops>
124 class Packet<DataWidth, DestWidthPerHop, MaxHops, 0> : public nvhls_message {
125  public:
126  Packet() { reset(); }
127 
128  Packet(const Packet& other) {
129  data = other.data;
130  dest = other.dest;
131  }
132 
133  Packet& operator=(const Packet& other) {
134  data = other.data;
135  dest = other.dest;
136  return *this;
137  }
138 
139  void reset() {
140  data = 0;
141  dest = 0;
142  }
143 
144  enum {
145  data_width = DataWidth,
146  dest_width_per_hop = DestWidthPerHop,
147  dest_width = DestWidthPerHop * MaxHops,
148  width = data_width + dest_width,
149  data_start_bit = 0,
150  data_end_bit = data_width - 1,
151  dest_start_bit = data_end_bit + 1,
152  dest_end_bit = dest_start_bit + dest_width - 1,
153  };
154 
155  NVUINTW(data_width) data;
156  NVUINTW(dest_width) dest;
157 
158  template <unsigned int Size>
159  void Marshall(Marshaller<Size>& m) {
160  m& data;
161  m& dest;
162  }
163 };
164 
165 //------------------------------------------------------------------------
166 // Flit
167 //------------------------------------------------------------------------
168 class FlitId2bit;
169 
170 template <int DataWidth, int DestWidthPerHop, int MaxHops = 1,
171  int PacketIdWidth = 0, class FlitId = FlitId2bit,
172  RouterType Rtype = StoreForward>
173 class Flit;
174 
202 class FlitId2bit : public nvhls_message {
203  public:
204  enum { width = 2 };
205 
206  typedef enum { BODY = 0, HEAD = 1, TAIL = 2, SNGL = 3 } Encoding;
207 
208  bool isHeader() const { return (data[0] == 1); }
209  bool isBody() const { return (data == BODY); }
210  bool isTail() const { return (data[1] == 1); }
211  bool isSingle() const { return (data == SNGL); }
212 
213  void set(const Encoding& enc) { data = enc; }
214  void reset() { set(BODY); }
215 
216  bool operator==(const FlitId2bit& other) const {
217  return (data == other.data);
218  }
219  FlitId2bit& operator=(const FlitId2bit& other) {
220  data = other.data;
221  return *this;
222  }
223 
224  template <unsigned int Size>
225  void Marshall(Marshaller<Size>& m) {
226  m& data;
227  }
228 
229  // Getter and setter providing raw access to the underlying data type
230  void set_raw(const NVUINTC(width) a) { data = a; }
231  NVUINTC(width) get_raw() { return data; }
232 
233  NVUINTC(width) data;
234 
235 };
236 
237 #ifndef __SYNTHESIS__
238 // NOTE: there is no real requirement to have this function templated. The only usage I am aware of it is with T=ostream
239 // the reason this function was made templated is to avoid linker error. When multiple C files would independently include
240 // current h file, unless this is a template function it would result a conflict in linkage stage because multiple
241 // objects will have the implementation of this function. The "real" solution is to move all function bodies into C files,
242 // and if necessary libraries. The quick and dirty workaround applied here relies on the fact that template functions are
243 // required to be in h files which forces linker to resolve these kind of conflicts. So by templating this function
244 // we avoid linker conflict scenario. Potentially can move it into a library in the future if/once such is created.
245 template<class T>
246 T& operator<<(T& os, const FlitId2bit& id) {
247  os << id.data;
248  return os;
249 }
250 #endif
251 
282 template <int DataWidth, int DestWidthPerHop, int MaxHops, int PacketIdWidth,
283  class FlitId>
284 class Flit<DataWidth, DestWidthPerHop, MaxHops, PacketIdWidth, FlitId,
285  StoreForward> : public nvhls_message {
286  public:
287  Flit();
288 
289  Flit(const Flit& other);
290 
291  Flit& operator=(const Flit& other) {
292  data = other.data;
293  dest = other.dest;
294  packet_id = other.packet_id;
295  flit_id = other.flit_id;
296  return *this;
297  }
298 
299  void reset();
300 
301  enum {
302  data_width = DataWidth,
303  dest_width_per_hop = DestWidthPerHop,
304  dest_width = DestWidthPerHop * MaxHops,
305  packet_id_width = PacketIdWidth,
306  flit_id_width = FlitId::width,
307  width = data_width + dest_width + packet_id_width + flit_id_width,
308  data_start_bit = 0,
309  data_end_bit = data_width - 1,
310  dest_start_bit = data_end_bit + 1,
311  dest_end_bit = dest_start_bit + dest_width - 1,
312  packet_id_start_bit = dest_end_bit + 1,
313  packet_id_end_bit = packet_id_start_bit + packet_id_width - 1,
314  flit_id_start_bit = packet_id_end_bit + 1,
315  flit_id_end_bit = flit_id_start_bit + flit_id_width - 1
316  };
317 
318  NVUINTW(data_width) data;
319  NVUINTW(dest_width) dest;
320  NVUINTW(packet_id_width) packet_id;
321  FlitId flit_id;
322 
323  template <unsigned int Size>
324  void Marshall(Marshaller<Size>& m) {
325  m& data;
326  m& dest;
327  m& packet_id;
328  m& flit_id;
329  }
330 };
331 
332 template <int DataWidth, int DestWidthPerHop, int MaxHops, int PacketIdWidth,
333  class FlitId>
334 void Flit<DataWidth, DestWidthPerHop, MaxHops, PacketIdWidth, FlitId,
335  StoreForward>::reset() {
336  data = 0;
337  dest = 0;
338  packet_id = 0;
339  flit_id.reset();
340 }
341 
342 template <int DataWidth, int DestWidthPerHop, int MaxHops, int PacketIdWidth,
343  class FlitId>
344 Flit<DataWidth, DestWidthPerHop, MaxHops, PacketIdWidth, FlitId,
345  StoreForward>::Flit() {
346  reset();
347 }
348 
349 template <int DataWidth, int DestWidthPerHop, int MaxHops, int PacketIdWidth,
350  class FlitId>
351 Flit<DataWidth, DestWidthPerHop, MaxHops, PacketIdWidth, FlitId,
352  StoreForward>::Flit(const Flit<DataWidth, DestWidthPerHop, MaxHops,
353  PacketIdWidth, FlitId,
354  StoreForward>& other) {
355  data = other.data;
356  dest = other.dest;
357  packet_id = other.packet_id;
358  flit_id = other.flit_id;
359 }
360 
361 //------------------------------------------------------------------------
362 // WHFlit
363 //------------------------------------------------------------------------
364 // Packet-id acts as unique identifier for the flits of a packet
365 // Flits of a packet take the same route and are always ordered
366 // Flit-id is used to indicate type of payload : start, data, end
367 
368 template <int DataWidth, int PacketIdWidth, class FlitId>
369 class Flit<DataWidth, 0, 0, PacketIdWidth, FlitId, WormHole> : public nvhls_message {
370  public:
371  Flit();
372 
373  Flit(const Flit& other);
374 
375  Flit& operator=(const Flit& other) {
376  data = other.data;
377  packet_id = other.packet_id;
378  flit_id = other.flit_id;
379  return *this;
380  }
381 
382  void reset();
383 
384  enum {
385  data_width = DataWidth,
386  packet_id_width = PacketIdWidth,
387  flit_id_width = FlitId::width,
388  width = data_width + packet_id_width + flit_id_width,
389  data_start_bit = 0,
390  data_end_bit = data_width - 1,
391  packet_id_start_bit = data_end_bit + 1,
392  packet_id_end_bit = packet_id_start_bit + packet_id_width - 1,
393  flit_id_start_bit = packet_id_end_bit + 1,
394  flit_id_end_bit = flit_id_start_bit + flit_id_width - 1
395  };
396 
397  NVUINTW(data_width) data;
398  NVUINTW(packet_id_width) packet_id;
399  FlitId flit_id;
400 
401  NVUINTW(packet_id_width) get_packet_id() const {
402  return packet_id;
403  }
404 
405  template <unsigned int Size>
406  void Marshall(Marshaller<Size>& m) {
407  m& data;
408  m& packet_id;
409  m& flit_id;
410  }
411 };
412 
413 template <int DataWidth, int PacketIdWidth, class FlitId>
415  data = 0;
416  packet_id = 0;
417  flit_id.reset();
418 }
419 
420 template <int DataWidth, int PacketIdWidth, class FlitId>
422  reset();
423 }
424 
425 template <int DataWidth, int PacketIdWidth, class FlitId>
428  data = other.data;
429  packet_id = other.packet_id;
430  flit_id = other.flit_id;
431 }
432 
433 template <int DataWidth, int PacketIdWidth, class FlitId>
434 inline std::ostream& operator<<(ostream& os, const Flit<DataWidth, 0, 0, PacketIdWidth, FlitId, WormHole>& flit)
435 {
436  os << "<FlitId, PacketID, Data> <" << flit.flit_id << "," << flit.packet_id << "," << flit.data << ">";
437  return os;
438 }
439 // WHFlit specialization without packet id
440 template <int DataWidth, class FlitId>
441 class Flit<DataWidth, 0, 0, 0, FlitId, WormHole> : public nvhls_message {
442  public:
443  Flit();
444 
445  Flit(const Flit& other);
446 
447  Flit& operator=(const Flit& other) {
448  data = other.data;
449  flit_id = other.flit_id;
450  return *this;
451  }
452 
453  void reset();
454 
455  enum {
456  data_width = DataWidth,
457  flit_id_width = FlitId::width,
458  width = data_width + flit_id_width,
459  data_start_bit = 0,
460  data_end_bit = data_width - 1,
461  flit_id_start_bit = data_end_bit + 1,
462  flit_id_end_bit = flit_id_start_bit + flit_id_width - 1
463  };
464 
465  NVUINTW(data_width) data;
466  FlitId flit_id;
467 
468  int get_packet_id() const {
469  return 0;
470  }
471 
472  template <unsigned int Size>
473  void Marshall(Marshaller<Size>& m) {
474  m& data;
475  m& flit_id;
476  }
477 };
478 
479 template <int DataWidth, class FlitId>
481  data = 0;
482  flit_id.reset();
483 }
484 
485 template <int DataWidth, class FlitId>
487  reset();
488 }
489 
490 template <int DataWidth, class FlitId>
493  data = other.data;
494  flit_id = other.flit_id;
495 }
496 
497 template <int DataWidth, class FlitId>
498 inline std::ostream& operator<<(ostream& os, const Flit<DataWidth, 0, 0, 0, FlitId, WormHole>& flit)
499 {
500  os << "<FlitId, Data> <" << flit.flit_id << "," << flit.data << ">";
501  return os;
502 }
503 
504 #endif /*NVHLS_PACKET_H*/
Encoding for FlitID.
Definition: nvhls_packet.h:202
#define NVUINTC(width)
Parameterized implementation of a network packet.
Definition: nvhls_packet.h:71
#define NVUINTW(width)
Definition: nvhls_types.h:35