MatchLib
nvhls_connections_network.h
1 /*
2  * Copyright (c) 2016-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 //========================================================================
17 // nvhls_connections.h
18 //========================================================================
19 
20 #ifndef NVHLS_CONNECTIONS_NETWORK_H_
21 #define NVHLS_CONNECTIONS_NETWORK_H_
22 
23 #include <systemc.h>
24 #include <nvhls_connections.h>
25 #include <nvhls_packet.h>
26 
27 namespace Connections {
28 
29 //------------------------------------------------------------------------
30 // InNetwork
31 //------------------------------------------------------------------------
32 
33 template <typename Message, unsigned int DestWidthPerHop, unsigned int MaxHops,
34  unsigned int PacketIdWidth>
35 class InNetwork : public sc_module {
36  SC_HAS_PROCESS(InNetwork);
37 
38  public:
39  static const int kDebugLevel = 3;
40  typedef Wrapped<Message> WMessage;
41  static const unsigned int width = WMessage::width;
42  typedef sc_lv<WMessage::width> MsgBits;
44  Packet_t;
45 
46  // Interface
47  sc_in_clk clk;
48  sc_in<bool> rst;
49  In<Packet_t> enq;
50  Out<Message> deq;
51 
52  InNetwork()
53  : sc_module(sc_module_name(sc_gen_unique_name("in_network"))),
54  clk("clk"),
55  rst("rst") {
56  Init();
57  }
58 
59  InNetwork(sc_module_name name) : sc_module(name), clk("clk"), rst("rst") {
60  Init();
61  }
62 
63  protected:
64  void Init() {
65 #ifdef CONNECTIONS_SIM_ONLY
66  enq.disable_spawn();
67  deq.disable_spawn();
68 #endif
69 
70  SC_METHOD(AssignMsg);
71  sensitive << enq._DATNAME_ << rst;
72 
73  SC_METHOD(AssignVal);
74  sensitive << enq._VLDNAME_;
75 
76  SC_METHOD(AssignRdy);
77  sensitive << deq._RDYNAME_;
78  }
79 
80  void AssignMsg() {
81  if (!rst.read()) {
82  deq._DATNAME_.write(0);
83  } else if (enq._VLDNAME_.read()) {
84  sc_lv<Wrapped<Packet_t>::width> pbits = enq._DATNAME_.read();
85  Marshaller<Wrapped<Packet_t>::width> pmarshaller(pbits);
86  Packet_t packet;
87  packet.Marshall(pmarshaller);
88  MsgBits mbits(packet.data);
89  deq._DATNAME_.write(mbits);
90  }
91  }
92 
93  void AssignVal() { deq._VLDNAME_.write(enq._VLDNAME_.read()); }
94  void AssignRdy() { enq._RDYNAME_.write(deq._RDYNAME_.read()); }
95 
96 #ifndef __SYNTHESIS__
97  public:
98  void line_trace() {
99  if (rst.read()) {
100  unsigned int pwidth = (Packet_t::width / 4);
101  // Enqueue port
102  if (enq._VLDNAME_.read() && enq._RDYNAME_.read()) {
103  CDCOUT(std::hex << std::setw(pwidth) << enq._DATNAME_.read(), kDebugLevel);
104  } else {
105  CDCOUT(std::setw(pwidth + 1) << " ", kDebugLevel);
106  }
107  CDCOUT(" | ", kDebugLevel);
108 
109  // Dequeue port
110  unsigned int mwidth = (Message().length() / 4);
111  if (deq._VLDNAME_.read() && deq._RDYNAME_.read()) {
112  CDCOUT(std::hex << std::setw(mwidth) << deq._DATNAME_.read(), kDebugLevel);
113  } else {
114  CDCOUT(std::setw(mwidth + 1) << " ", kDebugLevel);
115  }
116  CDCOUT(" | ", kDebugLevel);
117  }
118  }
119 #endif
120 };
121 
122 //------------------------------------------------------------------------
123 // OutNetwork
124 //------------------------------------------------------------------------
125 
126 template <typename Message, unsigned int DestWidthPerHop, unsigned int MaxHops,
127  unsigned int PacketIdWidth>
128 class OutNetwork : public sc_module {
129  SC_HAS_PROCESS(OutNetwork);
130 
131  public:
132  static const int kDebugLevel = 3;
133  typedef Wrapped<Message> WMessage;
134  static const unsigned int width = WMessage::width;
135  typedef sc_lv<WMessage::width> MsgBits;
137  Packet_t;
138 
139  // Interface
140  sc_in_clk clk;
141  sc_in<bool> rst;
142  In<Message> enq;
143  Out<Packet_t> deq;
144  In<sc_lv<DestWidthPerHop * MaxHops> > route;
145  In<sc_lv<PacketIdWidth> > id;
146 
147  // Internal State
148  sc_signal<sc_lv<DestWidthPerHop * MaxHops> > route_state;
149  sc_signal<sc_lv<PacketIdWidth> > id_state;
150 
151  OutNetwork()
152  : sc_module(sc_module_name(sc_gen_unique_name("out_network"))),
153  clk("clk"),
154  rst("rst") {
155  Init();
156  }
157 
158  OutNetwork(sc_module_name name) : sc_module(name), clk("clk"), rst("rst") {
159  Init();
160  }
161 
162  protected:
163  void Init() {
164 #ifdef CONNECTIONS_SIM_ONLY
165  enq.disable_spawn();
166  deq.disable_spawn();
167  route.disable_spawn();
168  id.disable_spawn();
169 #endif
170 
171  SC_METHOD(AssignMsg);
172  sensitive << enq._DATNAME_ << id_state << route_state << rst;
173 
174  SC_METHOD(AssignVal);
175  sensitive << enq._VLDNAME_;
176 
177  SC_METHOD(AssignRdy);
178  sensitive << deq._RDYNAME_;
179 
180  SC_METHOD(TieToHigh);
181  sensitive << clk.pos();
182 
183  SC_THREAD(SetState);
184  sensitive << clk.pos();
186  }
187 
188  void AssignMsg() {
189  if (!rst.read()) {
190  deq._DATNAME_.write(0);
191  } else if (enq._VLDNAME_.read()) {
192  Packet_t packet;
193  vector_to_type(id_state.read(), false, &packet.packet_id);
194  vector_to_type(route_state.read(), false, &packet.dest);
195  vector_to_type(enq._DATNAME_.read(), false, &packet.data);
196  Marshaller<Wrapped<Packet_t>::width> pmarshaller;
197  packet.Marshall(pmarshaller);
198  deq._DATNAME_.write(pmarshaller.GetResult());
199  }
200  }
201 
202  void AssignVal() { deq._VLDNAME_.write(enq._VLDNAME_.read()); }
203  void AssignRdy() { enq._RDYNAME_.write(deq._RDYNAME_.read()); }
204 
205  void TieToHigh() {
206  route._RDYNAME_.write(1);
207  id._RDYNAME_.write(1);
208  }
209 
210  void SetState() {
211  id_state.write(0);
212  route_state.write(0);
213  wait();
214  while (1) {
215  if (route._VLDNAME_.read()) {
216  route_state.write(route._DATNAME_.read());
217  }
218 
219  if (id._VLDNAME_.read()) {
220  id_state.write(id._DATNAME_.read());
221  }
222  wait();
223  }
224  }
225 
226 #ifndef __SYNTHESIS__
227  public:
228  void line_trace() {
229  if (rst.read()) {
230  unsigned int mwidth = (Message().length() / 4);
231  // Enqueue port
232  if (enq._VLDNAME_.read() && enq._RDYNAME_.read()) {
233  CDCOUT(std::hex << std::setw(mwidth) << enq._DATNAME_.read(), kDebugLevel);
234  } else {
235  CDCOUT(std::setw(mwidth + 1) << " ", kDebugLevel);
236  }
237  CDCOUT(" | ", kDebugLevel);
238 
239  // Dequeue port
240  unsigned int pwidth = (Packet_t::width / 4);
241  if (deq._VLDNAME_.read() && deq._RDYNAME_.read()) {
242  CDCOUT(std::hex << std::setw(pwidth) << deq._DATNAME_.read(), kDebugLevel);
243  } else {
244  CDCOUT(std::setw(pwidth + 1) << " ", kDebugLevel);
245  }
246  CDCOUT(" | ", kDebugLevel);
247  }
248  }
249 #endif
250 };
251 
252 //------------------------------------------------------------------------
253 // InNetworkCredit
254 //------------------------------------------------------------------------
255 // NOTE: Currently, the PacketIdWidth, DestWidthPerHop, MaxHops parameters
256 // are assumed to be the same for a packet and a credit_packet
257 
258 template <typename Message, unsigned int DestWidthPerHop, unsigned int MaxHops,
259  unsigned int PacketIdWidth, unsigned int CreditWidth>
260 class InNetworkCredit : public sc_module {
261  SC_HAS_PROCESS(InNetworkCredit);
262 
263  public:
264  static const int kDebugLevel = 3;
265  typedef Wrapped<Message> WMessage;
266  static const unsigned int width = WMessage::width;
267  typedef sc_lv<WMessage::width> MsgBits;
269  Packet_t;
272  typedef sc_lv<CreditWidth> Credit_t;
273 
274  // Interface
275  sc_in_clk clk;
276  sc_in<bool> rst;
277  In<Packet_t> enq;
278  Out<Message> deq;
279  Out<CreditPacket_t> credit;
280  In<Credit_t> init_credits;
281  In<sc_lv<DestWidthPerHop * MaxHops> > credit_route;
282  In<sc_lv<PacketIdWidth> > credit_id;
283 
284  // Sub Module
286 
287  // Wire
288  Combinational<Credit_t> credit_enq;
289 
290  // Internal State
291  sc_signal<Credit_t> credits;
292  sc_signal<Credit_t> credits_next;
293 
295  : sc_module(sc_module_name(sc_gen_unique_name("in_nw_credit"))),
296  clk("clk"),
297  rst("rst"),
298  credit_out("credit_out") {
299  Init();
300  }
301 
302  InNetworkCredit(sc_module_name name)
303  : sc_module(name), clk("clk"), rst("rst"), credit_out("credit_out") {
304  Init();
305  }
306 
307  protected:
308  void Init() {
309 #ifdef CONNECTIONS_SIM_ONLY
310  enq.disable_spawn();
311  deq.disable_spawn();
312  credit.disable_spawn();
313  init_credits.disable_spawn();
314  credit_route.disable_spawn();
315  credit_id.disable_spawn();
316 #endif
317 
318  credit_out.clk(clk);
319  credit_out.rst(rst);
320  credit_out.route(credit_route);
321  credit_out.id(credit_id);
322  credit_out.enq(credit_enq);
323  credit_out.deq(credit);
324 
325  SC_METHOD(AssignMsg);
326  sensitive << enq._DATNAME_ << rst;
327 
328  SC_METHOD(AssignVal);
329  sensitive << enq._VLDNAME_;
330 
331  SC_METHOD(AssignRdy);
332  sensitive << deq._RDYNAME_;
333 
334  SC_METHOD(TieToHigh);
335  sensitive << clk.pos();
336 
337  SC_METHOD(AssignNextCredits);
338  sensitive << deq._VLDNAME_ << deq._RDYNAME_ << credit_enq._VLDNAME_ << credit_enq._RDYNAME_
339  << credits;
340 
341  SC_METHOD(AssignCreditMsg);
342  sensitive << deq._VLDNAME_ << deq._RDYNAME_ << credit_enq._VLDNAME_ << credit_enq._RDYNAME_
343  << credits;
344 
345  SC_METHOD(AssignCreditVal);
346  sensitive << deq._VLDNAME_ << deq._RDYNAME_ << credits;
347 
348  SC_THREAD(UpdateCredit);
349  sensitive << clk.pos();
351  }
352 
353  void AssignMsg() {
354  if (!rst.read()) {
355  deq._DATNAME_.write(0);
356  } else if (enq._VLDNAME_.read()) {
357  sc_lv<Wrapped<Packet_t>::width> pbits = enq._DATNAME_.read();
358  Marshaller<Wrapped<Packet_t>::width> pmarshaller(pbits);
359  Packet_t packet;
360  packet.Marshall(pmarshaller);
361  MsgBits mbits(packet.data);
362  deq._DATNAME_.write(mbits);
363  }
364  }
365 
366  void AssignVal() { deq._VLDNAME_.write(enq._VLDNAME_.read()); }
367  void AssignRdy() { enq._RDYNAME_.write(deq._RDYNAME_.read()); }
368 
369  void TieToHigh() { init_credits._RDYNAME_.write(1); }
370 
371  void AssignNextCredits() {
372  bool do_deq = deq._VLDNAME_.read() && deq._RDYNAME_.read();
373  bool do_credit = credit_enq._VLDNAME_.read() && credit_enq._RDYNAME_.read();
374  if (do_credit && !do_deq && (credits.read() != 0)) {
375  credits_next.write(0);
376  } else if (do_credit && do_deq) {
377  credits_next.write(0);
378  } else if (!do_credit && do_deq) {
379  credits_next.write(credits.read().to_uint() + 1);
380  } else {
381  credits_next.write(credits.read());
382  }
383  }
384 
385  void AssignCreditMsg() {
386  bool do_deq = deq._VLDNAME_.read() && deq._RDYNAME_.read();
387  bool do_credit = credit_enq._VLDNAME_.read() && credit_enq._RDYNAME_.read();
388  if (do_deq && do_credit && (credits.read() == 0)) {
389  credit_enq._DATNAME_.write(1);
390  } else if (do_deq && do_credit && (credits.read() != 0)) {
391  credit_enq._DATNAME_.write(credits.read().to_uint() + 1);
392  } else if (!do_deq && do_credit && (credits.read() != 0)) {
393  credit_enq._DATNAME_.write(credits.read());
394  } else {
395  credit_enq._DATNAME_.write(0);
396  }
397  }
398 
399  void AssignCreditVal() {
400  bool do_deq = deq._VLDNAME_.read() && deq._RDYNAME_.read();
401  if (do_deq || (credits.read() != 0)) {
402  credit_enq._VLDNAME_.write(1);
403  } else {
404  credit_enq._VLDNAME_.write(0);
405  }
406  }
407 
408  void UpdateCredit() {
409  credits.write(0);
410  wait();
411  while (1) {
412  if (init_credits._VLDNAME_.read()) {
413  credits.write(init_credits._DATNAME_.read());
414  } else {
415  credits.write(credits_next.read());
416  }
417  wait();
418  }
419  }
420 
421 #ifndef __SYNTHESIS__
422  public:
423  void line_trace() {
424  if (rst.read()) {
425  unsigned int pwidth = (Packet_t::width / 4);
426  // Enqueue port
427  if (enq._VLDNAME_.read() && enq._RDYNAME_.read()) {
428  CDCOUT(std::hex << std::setw(pwidth) << enq._DATNAME_.read(), kDebugLevel);
429  } else {
430  CDCOUT(std::setw(pwidth + 1) << " ", kDebugLevel);
431  }
432  CDCOUT(" | ", kDebugLevel);
433 
434  // Dequeue port
435  unsigned int mwidth = (Message().length() / 4);
436  if (deq._VLDNAME_.read() && deq._RDYNAME_.read()) {
437  CDCOUT(std::hex << std::setw(mwidth) << deq._DATNAME_.read(), kDebugLevel);
438  } else {
439  CDCOUT(std::setw(mwidth + 1) << " ", kDebugLevel);
440  }
441  CDCOUT(" | ", kDebugLevel);
442 
443  // Pending credits
444  CDCOUT(std::hex << " ( " << credits.read() << " ) ", kDebugLevel);
445 
446  // Credit
447  unsigned int cwidth = (CreditPacket_t::width / 4);
448  if (credit._VLDNAME_.read() && credit._RDYNAME_.read()) {
449  CDCOUT(std::hex << std::setw(cwidth) << credit._DATNAME_.read(), kDebugLevel);
450  } else {
451  CDCOUT(std::setw(cwidth + 1) << " ", kDebugLevel);
452  }
453  CDCOUT(" | ", kDebugLevel);
454  }
455  }
456 #endif
457 };
458 
459 //------------------------------------------------------------------------
460 // OutNetworkCredit
461 //------------------------------------------------------------------------
462 // NOTE: Currently, the PacketIdWidth, DestWidthPerHop, MaxHops parameters
463 // are assumed to be the same for a packet and a credit_packet
464 
465 template <typename Message, unsigned int DestWidthPerHop, unsigned int MaxHops,
466  unsigned int PacketIdWidth, unsigned int CreditWidth>
467 class OutNetworkCredit : public sc_module {
468  SC_HAS_PROCESS(OutNetworkCredit);
469 
470  public:
471  static const int kDebugLevel = 3;
472  typedef Wrapped<Message> WMessage;
473  static const unsigned int width = WMessage::width;
474  typedef sc_lv<WMessage::width> MsgBits;
476  Packet_t;
479  typedef sc_lv<CreditWidth> Credit_t;
480 
481  // Interface
482  sc_in_clk clk;
483  sc_in<bool> rst;
484  In<Message> enq;
485  Out<Packet_t> deq;
486  In<CreditPacket_t> credit;
487  In<sc_lv<DestWidthPerHop * MaxHops> > route;
488  In<sc_lv<PacketIdWidth> > id;
489 
490  // Sub Module
492 
493  // Wire
494  Combinational<Credit_t> credit_deq;
495 
496  // Internal State
497  sc_signal<sc_lv<DestWidthPerHop * MaxHops> > route_state;
498  sc_signal<sc_lv<PacketIdWidth> > id_state;
499  sc_signal<Credit_t> credits;
500  sc_signal<Credit_t> credits_next;
501 
503  : sc_module(sc_module_name(sc_gen_unique_name("out_nw_credit"))),
504  clk("clk"),
505  rst("rst"),
506  credit_in("credit_in") {
507  Init();
508  }
509 
510  OutNetworkCredit(sc_module_name name)
511  : sc_module(name), clk("clk"), rst("rst"), credit_in("credit_in") {
512  Init();
513  }
514 
515  protected:
516  void Init() {
517 #ifdef CONNECTIONS_SIM_ONLY
518  enq.disable_spawn();
519  deq.disable_spawn();
520  credit.disable_spawn();
521  route.disable_spawn();
522  id.disable_spawn();
523 #endif
524 
525  credit_in.clk(clk);
526  credit_in.rst(rst);
527  credit_in.enq(credit);
528  credit_in.deq(credit_deq);
529 
530  SC_METHOD(AssignMsg);
531  sensitive << enq._DATNAME_ << id_state << route_state << rst;
532 
533  SC_METHOD(AssignVal);
534  sensitive << enq._VLDNAME_ << credits << credit_deq._VLDNAME_ << credit_deq._RDYNAME_;
535 
536  SC_METHOD(AssignRdy);
537  sensitive << deq._RDYNAME_;
538 
539  SC_METHOD(TieToHigh);
540  sensitive << clk.pos();
541 
542  SC_METHOD(AssignNextCredits);
543  sensitive << deq._VLDNAME_ << deq._RDYNAME_ << credit_deq._VLDNAME_ << credit_deq._RDYNAME_
544  << credits;
545 
546  SC_METHOD(AssignCreditRdy);
547  sensitive << deq._VLDNAME_ << deq._RDYNAME_ << credits;
548 
549  SC_THREAD(UpdateCredit);
550  sensitive << clk.pos();
552 
553  SC_THREAD(SetState);
554  sensitive << clk.pos();
556  }
557 
558  void AssignMsg() {
559  if (!rst.read()) {
560  deq._DATNAME_.write(0);
561  } else if (enq._VLDNAME_.read()) {
562  Packet_t packet;
563  vector_to_type(id_state.read(), false, &packet.packet_id);
564  vector_to_type(route_state.read(), false, &packet.dest);
565  vector_to_type(enq._DATNAME_.read(), false, &packet.data);
566  Marshaller<Wrapped<Packet_t>::width> pmarshaller;
567  packet.Marshall(pmarshaller);
568  deq._DATNAME_.write(pmarshaller.GetResult());
569  }
570  }
571 
572  void AssignVal() {
573  bool do_credit = credit_deq._VLDNAME_.read() && credit_deq._RDYNAME_.read();
574  if (enq._VLDNAME_.read() && (credits.read() != 0)) {
575  deq._VLDNAME_.write(1);
576  } else if (enq._VLDNAME_.read() && (credits.read() == 0) && do_credit) {
577  deq._VLDNAME_.write(1);
578  } else {
579  deq._VLDNAME_.write(0);
580  }
581  }
582 
583  void AssignRdy() { enq._RDYNAME_.write(deq._RDYNAME_.read()); }
584 
585  void TieToHigh() {
586  route._RDYNAME_.write(1);
587  id._RDYNAME_.write(1);
588  }
589 
590  void AssignNextCredits() {
591  bool do_deq = deq._VLDNAME_.read() && deq._RDYNAME_.read();
592  bool do_credit = credit_deq._VLDNAME_.read() && credit_deq._RDYNAME_.read();
593  if (!do_credit && do_deq) {
594  credits_next.write(credits.read().to_uint() - 1);
595  } else if (do_credit && !do_deq) {
596  credits_next.write(credits.read().to_uint() +
597  credit._DATNAME_.read().to_uint());
598  } else if (do_credit && do_deq) {
599  credits_next.write(credits.read().to_uint() +
600  credit._DATNAME_.read().to_uint() - 1);
601  } else {
602  credits_next.write(credits.read());
603  }
604  }
605 
606  void AssignCreditRdy() { credit_deq._RDYNAME_.write(1); }
607 
608  void UpdateCredit() {
609  credits.write(0);
610  wait();
611  while (1) {
612  credits.write(credits_next.read());
613  wait();
614  }
615  }
616 
617  void SetState() {
618  id_state.write(0);
619  route_state.write(0);
620  wait();
621  while (1) {
622  if (route._VLDNAME_.read()) {
623  route_state.write(route._DATNAME_.read());
624  }
625 
626  if (id._VLDNAME_.read()) {
627  id_state.write(id._DATNAME_.read());
628  }
629  wait();
630  }
631  }
632 
633 #ifndef __SYNTHESIS__
634  public:
635  void line_trace() {
636  if (rst.read()) {
637  unsigned int mwidth = (Message().length() / 4);
638  // Enqueue port
639  if (enq._VLDNAME_.read() && enq._RDYNAME_.read()) {
640  CDCOUT(std::hex << std::setw(mwidth) << enq._DATNAME_.read(), kDebugLevel);
641  } else {
642  CDCOUT(std::setw(mwidth + 1) << " ", kDebugLevel);
643  }
644  CDCOUT(" | ", kDebugLevel);
645 
646  // Dequeue port
647  unsigned int pwidth = (Packet_t::width / 4);
648  if (deq._VLDNAME_.read() && deq._RDYNAME_.read()) {
649  CDCOUT(std::hex << std::setw(pwidth) << deq._DATNAME_.read(), kDebugLevel);
650  } else {
651  CDCOUT(std::setw(pwidth + 1) << " ", kDebugLevel);
652  }
653  CDCOUT(" | ", kDebugLevel);
654 
655  // Pending credits
656  CDCOUT(std::hex << " ( " << credits.read() << " ) ", kDebugLevel);
657 
658  // Credit
659  unsigned int cwidth = (CreditPacket_t::width / 4);
660  if (credit._VLDNAME_.read() && credit._RDYNAME_.read()) {
661  CDCOUT(std::hex << std::setw(cwidth) << credit._DATNAME_.read(), kDebugLevel);
662  } else {
663  CDCOUT(std::setw(cwidth + 1) << " ", kDebugLevel);
664  }
665  CDCOUT(" | ", kDebugLevel);
666  }
667  }
668 #endif
669 };
670 
671 } // namespace Connections
672 
673 #endif // NVHLS_CONNECTIONS_NETWORK_H_
Parameterized implementation of a network packet.
Definition: nvhls_packet.h:71
#define CDCOUT(x, y)
Definition: hls_globals.h:73
#define NVHLS_NEG_RESET_SIGNAL_IS(port)
ENABLE_SYNC_RESET define: Select synchronous or asynchronous reset.
Definition: nvhls_module.h:39