17 #ifndef __AXISUBORDINATETOREG_H__
18 #define __AXISUBORDINATETOREG_H__
22 #include <hls_globals.h>
24 #include <mem_array.h>
54 template <
typename axiCfg,
int numReg,
int numAddrBitsToInspect = axiCfg::addrW
idth>
57 static const int kDebugLevel = 5;
62 sc_in<bool> reset_bar;
64 typename axi4_::read::template subordinate<> if_axi_rd;
65 typename axi4_::write::template subordinate<> if_axi_wr;
68 static const int bytesPerReg = axi4_::DATA_WIDTH >> 3;
71 sc_in<
NVUINTW(numAddrBitsToInspect)> baseAddr;
74 sc_out<
NVUINTW(axi4_::DATA_WIDTH)> regOut[numReg];
79 reset_bar(
"reset_bar"),
80 if_axi_rd(
"if_axi_rd"),
81 if_axi_wr(
"if_axi_wr")
84 sensitive << clk.pos();
85 async_reset_signal_is(reset_bar,
false);
93 NVUINTW(axi4_::DATA_WIDTH) reg[numReg];
94 NVUINTW(numAddrBitsToInspect) maxValidAddr = baseAddr.read() + bytesPerReg*numReg - 1;
96 #pragma hls_unroll yes
97 for (
int i=0; i<numReg; i++) {
99 regOut[i].write(reg[i]);
108 NVUINTW(numAddrBitsToInspect) axiRdAddr;
109 NVUINTW(axi4_::ALEN_WIDTH) axiRdLen;
111 NVUINTW(numAddrBitsToInspect) axiWrAddr;
114 bool read_arb_req = 0;
115 bool write_arb_req = 0;
116 bool arb_needs_update = 1;
121 #pragma hls_pipeline_init_interval 1
122 #pragma pipeline_stall_mode flush
126 valid_mask = write_arb_req << 1 | read_arb_req;
127 if (arb_needs_update) {
128 select_mask = arb.pick(valid_mask);
129 if (select_mask != 0) arb_needs_update = 0;
133 if (if_axi_rd.nb_aread(axi_rd_req)) {
135 NVUINTW(numAddrBitsToInspect) addr_temp(
static_cast<sc_uint<numAddrBitsToInspect>
>(axi_rd_req.addr));
136 NVUINTW(axi4_::ALEN_WIDTH) len_temp(
static_cast< sc_uint<axi4_::ALEN_WIDTH>
>(axi_rd_req.len));
137 axiRdAddr = addr_temp;
142 if (!write_arb_req) {
143 if (if_axi_wr.aw.PopNB(axi_wr_req_addr)) {
145 NVUINTW(numAddrBitsToInspect) addr_temp(
static_cast< sc_uint<numAddrBitsToInspect>
>(axi_wr_req_addr.addr));
146 axiWrAddr = addr_temp;
150 if (select_mask == 1) {
151 valid_rd_addr = (axiRdAddr >= baseAddr.read() && axiRdAddr <= maxValidAddr);
153 NVUINTW(regAddrWidth) regAddr = (axiRdAddr - baseAddr.read()) >> axiAddrBitsPerReg;
154 axi_rd_resp.id = axi_rd_req.id;
156 axi_rd_resp.resp = axi4_::Enc::XRESP::OKAY;
157 NVUINTW(axi4_::DATA_WIDTH) read_data;
158 axi_rd_resp.data = reg[regAddr];
161 axi_rd_resp.resp = axi4_::Enc::XRESP::SLVERR;
164 axi_rd_resp.last = 1;
166 arb_needs_update = 1;
168 axi_rd_resp.last = 0;
170 axiRdAddr += bytesPerReg;
172 if_axi_rd.rwrite(axi_rd_resp);
173 CDCOUT(sc_time_stamp() <<
" " << name() <<
" Read from local reg:"
174 <<
" axi_addr=" << hex << axiRdAddr.to_int64()
175 <<
" reg_addr=" << regAddr.to_int64()
176 <<
" data=" << hex << axi_rd_resp.data
177 << endl, kDebugLevel);
178 }
else if (select_mask == 2) {
179 if (if_axi_wr.w.PopNB(axi_wr_req_data)) {
180 valid_wr_addr = (axiWrAddr >= baseAddr.read() && axiWrAddr <= maxValidAddr);
182 NVUINTW(axi4_::DATA_WIDTH) axiData(
static_cast<typename axi4_::Data
>(axi_wr_req_data.data));
183 NVUINTW(regAddrWidth) regAddr = (axiWrAddr - baseAddr.read()) >> axiAddrBitsPerReg;
184 if (axi4_::WSTRB_WIDTH > 0) {
185 if (!axi_wr_req_data.wstrb.and_reduce()) {
186 NVUINTW(axi4_::DATA_WIDTH) old_data = reg[regAddr];
187 #pragma hls_unroll yes
188 for (
int i=0; i<axi4_::WSTRB_WIDTH; i++) {
189 if (axi_wr_req_data.wstrb[i] == 0) {
190 axiData =
nvhls::set_slc(axiData, nvhls::get_slc<8>(old_data,8*i), 8*i);
195 #pragma hls_unroll yes
196 for (
int i=0; i<numReg; i++) {
201 CDCOUT(sc_time_stamp() <<
" " << name() <<
" Wrote to local reg:"
202 <<
" axi_addr=" << hex << axiWrAddr.to_int64()
203 <<
" reg_addr=" << regAddr.to_int64()
204 <<
" data=" << hex << axi_wr_req_data.data
205 <<
" wstrb=" << hex << axi_wr_req_data.wstrb.to_uint64()
206 << endl, kDebugLevel);
207 if (axi_wr_req_data.last == 1) {
209 arb_needs_update = 1;
210 if (axiCfg::useWriteResponses) {
211 axi_wr_resp.id = axi_wr_req_addr.id;
213 axi_wr_resp.resp = axi4_::Enc::XRESP::OKAY;
215 axi_wr_resp.resp = axi4_::Enc::XRESP::SLVERR;
217 if_axi_wr.bwrite(axi_wr_resp);
220 axiWrAddr += bytesPerReg;
224 #pragma hls_unroll yes
225 for (
int i=0; i<numReg; i++) {
226 regOut[i].write(reg[i]);
260 template <
typename axiCfg,
int numControlReg,
int numStatusReg,
int numAddrBitsToInspect = axiCfg::addrW
idth>
263 static const int kDebugLevel = 5;
268 sc_in<bool> reset_bar;
270 typename axi4_::read::template subordinate<> if_axi_rd;
271 typename axi4_::write::template subordinate<> if_axi_wr;
273 static const int numReg = numControlReg + numStatusReg;
276 static const int bytesPerReg = axi4_::DATA_WIDTH >> 3;
279 sc_in<
NVUINTW(numAddrBitsToInspect)> baseAddr;
282 sc_out<
NVUINTW(axi4_::DATA_WIDTH)> regOut[numControlReg];
283 sc_in<
NVUINTW(axi4_::DATA_WIDTH)> regIn[numStatusReg];
288 reset_bar(
"reset_bar"),
289 if_axi_rd(
"if_axi_rd"),
290 if_axi_wr(
"if_axi_wr")
293 sensitive << clk.pos();
294 async_reset_signal_is(reset_bar,
false);
302 NVUINTW(axi4_::DATA_WIDTH) reg[numControlReg];
303 NVUINTW(numAddrBitsToInspect) maxValidRdAddr = baseAddr.read() + bytesPerReg*numReg - 1;
304 NVUINTW(numAddrBitsToInspect) maxValidWrAddr = baseAddr.read() + bytesPerReg*numControlReg - 1;
306 #pragma hls_unroll yes
307 for (
int i=0; i<numControlReg; i++) {
309 regOut[i].write(reg[i]);
318 NVUINTW(numAddrBitsToInspect) axiRdAddr;
319 NVUINTW(axi4_::ALEN_WIDTH) axiRdLen;
321 NVUINTW(numAddrBitsToInspect) axiWrAddr;
324 bool read_arb_req = 0;
325 bool write_arb_req = 0;
326 bool arb_needs_update = 1;
331 #pragma hls_pipeline_init_interval 1
332 #pragma pipeline_stall_mode flush
336 valid_mask = write_arb_req << 1 | read_arb_req;
337 if (arb_needs_update) {
338 select_mask = arb.pick(valid_mask);
339 if (select_mask != 0) arb_needs_update = 0;
343 if (if_axi_rd.nb_aread(axi_rd_req)) {
345 NVUINTW(numAddrBitsToInspect) addr_temp(
static_cast<sc_uint<numAddrBitsToInspect>
>(axi_rd_req.addr));
346 NVUINTW(axi4_::ALEN_WIDTH) len_temp(
static_cast< sc_uint<axi4_::ALEN_WIDTH>
>(axi_rd_req.len));
347 axiRdAddr = addr_temp;
352 if (!write_arb_req) {
353 if (if_axi_wr.aw.PopNB(axi_wr_req_addr)) {
355 NVUINTW(numAddrBitsToInspect) addr_temp(
static_cast< sc_uint<numAddrBitsToInspect>
>(axi_wr_req_addr.addr));
356 axiWrAddr = addr_temp;
360 if (select_mask == 1) {
361 valid_rd_addr = (axiRdAddr >= baseAddr.read() && axiRdAddr <= maxValidRdAddr);
363 NVUINTW(controlRegAddrWidth) controlRegAddr = (axiRdAddr - baseAddr.read()) >> axiAddrBitsPerReg;
364 NVUINTW(statusRegAddrWidth) statusRegAddr = ((axiRdAddr - baseAddr.read()) >> axiAddrBitsPerReg) - numControlReg;
365 axi_rd_resp.id = axi_rd_req.id;
367 axi_rd_resp.resp = axi4_::Enc::XRESP::OKAY;
368 NVUINTW(axi4_::DATA_WIDTH) read_data;
369 if (axiRdAddr <= maxValidWrAddr) {
370 axi_rd_resp.data = reg[controlRegAddr];
372 axi_rd_resp.data = regIn[statusRegAddr].read();
376 axi_rd_resp.resp = axi4_::Enc::XRESP::SLVERR;
379 axi_rd_resp.last = 1;
381 arb_needs_update = 1;
383 axi_rd_resp.last = 0;
385 axiRdAddr += bytesPerReg;
387 if_axi_rd.rwrite(axi_rd_resp);
388 if (axiRdAddr <= maxValidWrAddr) {
389 CDCOUT(sc_time_stamp() <<
" " << name() <<
" Read from control reg:"
390 <<
" axi_addr=" << hex << axiRdAddr.to_int64()
391 <<
" reg_addr=" << controlRegAddr.to_int64()
392 <<
" data=" << hex << axi_rd_resp.data
393 << endl, kDebugLevel);
395 CDCOUT(sc_time_stamp() <<
" " << name() <<
" Read from status reg:"
396 <<
" axi_addr=" << hex << axiRdAddr.to_int64()
397 <<
" reg_addr=" << statusRegAddr.to_int64()
398 <<
" data=" << hex << axi_rd_resp.data
399 << endl, kDebugLevel);
401 }
else if (select_mask == 2) {
402 if (if_axi_wr.w.PopNB(axi_wr_req_data)) {
403 valid_wr_addr = (axiWrAddr >= baseAddr.read() && axiWrAddr <= maxValidWrAddr);
405 NVUINTW(axi4_::DATA_WIDTH) axiData(
static_cast<typename axi4_::Data
>(axi_wr_req_data.data));
406 NVUINTW(controlRegAddrWidth) regAddr = (axiWrAddr - baseAddr.read()) >> axiAddrBitsPerReg;
407 if (axi4_::WSTRB_WIDTH > 0) {
408 if (!axi_wr_req_data.wstrb.and_reduce()) {
409 NVUINTW(axi4_::DATA_WIDTH) old_data = reg[regAddr];
410 #pragma hls_unroll yes
411 for (
int i=0; i<axi4_::WSTRB_WIDTH; i++) {
412 if (axi_wr_req_data.wstrb[i] == 0) {
413 axiData =
nvhls::set_slc(axiData, nvhls::get_slc<8>(old_data,8*i), 8*i);
418 #pragma hls_unroll yes
419 for (
int i=0; i<numControlReg; i++) {
424 CDCOUT(sc_time_stamp() <<
" " << name() <<
" Wrote to local reg:"
425 <<
" axi_addr=" << hex << axiWrAddr.to_int64()
426 <<
" reg_addr=" << regAddr.to_int64()
427 <<
" data=" << hex << axi_wr_req_data.data
428 <<
" wstrb=" << hex << axi_wr_req_data.wstrb.to_uint64()
429 << endl, kDebugLevel);
430 if (axi_wr_req_data.last == 1) {
432 arb_needs_update = 1;
433 if (axiCfg::useWriteResponses) {
434 axi_wr_resp.id = axi_wr_req_addr.id;
436 axi_wr_resp.resp = axi4_::Enc::XRESP::OKAY;
438 axi_wr_resp.resp = axi4_::Enc::XRESP::SLVERR;
440 if_axi_wr.bwrite(axi_wr_resp);
443 axiWrAddr += bytesPerReg;
447 #pragma hls_unroll yes
448 for (
int i=0; i<numControlReg; i++) {
449 regOut[i].write(reg[i]);
A generalized implementation of generic n-way roundrobin arbiter.
An AXI subordinate containing memory-mapped registers.
An AXI subordinate containing memory-mapped registers.
The base axi4 class parameterized according a valid config.
#define NVHLS_ASSERT_MSG(X, MSG)
NVUINTW(Wrapped< T >::width) TypeToNVUINT(T in)
Convert Type to NVUINT.
type1 set_slc(type1 X, type2 Y, const unsigned int i)
Function that replaces slice of bits.
A struct composed of the signals associated with AXI read and write requests.
A struct composed of the signals associated with an AXI read response.
A struct composed of the signals associated with an AXI write response.
A struct composed of the signals associated with AXI write data.
Compute Celing of log2 of a constant.