MatchLib
All Classes Namespaces Files Functions Modules Pages
AxiSubordinateToMem.h
1/*
2 * Copyright (c) 2016-2024, 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#ifndef __AXISUBORDINATETOMEM_H__
18#define __AXISUBORDINATETOMEM_H__
19
20#include <systemc.h>
21#include <ac_reset_signal_is.h>
22#include <hls_globals.h>
23#include <axi/axi4.h>
24#include <mem_array.h>
25#include <fifo.h>
26
56template <typename axiCfg, int capacity, int fifoDepth = 8>
57class AxiSubordinateToMem : public sc_module {
58 private:
59 static const int capacity_in_bytes = capacity;
60 static const int banks = 1;
61
62 typedef NVUINTW(axiCfg::dataWidth) Data;
64
65 Memarray memarray;
66
67 public:
68 static const int kDebugLevel = 2;
69
70 typedef typename axi::axi4<axiCfg> axi4_;
71 static const int bytesPerWord = axiCfg::dataWidth >> 3;
72
73 typename axi4_::read::template subordinate<> if_rd;
74 typename axi4_::write::template subordinate<> if_wr;
75
76 sc_in<bool> reset_bar;
77 sc_in<bool> clk;
78
83
84 SC_CTOR(AxiSubordinateToMem)
85 : if_rd("if_rd"), if_wr("if_wr"), reset_bar("reset_bar"), clk("clk") {
86 SC_THREAD(run);
87 sensitive << clk.pos();
88 async_reset_signal_is(reset_bar, false);
89 }
90
91 protected:
92 void run() {
93 if_rd.reset();
94 if_wr.reset();
95
96 rd_resp.reset();
97 rd_addr.reset();
98 wr_resp.reset();
99 wr_addr.reset();
100
101 sc_uint<axi4_::ALEN_WIDTH> rd_beat_cnt = 0;
102 sc_uint<axi4_::ALEN_WIDTH> wr_beat_cnt = 0;
103
104 #pragma hls_pipeline_init_interval 2
105 #pragma pipeline_stall_mode flush
106 while (1) {
107 wait();
108
109 bool rd_resp_full = rd_resp.isFull();
110
111 if (!rd_resp.isEmpty()) {
112 typename axi4_::ReadPayload data_pld;
113 data_pld = rd_resp.peek();
114 if (if_rd.nb_rwrite(data_pld)) {
115 rd_resp.incrHead();
116 }
117 }
118
119 if (!rd_resp_full && !rd_addr.isEmpty()) {
120 typename axi4_::AddrPayload rd_addr_pld;
121 rd_addr_pld = rd_addr.peek();
122
123 CDCOUT(sc_time_stamp() << " " << name() << " Received read request: "
124 << rd_addr_pld
125 << endl, kDebugLevel);
126
127 typename axi4_::ReadPayload data_pld;
128 data_pld.data = memarray.read(rd_addr_pld.addr + bytesPerWord*rd_beat_cnt);
129 data_pld.resp = axi4_::Enc::XRESP::OKAY;
130 data_pld.id = rd_addr_pld.id;
131
132 auto rd_beat_cnt_local = rd_beat_cnt;
133
134 if (rd_beat_cnt_local == rd_addr_pld.len) {
135 rd_beat_cnt_local = 0;
136 rd_addr.incrHead();
137 data_pld.last = 1;
138 } else {
139 data_pld.last = 0;
140 ++rd_beat_cnt_local;
141 }
142
143 rd_beat_cnt = rd_beat_cnt_local;
144 rd_resp.push(data_pld);
145 }
146
147 if (!rd_addr.isFull()) {
148 typename axi4_::AddrPayload rd_addr_pld;
149 if (if_rd.nb_aread(rd_addr_pld)) {
150 rd_addr.push(rd_addr_pld);
151 }
152 }
153
154 bool wr_resp_full = wr_resp.isFull();
155 bool wr_addr_full = wr_addr.isFull();
156
157 if (!wr_resp.isEmpty()) {
158 typename axi4_::WRespPayload resp_pld;
159 resp_pld = wr_resp.peek();
160 if (if_wr.nb_bwrite(resp_pld)) {
161 wr_resp.incrHead();
162 }
163 }
164
165 if (!wr_resp_full && !wr_addr.isEmpty()) {
166 typename axi4_::AddrPayload wr_addr_pld;
167 wr_addr_pld = wr_addr.peek();
168
169 typename axi4_::WritePayload write_pld;
170
171 if (if_wr.w.PopNB(write_pld)) {
172 auto wr_beat_cnt_local = wr_beat_cnt;
173 memarray.write(static_cast<typename Memarray::LocalIndex>(static_cast<sc_uint<axi4_::ADDR_WIDTH> >
174 (wr_addr_pld.addr) + bytesPerWord*wr_beat_cnt_local), 0, write_pld.data);
175 CDCOUT(sc_time_stamp() << " " << name() << " Received write request:"
176 << " addr=[" << wr_addr_pld << "]"
177 << " data=[" << write_pld << "]"
178 << " beat=" << dec << wr_beat_cnt_local
179 << endl, kDebugLevel);
180
181 if (wr_beat_cnt_local == wr_addr_pld.len) {
182 wr_beat_cnt_local = 0;
183 NVHLS_ASSERT_MSG(write_pld.last == true, "WRLEN indicates that this should be the last beat, but WRLAST is not set");
184 wr_addr.incrHead();
185
186 // push resp
187 typename axi4_::WRespPayload resp_pld;
188 resp_pld.resp = axi4_::Enc::XRESP::OKAY;
189 resp_pld.id = wr_addr_pld.id;
190 wr_resp.push(resp_pld);
191 } else {
192 NVHLS_ASSERT_MSG(write_pld.last == false, "WRLEN indicates that this should not be the last beat, but WRLAST is set");
193 ++wr_beat_cnt_local;
194 }
195
196 wr_beat_cnt = wr_beat_cnt_local;
197 }
198 }
199
200 if (!wr_addr_full) {
201 typename axi4_::AddrPayload wr_addr_pld;
202 if (if_wr.aw.PopNB(wr_addr_pld)) {
203 wr_addr.push(wr_addr_pld);
204 }
205 }
206 }
207 }
208};
209
210#endif
An AXI subordinate SRAM.
Configurable FIFO class.
Definition fifo.h:65
The base axi4 class parameterized according a valid config.
Definition axi4.h:64
Abstract Memory Class.
Definition mem_array.h:83
#define NVHLS_ASSERT_MSG(X, MSG)
#define CDCOUT(x, y)
Definition hls_globals.h:73
#define NVUINTW(width)
Definition nvhls_types.h:35
A struct composed of the signals associated with AXI read and write requests.
Definition axi4.h:114
A struct composed of the signals associated with an AXI read response.
Definition axi4.h:157
A struct composed of the signals associated with an AXI write response.
Definition axi4.h:190
A struct composed of the signals associated with AXI write data.
Definition axi4.h:215