20 #ifndef NVHLS_CONNECTIONS_BUFFERED_PORTS_H_ 21 #define NVHLS_CONNECTIONS_BUFFERED_PORTS_H_ 24 #include <nvhls_assert.h> 25 #include <nvhls_marshaller.h> 26 #include <nvhls_module.h> 32 template <
typename Message,
int BufferSize = 1, connections_port_t port_marshall_type = AUTO_PORT>
33 class InBuffered :
public InBlocking<Message, port_marshall_type> {
37 InBuffered() : InBlocking<Message, port_marshall_type>(), fifo() {}
39 explicit InBuffered(
const char* name) : InBlocking<Message, port_marshall_type>(name), fifo() {}
42 InBlocking<Message,port_marshall_type>::Reset();
47 bool Empty() {
return fifo.isEmpty(); }
49 Message Pop() {
return fifo.pop(); }
51 void IncrHead() { fifo.incrHead(); }
53 Message Peek() {
return fifo.peek(); }
59 if (this->PopNB(msg)) {
66 template <
typename Message,
int BufferSize = 1, connections_port_t port_marshall_type = AUTO_PORT>
67 class OutBuffered :
public OutBlocking<Message, port_marshall_type> {
71 OutBuffered() : OutBlocking<Message, port_marshall_type>(), fifo() {}
73 explicit OutBuffered(
const char* name) : OutBlocking<Message, port_marshall_type>(name), fifo() {}
76 OutBlocking<Message,port_marshall_type>::Reset();
81 bool Full() {
return fifo.isFull(); }
83 bool Empty() {
return fifo.isEmpty(); }
85 AddressPlusOne NumAvailable() {
return fifo.NumAvailable(); }
87 void Push(
const Message& msg) { fifo.push(msg); }
90 if (!fifo.isEmpty()) {
91 Message msg = fifo.peek();
92 if (this->PushNB(msg)) {
104 template <
typename Message, connections_port_t port_marshall_type = AUTO_PORT>
107 template <
typename Message>
111 typedef Wrapped<Message> WMessage;
112 static const unsigned int width = WMessage::width;
113 typedef sc_lv<WMessage::width> MsgBits;
114 sc_signal<MsgBits> msg;
118 StateSignal(sc_module_name name) : msg(CONNECTIONS_CONCAT(name,
"_msg")) { }
125 template <
typename Message>
129 typedef Wrapped<Message> WMessage;
130 static const unsigned int width = WMessage::width;
131 typedef sc_lv<WMessage::width> MsgBits;
132 sc_signal<MsgBits> msg;
136 StateSignal(sc_module_name name) : msg(CONNECTIONS_CONCAT(name,
"_msg")) { }
143 template <
typename Message>
147 sc_signal<Message> msg;
151 StateSignal(sc_module_name name) : msg(CONNECTIONS_CONCAT(name,
"_msg")) { }
161 template <
typename Message>
173 template <
typename Message, connections_port_t port_marshall_type>
181 In<Message, port_marshall_type> enq;
182 Out<Message, port_marshall_type> deq;
185 : sc_module(sc_module_name(sc_gen_unique_name(
"byp"))),
191 Bypass(sc_module_name name) : sc_module(name), clk(
"clk"), rst(
"rst") {
207 #ifdef CONNECTIONS_SIM_ONLY 216 sensitive << enq.val << full;
219 sensitive << enq.val << deq.rdy << full;
221 SC_METHOD(BypassMux);
222 sensitive << enq.msg << state.msg << full;
225 sensitive << clk.pos();
233 wen.write(enq.val.read() && !deq.rdy.read() && !full.read());
237 void EnqRdy() { enq.rdy.write(!full.read()); }
241 deq.val.write(full.read() || (!full.read() && enq.val.read()));
247 deq.msg.write(state.msg.read());
249 deq.msg.write(enq.msg.read());
263 if (deq.rdy.read()) {
265 }
else if (enq.val.read() && !deq.rdy.read() && !full.read()) {
271 state.msg.write(enq.msg.read());
277 #ifndef __SYNTHESIS__ 281 unsigned int width = (Message().length() / 4);
283 if (enq.val.read() && enq.rdy.read()) {
284 std::cout << std::hex << std::setw(width) << enq.msg.read();
286 std::cout << std::setw(width + 1) <<
" ";
289 std::cout <<
" ( " << full.read() <<
" ) ";
292 if (deq.val.read() && deq.rdy.read()) {
293 std::cout << std::hex << std::setw(width) << deq.msg.read();
295 std::cout << std::setw(width + 1) <<
" ";
305 template <
typename Message>
317 template <
typename Message, connections_port_t port_marshall_type>
325 In<Message, port_marshall_type> enq;
326 Out<Message, port_marshall_type> deq;
329 : sc_module(sc_module_name(sc_gen_unique_name(
"byp"))),
335 Pipeline(sc_module_name name) : sc_module(name), clk(
"clk"), rst(
"rst") {
351 #ifdef CONNECTIONS_SIM_ONLY 357 sensitive << full << deq.rdy;
363 sensitive << enq.val << deq.rdy << full;
366 sensitive << state.msg;
369 sensitive << clk.pos();
378 wen.write(enq.val.read() && (!full.read() || (full && deq.rdy.read())));
383 void EnqRdy() { enq.rdy.write(!full.read() || (full && deq.rdy.read())); }
386 void DeqVal() { deq.val.write(full.read()); }
389 void DeqMsg() { deq.msg.write(state.msg.read()); }
401 if (full.read() && deq.rdy.read() && !enq.val.read()) {
403 }
else if (enq.val.read() &&
404 (!full.read() || (full.read() && deq.rdy.read()))) {
410 state.msg.write(enq.msg.read());
416 #ifndef __SYNTHESIS__ 420 unsigned int width = (Message().length() / 4);
422 if (enq.val.read() && enq.rdy.read()) {
423 std::cout << std::hex << std::setw(width) << enq.msg.read();
425 std::cout << std::setw(width + 1) <<
" ";
428 std::cout <<
" ( " << full.read() <<
" ) ";
431 if (deq.val.read() && deq.rdy.read()) {
432 std::cout << std::hex << std::setw(width) << deq.msg.read();
434 std::cout << std::setw(width + 1) <<
" ";
444 template <
typename Message>
463 template <
typename Message,
unsigned int NumEntries, connections_port_t port_marshall_type = AUTO_PORT>
471 In<Message, port_marshall_type> enq;
472 Out<Message, port_marshall_type> deq;
475 : sc_module(sc_module_name(sc_gen_unique_name(
"byp"))),
481 BypassBuffered(sc_module_name name) : sc_module(name), clk(
"clk"), rst(
"rst") {
487 static const int AddrWidth =
nvhls::nbits<NumEntries - 1>::val;
488 typedef NVUINTW(AddrWidth) BuffIdx;
491 sc_signal<Bit> full_next;
492 sc_signal<BuffIdx> head_next;
493 sc_signal<BuffIdx> tail_next;
497 sc_signal<BuffIdx> head;
498 sc_signal<BuffIdx> tail;
503 #ifdef CONNECTIONS_SIM_ONLY 512 sensitive << full << head << tail << enq.val;
515 #ifndef __SYNTHESIS__ 516 sensitive << deq.rdy << full << head << tail << enq.val << enq.msg;
518 sensitive << full << head << tail << enq.msg;
522 sensitive << enq.val << full << head << tail << deq.rdy;
525 sensitive << deq.rdy << full << head << tail;
528 sensitive << enq.val << deq.rdy << full << head << tail;
531 sensitive << clk.pos();
541 void EnqRdy() { enq.rdy.write(!full.read()); }
545 bool empty = (!full.read() && (head.read() == tail.read()));
546 deq.val.write(!empty || enq.val.read());
551 bool empty = (!full.read() && (head.read() == tail.read()));
552 #ifndef __SYNTHESIS__ 553 bool do_deq = !empty || enq.val.read();
557 deq.msg.write(buffer[tail.read()].msg.read());
559 deq.msg.write(enq.msg.read());
561 #ifndef __SYNTHESIS__ 570 bool empty = (!full.read() && (head.read() == tail.read()));
571 bool do_enq = (enq.val.read() && !full.read() &&
572 !(empty && deq.rdy.read()));
574 if ((head.read() + 1) == NumEntries)
577 head_inc = head.read() + 1;
580 head_next.write(head_inc);
582 head_next.write(head.read());
587 bool empty = (!full.read() && (head.read() == tail.read()));
588 bool do_deq = (deq.rdy.read() && !empty);
590 if ((tail.read() + 1) == NumEntries)
593 tail_inc = tail.read() + 1;
596 tail_next.write(tail_inc);
598 tail_next.write(tail.read());
603 bool empty = (!full.read() && (head.read() == tail.read()));
604 bool do_enq = (enq.val.read() && !full.read() &&
605 !(empty && deq.rdy.read()));
606 bool do_deq = (deq.rdy.read() && !empty);
609 if ((head.read() + 1) == NumEntries)
612 head_inc = head.read() + 1;
614 if (do_enq && !do_deq && (head_inc == tail.read()))
616 else if (do_deq && full.read())
619 full_next.write(full.read());
628 #pragma hls_unroll yes 629 for (
unsigned int i = 0; i < NumEntries; ++i)
630 buffer[i].msg.reset_state();
637 head.write(head_next);
640 tail.write(tail_next);
643 full.write(full_next);
646 bool empty = (!full.read() && (head.read() == tail.read()));
648 if (enq.val.read() && !full.read() &&
649 !(empty && deq.rdy.read())) {
650 buffer[head.read()].msg.write(enq.msg.read());
657 #ifndef __SYNTHESIS__ 661 unsigned int width = (Message().length() / 4);
663 if (enq.val.read() && enq.rdy.read()) {
664 std::cout << std::hex << std::setw(width) << enq.msg.read();
666 std::cout << std::setw(width + 1) <<
" ";
669 std::cout <<
" ( " << full.read() <<
" ) ";
672 if (deq.val.read() && deq.rdy.read()) {
673 std::cout << std::hex << std::setw(width) << deq.msg.read();
675 std::cout << std::setw(width + 1) <<
" ";
685 template <
typename Message,
unsigned int NumEntries>
698 template <
typename Message,
unsigned int NumEntries, connections_port_t port_marshall_type>
706 In<Message, port_marshall_type> enq;
707 Out<Message, port_marshall_type> deq;
710 : sc_module(sc_module_name(sc_gen_unique_name(
"buffer"))),
716 Buffer(sc_module_name name) : sc_module(name), clk(
"clk"), rst(
"rst") {
723 typedef NVUINTW(AddrWidth) BuffIdx;
726 sc_signal<Bit> full_next;
727 sc_signal<BuffIdx> head_next;
728 sc_signal<BuffIdx> tail_next;
732 sc_signal<BuffIdx> head;
733 sc_signal<BuffIdx> tail;
738 #ifdef CONNECTIONS_SIM_ONLY 747 sensitive << full << head << tail;
750 #ifndef __SYNTHESIS__ 751 sensitive << deq.rdy << full << head << tail;
757 sensitive << enq.val << full << head;
760 sensitive << deq.rdy << full << head << tail;
763 sensitive << enq.val << deq.rdy << full << head << tail;
766 sensitive << clk.pos();
776 void EnqRdy() { enq.rdy.write(!full.read()); }
780 bool empty = (!full.read() && (head.read() == tail.read()));
781 deq.val.write(!empty);
786 #ifndef __SYNTHESIS__ 787 bool empty = (!full.read() && (head.read() == tail.read()));
788 bool do_deq = !empty;
791 deq.msg.write(buffer[tail.read()].msg.read());
792 #ifndef __SYNTHESIS__ 801 bool do_enq = (enq.val.read() && !full.read());
803 if ((head.read() + 1) == NumEntries)
806 head_inc = head.read() + 1;
809 head_next.write(head_inc);
811 head_next.write(head.read());
816 bool empty = (!full.read() && (head.read() == tail.read()));
817 bool do_deq = (deq.rdy.read() && !empty);
819 if ((tail.read() + 1) == NumEntries)
822 tail_inc = tail.read() + 1;
825 tail_next.write(tail_inc);
827 tail_next.write(tail.read());
832 bool empty = (!full.read() && (head.read() == tail.read()));
833 bool do_enq = (enq.val.read() && !full.read());
834 bool do_deq = (deq.rdy.read() && !empty);
837 if ((head.read() + 1) == NumEntries)
840 head_inc = head.read() + 1;
842 if (do_enq && !do_deq && (head_inc == tail.read()))
844 else if (do_deq && full.read())
847 full_next.write(full.read());
856 #pragma hls_unroll yes 857 for (
unsigned int i = 0; i < NumEntries; ++i)
858 buffer[i].reset_state();
864 head.write(head_next);
867 tail.write(tail_next);
870 full.write(full_next);
873 if (enq.val.read() && !full.read()) {
874 buffer[head.read()].msg.write(enq.msg.read());
881 #ifndef __SYNTHESIS__ 885 unsigned int width = (Message().length() / 4);
887 if (enq.val.read() && enq.rdy.read()) {
888 std::cout << std::hex << std::setw(width) << enq.msg.read();
890 std::cout << std::setw(width + 1) <<
" ";
893 std::cout <<
" ( " << full.read() <<
" ) ";
896 if (deq.val.read() && deq.rdy.read()) {
897 std::cout << std::hex << std::setw(width) << deq.msg.read();
899 std::cout << std::setw(width + 1) <<
" ";
909 template <
typename Message,
unsigned int NumEntries>
910 class Buffer<Message, NumEntries, TLM_PORT> :
public Buffer<Message, NumEntries, DIRECT_PORT>
921 template <
typename MessageType, connections_port_t port_marshall_type = AUTO_PORT>
922 class Sink :
public sc_module {
923 SC_HAS_PROCESS(
Sink);
928 In<MessageType, port_marshall_type> in;
931 Sink(sc_module_name nm)
937 sensitive << clk.pos();
940 static const unsigned int width = 0;
941 template <
unsigned int Size>
942 void Marshall(Marshaller<Size>& m) {
956 template <
typename C>
957 void operator()(C& rhs) {
962 template <
typename MessageType, connections_port_t port_marshall_type = AUTO_PORT>
969 In<MessageType, port_marshall_type> in;
978 sensitive << clk.pos();
981 static const unsigned int width = 0;
982 template <
unsigned int Size>
983 void Marshall(Marshaller<Size>& m) {
997 template <
typename C>
998 void operator()(C& rhs) {
1003 template <
typename MessageType, connections_port_t port_marshall_type = AUTO_PORT>
1010 Out<MessageType, port_marshall_type> out;
1018 SC_THREAD(DoSource);
1019 sensitive << clk.pos();
1022 static const unsigned int width = 0;
1023 template <
unsigned int Size>
1024 void Marshall(Marshaller<Size>& m) {
1038 template <
typename C>
1039 void operator()(C& rhs) {
1053 template <
typename Message,
unsigned int NumEntries = 1>
1058 Combinational<Message> enq;
1059 Combinational<Message> deq;
1063 OutBlocking<Message>& out,
1064 Combinational<Message>& chan)
1065 : enq(sc_gen_unique_name(
"bind_enq")),
1066 deq(sc_gen_unique_name(
"bind_deq")) {
1074 OutBlocking<Message>& out,
1075 Combinational<Message>& chan,
1076 sc_in_clk& clk, sc_in<bool>& rst)
1077 : enq(sc_gen_unique_name(
"bind_enq")),
1078 deq(sc_gen_unique_name(
"bind_deq")) {
1086 OutBlocking<Message>& out,
1088 sc_in_clk& clk, sc_in<bool>& rst)
1089 : enq(sc_gen_unique_name(
"bind_enq")),
1090 deq(sc_gen_unique_name(
"bind_deq")) {
1102 OutBlocking<Message>& out,
1104 sc_in_clk& clk, sc_in<bool>& rst)
1105 : enq(sc_gen_unique_name(
"bind_enq")),
1106 deq(sc_gen_unique_name(
"bind_deq")) {
1119 OutBlocking<Message>& out,
1121 sc_in_clk& clk, sc_in<bool>& rst)
1122 : enq(sc_gen_unique_name(
"bind_enq")),
1123 deq(sc_gen_unique_name(
"bind_deq")) {
1135 OutBlocking<Message>& out,
1137 sc_in_clk& clk, sc_in<bool>& rst)
1138 : enq(sc_gen_unique_name(
"bind_enq")),
1139 deq(sc_gen_unique_name(
"bind_deq")) {
1155 #endif // NVHLS_CONNECTIONS_BUFFERED_PORTS_H_
NVUINTW(Wrapped< T >::width) TypeToNVUINT(T in)
Convert Type to NVUINT.
Compute index width of a constant.
Compute number of bits to represent a constant.
#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's reset_signal_is() and async_reset_signal_is() so that ENABLE_SYNC_RESET can select type.