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