20 #ifndef NVHLS_CONNECTIONS_BUFFERED_PORTS_H_
21 #define NVHLS_CONNECTIONS_BUFFERED_PORTS_H_
25 #include <nvhls_assert.h>
26 #include <nvhls_marshaller.h>
27 #include <nvhls_module.h>
31 namespace Connections {
33 template <
typename Message,
int BufferSize = 1, connections_port_t port_marshall_type = AUTO_PORT>
34 class InBuffered :
public InBlocking<Message, port_marshall_type> {
38 InBuffered() : InBlocking<Message, port_marshall_type>(), fifo() {}
40 explicit InBuffered(
const char* name) : InBlocking<Message, port_marshall_type>(name), fifo() {}
43 InBlocking<Message,port_marshall_type>::Reset();
48 bool Empty() {
return fifo.isEmpty(); }
50 Message Pop() {
return fifo.pop(); }
52 void IncrHead() { fifo.incrHead(); }
54 Message Peek() {
return fifo.peek(); }
60 if (this->PopNB(dat)) {
67 template <
typename Message,
int BufferSize = 1, connections_port_t port_marshall_type = AUTO_PORT>
68 class OutBuffered :
public OutBlocking<Message, port_marshall_type> {
72 OutBuffered() : OutBlocking<Message, port_marshall_type>(), fifo() {}
74 explicit OutBuffered(
const char* name) : OutBlocking<Message, port_marshall_type>(name), fifo() {}
77 OutBlocking<Message,port_marshall_type>::Reset();
82 bool Full() {
return fifo.isFull(); }
84 bool Empty() {
return fifo.isEmpty(); }
86 AddressPlusOne NumAvailable() {
return fifo.NumAvailable(); }
88 void Push(
const Message& dat) { fifo.push(dat); }
91 if (!fifo.isEmpty()) {
92 Message dat = fifo.peek();
93 if (this->PushNB(dat)) {
105 template <
typename Message, connections_port_t port_marshall_type = AUTO_PORT>
108 template <
typename Message>
112 typedef Wrapped<Message> WMessage;
113 static const unsigned int width = WMessage::width;
114 typedef sc_lv<WMessage::width> MsgBits;
115 sc_signal<MsgBits> dat;
119 StateSignal(sc_module_name name) : dat(CONNECTIONS_CONCAT(name,
"_dat")) { }
126 template <
typename Message>
130 typedef Wrapped<Message> WMessage;
131 static const unsigned int width = WMessage::width;
132 typedef sc_lv<WMessage::width> MsgBits;
133 sc_signal<MsgBits> dat;
137 StateSignal(sc_module_name name) : dat(CONNECTIONS_CONCAT(name,
"_dat")) { }
144 template <
typename Message>
148 sc_signal<Message> dat;
152 StateSignal(sc_module_name name) : dat(CONNECTIONS_CONCAT(name,
"_dat")) { }
162 template <
typename Message>
174 template <
typename Message, connections_port_t port_marshall_type>
179 static const int kDebugLevel = 3;
183 In<Message, port_marshall_type> enq;
184 Out<Message, port_marshall_type> deq;
187 : sc_module(sc_module_name(sc_gen_unique_name(
"byp"))),
193 Bypass(sc_module_name name) : sc_module(name), clk(
"clk"), rst(
"rst") {
209 #ifdef CONNECTIONS_SIM_ONLY
218 sensitive << enq.vld << full;
221 sensitive << enq.vld << deq.rdy << full;
223 SC_METHOD(BypassMux);
224 sensitive << enq.dat << state.dat << full;
227 sensitive << clk.pos();
235 wen.write(enq.vld.read() && !deq.rdy.read() && !full.read());
239 void EnqRdy() { enq.rdy.write(!full.read()); }
243 deq.vld.write(full.read() || (!full.read() && enq.vld.read()));
249 deq.dat.write(state.dat.read());
251 deq.dat.write(enq.dat.read());
265 if (deq.rdy.read()) {
267 }
else if (enq.vld.read() && !deq.rdy.read() && !full.read()) {
273 state.dat.write(enq.dat.read());
279 #ifndef __SYNTHESIS__
283 unsigned int width = (Message().length() / 4);
285 if (enq.vld.read() && enq.rdy.read()) {
286 CDCOUT(std::hex << std::setw(width) << enq.dat.read(), kDebugLevel);
288 CDCOUT(std::setw(width + 1) <<
" ", kDebugLevel);
291 CDCOUT(
" ( " << full.read() <<
" ) ", kDebugLevel);
294 if (deq.vld.read() && deq.rdy.read()) {
295 CDCOUT(std::hex << std::setw(width) << deq.dat.read(), kDebugLevel);
297 CDCOUT(std::setw(width + 1) <<
" ", kDebugLevel);
299 CDCOUT(
" | ", kDebugLevel);
307 template <
typename Message>
319 template <
typename Message, connections_port_t port_marshall_type>
324 static const int kDebugLevel = 3;
328 In<Message, port_marshall_type> enq;
329 Out<Message, port_marshall_type> deq;
332 : sc_module(sc_module_name(sc_gen_unique_name(
"byp"))),
338 Pipeline(sc_module_name name) : sc_module(name), clk(
"clk"), rst(
"rst") {
354 #ifdef CONNECTIONS_SIM_ONLY
360 sensitive << full << deq.rdy;
366 sensitive << enq.vld << deq.rdy << full;
369 sensitive << state.dat;
372 sensitive << clk.pos();
381 wen.write(enq.vld.read() && (!full.read() || (full && deq.rdy.read())));
386 void EnqRdy() { enq.rdy.write(!full.read() || (full && deq.rdy.read())); }
389 void DeqVld() { deq.vld.write(full.read()); }
392 void DeqMsg() { deq.dat.write(state.dat.read()); }
404 if (full.read() && deq.rdy.read() && !enq.vld.read()) {
406 }
else if (enq.vld.read() &&
407 (!full.read() || (full.read() && deq.rdy.read()))) {
413 state.dat.write(enq.dat.read());
419 #ifndef __SYNTHESIS__
423 unsigned int width = (Message().length() / 4);
425 if (enq.vld.read() && enq.rdy.read()) {
426 CDCOUT(std::hex << std::setw(width) << enq.dat.read(), kDebugLevel);
428 CDCOUT(std::setw(width + 1) <<
" ", kDebugLevel);
431 CDCOUT(
" ( " << full.read() <<
" ) ", kDebugLevel);
434 if (deq.vld.read() && deq.rdy.read()) {
435 CDCOUT(std::hex << std::setw(width) << deq.dat.read(), kDebugLevel);
437 CDCOUT(std::setw(width + 1) <<
" ", kDebugLevel);
439 CDCOUT(
" | ", kDebugLevel);
447 template <
typename Message>
466 template <
typename Message,
unsigned int NumEntries, connections_port_t port_marshall_type = AUTO_PORT>
471 static const int kDebugLevel = 3;
475 In<Message, port_marshall_type> enq;
476 Out<Message, port_marshall_type> deq;
479 : sc_module(sc_module_name(sc_gen_unique_name(
"byp"))),
485 BypassBuffered(sc_module_name name) : sc_module(name), clk(
"clk"), rst(
"rst") {
491 static const int AddrWidth =
nvhls::nbits<NumEntries - 1>::val;
492 typedef NVUINTW(AddrWidth) BuffIdx;
495 sc_signal<Bit> full_next;
496 sc_signal<BuffIdx> head_next;
497 sc_signal<BuffIdx> tail_next;
501 sc_signal<BuffIdx> head;
502 sc_signal<BuffIdx> tail;
507 #ifdef CONNECTIONS_SIM_ONLY
516 sensitive << full << head << tail << enq.vld;
519 #ifndef __SYNTHESIS__
520 sensitive << deq.rdy << full << head << tail << enq.vld << enq.dat;
522 sensitive << full << head << tail << enq.dat;
526 sensitive << enq.vld << full << head << tail << deq.rdy;
529 sensitive << deq.rdy << full << head << tail;
532 sensitive << enq.vld << deq.rdy << full << head << tail;
535 sensitive << clk.pos();
545 void EnqRdy() { enq.rdy.write(!full.read()); }
549 bool empty = (!full.read() && (head.read() == tail.read()));
550 deq.vld.write(!empty || enq.vld.read());
555 bool empty = (!full.read() && (head.read() == tail.read()));
556 #ifndef __SYNTHESIS__
557 bool do_deq = !empty || enq.vld.read();
561 deq.dat.write(buffer[tail.read()].dat.read());
563 deq.dat.write(enq.dat.read());
565 #ifndef __SYNTHESIS__
574 bool empty = (!full.read() && (head.read() == tail.read()));
575 bool do_enq = (enq.vld.read() && !full.read() &&
576 !(empty && deq.rdy.read()));
578 if ((head.read() + 1) == NumEntries)
581 head_inc = head.read() + 1;
584 head_next.write(head_inc);
586 head_next.write(head.read());
591 bool empty = (!full.read() && (head.read() == tail.read()));
592 bool do_deq = (deq.rdy.read() && !empty);
594 if ((tail.read() + 1) == NumEntries)
597 tail_inc = tail.read() + 1;
600 tail_next.write(tail_inc);
602 tail_next.write(tail.read());
607 bool empty = (!full.read() && (head.read() == tail.read()));
608 bool do_enq = (enq.vld.read() && !full.read() &&
609 !(empty && deq.rdy.read()));
610 bool do_deq = (deq.rdy.read() && !empty);
613 if ((head.read() + 1) == NumEntries)
616 head_inc = head.read() + 1;
618 if (do_enq && !do_deq && (head_inc == tail.read()))
620 else if (do_deq && full.read())
623 full_next.write(full.read());
632 #pragma hls_unroll yes
633 for (
unsigned int i = 0; i < NumEntries; ++i)
634 buffer[i].dat.reset_state();
641 head.write(head_next);
644 tail.write(tail_next);
647 full.write(full_next);
650 bool empty = (!full.read() && (head.read() == tail.read()));
652 if (enq.vld.read() && !full.read() &&
653 !(empty && deq.rdy.read())) {
654 buffer[head.read()].dat.write(enq.dat.read());
661 #ifndef __SYNTHESIS__
665 unsigned int width = (Message().length() / 4);
667 if (enq.vld.read() && enq.rdy.read()) {
668 CDCOUT(std::hex << std::setw(width) << enq.dat.read(), kDebugLevel);
670 CDCOUT(std::setw(width + 1) <<
" ", kDebugLevel);
673 CDCOUT(
" ( " << full.read() <<
" ) ", kDebugLevel);
676 if (deq.vld.read() && deq.rdy.read()) {
677 CDCOUT(std::hex << std::setw(width) << deq.dat.read(), kDebugLevel);
679 CDCOUT(std::setw(width + 1) <<
" ", kDebugLevel);
681 CDCOUT(
" | ", kDebugLevel);
689 template <
typename Message,
unsigned int NumEntries>
702 template <
typename Message,
unsigned int NumEntries, connections_port_t port_marshall_type>
707 static const int kDebugLevel = 3;
711 In<Message, port_marshall_type> enq;
712 Out<Message, port_marshall_type> deq;
715 : sc_module(sc_module_name(sc_gen_unique_name(
"buffer"))),
721 Buffer(sc_module_name name) : sc_module(name), clk(
"clk"), rst(
"rst") {
728 typedef NVUINTW(AddrWidth) BuffIdx;
731 sc_signal<Bit> full_next;
732 sc_signal<BuffIdx> head_next;
733 sc_signal<BuffIdx> tail_next;
737 sc_signal<BuffIdx> head;
738 sc_signal<BuffIdx> tail;
743 #ifdef CONNECTIONS_SIM_ONLY
752 sensitive << full << head << tail;
755 #ifndef __SYNTHESIS__
756 sensitive << deq.rdy << full << head << tail;
762 sensitive << enq.vld << full << head;
765 sensitive << deq.rdy << full << head << tail;
768 sensitive << enq.vld << deq.rdy << full << head << tail;
771 sensitive << clk.pos();
781 void EnqRdy() { enq.rdy.write(!full.read()); }
785 bool empty = (!full.read() && (head.read() == tail.read()));
786 deq.vld.write(!empty);
791 #ifndef __SYNTHESIS__
792 bool empty = (!full.read() && (head.read() == tail.read()));
793 bool do_deq = !empty;
796 deq.dat.write(buffer[tail.read()].dat.read());
797 #ifndef __SYNTHESIS__
806 bool do_enq = (enq.vld.read() && !full.read());
808 if ((head.read() + 1) == NumEntries)
811 head_inc = head.read() + 1;
814 head_next.write(head_inc);
816 head_next.write(head.read());
821 bool empty = (!full.read() && (head.read() == tail.read()));
822 bool do_deq = (deq.rdy.read() && !empty);
824 if ((tail.read() + 1) == NumEntries)
827 tail_inc = tail.read() + 1;
830 tail_next.write(tail_inc);
832 tail_next.write(tail.read());
837 bool empty = (!full.read() && (head.read() == tail.read()));
838 bool do_enq = (enq.vld.read() && !full.read());
839 bool do_deq = (deq.rdy.read() && !empty);
842 if ((head.read() + 1) == NumEntries)
845 head_inc = head.read() + 1;
847 if (do_enq && !do_deq && (head_inc == tail.read()))
849 else if (do_deq && full.read())
852 full_next.write(full.read());
861 #pragma hls_unroll yes
862 for (
unsigned int i = 0; i < NumEntries; ++i)
863 buffer[i].reset_state();
869 head.write(head_next);
872 tail.write(tail_next);
875 full.write(full_next);
878 if (enq.vld.read() && !full.read()) {
879 buffer[head.read()].dat.write(enq.dat.read());
886 #ifndef __SYNTHESIS__
890 unsigned int width = (Message().length() / 4);
892 if (enq.vld.read() && enq.rdy.read()) {
893 CDCOUT(std::hex << std::setw(width) << enq.dat.read(), kDebugLevel);
895 CDCOUT(std::setw(width + 1) <<
" ", kDebugLevel);
898 CDCOUT(
" ( " << full.read() <<
" ) ", kDebugLevel);
901 if (deq.vld.read() && deq.rdy.read()) {
902 CDCOUT(std::hex << std::setw(width) << deq.dat.read(), kDebugLevel);
904 CDCOUT(std::setw(width + 1) <<
" ", kDebugLevel);
906 CDCOUT(
" | ", kDebugLevel);
914 template <
typename Message,
unsigned int NumEntries>
915 class Buffer<Message, NumEntries, TLM_PORT> :
public Buffer<Message, NumEntries, DIRECT_PORT>
926 template <
typename MessageType, connections_port_t port_marshall_type = AUTO_PORT>
927 class Sink :
public sc_module {
928 SC_HAS_PROCESS(
Sink);
933 In<MessageType, port_marshall_type> in;
936 Sink(sc_module_name nm)
942 sensitive << clk.pos();
945 static const unsigned int width = 0;
946 template <
unsigned int Size>
947 void Marshall(Marshaller<Size>& m) {
961 template <
typename C>
962 void operator()(C& rhs) {
967 template <
typename MessageType, connections_port_t port_marshall_type = AUTO_PORT>
974 In<MessageType, port_marshall_type> in;
983 sensitive << clk.pos();
986 static const unsigned int width = 0;
987 template <
unsigned int Size>
988 void Marshall(Marshaller<Size>& m) {
1002 template <
typename C>
1003 void operator()(C& rhs) {
1008 template <
typename MessageType, connections_port_t port_marshall_type = AUTO_PORT>
1015 Out<MessageType, port_marshall_type> out;
1023 SC_THREAD(DoSource);
1024 sensitive << clk.pos();
1027 static const unsigned int width = 0;
1028 template <
unsigned int Size>
1029 void Marshall(Marshaller<Size>& m) {
1043 template <
typename C>
1044 void operator()(C& rhs) {
1058 template <
typename Message,
unsigned int NumEntries = 1>
1063 Combinational<Message> enq;
1064 Combinational<Message> deq;
1068 OutBlocking<Message>& out,
1069 Combinational<Message>& chan)
1070 : enq(sc_gen_unique_name(
"bind_enq")),
1071 deq(sc_gen_unique_name(
"bind_deq")) {
1079 OutBlocking<Message>& out,
1080 Combinational<Message>& chan,
1081 sc_in_clk& clk, sc_in<bool>& rst)
1082 : enq(sc_gen_unique_name(
"bind_enq")),
1083 deq(sc_gen_unique_name(
"bind_deq")) {
1091 OutBlocking<Message>& out,
1093 sc_in_clk& clk, sc_in<bool>& rst)
1094 : enq(sc_gen_unique_name(
"bind_enq")),
1095 deq(sc_gen_unique_name(
"bind_deq")) {
1107 OutBlocking<Message>& out,
1109 sc_in_clk& clk, sc_in<bool>& rst)
1110 : enq(sc_gen_unique_name(
"bind_enq")),
1111 deq(sc_gen_unique_name(
"bind_deq")) {
1124 OutBlocking<Message>& out,
1126 sc_in_clk& clk, sc_in<bool>& rst)
1127 : enq(sc_gen_unique_name(
"bind_enq")),
1128 deq(sc_gen_unique_name(
"bind_deq")) {
1140 OutBlocking<Message>& out,
1142 sc_in_clk& clk, sc_in<bool>& rst)
1143 : enq(sc_gen_unique_name(
"bind_enq")),
1144 deq(sc_gen_unique_name(
"bind_deq")) {
#define NVHLS_NEG_RESET_SIGNAL_IS(port)
ENABLE_SYNC_RESET define: Select synchronous or asynchronous reset.
Compute index width of a constant.
Compute number of bits to represent a constant.