MatchLib
All Classes Namespaces Files Functions Modules Pages
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
27namespace Connections {
28
29//------------------------------------------------------------------------
30// InNetwork
31//------------------------------------------------------------------------
32
33template <typename Message, unsigned int DestWidthPerHop, unsigned int MaxHops,
34 unsigned int PacketIdWidth>
35class 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;
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
126template <typename Message, unsigned int DestWidthPerHop, unsigned int MaxHops,
127 unsigned int PacketIdWidth>
128class 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
258template <typename Message, unsigned int DestWidthPerHop, unsigned int MaxHops,
259 unsigned int PacketIdWidth, unsigned int CreditWidth>
260class 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
465template <typename Message, unsigned int DestWidthPerHop, unsigned int MaxHops,
466 unsigned int PacketIdWidth, unsigned int CreditWidth>
467class 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.
#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.