17 #ifndef __ARBITRATEDSCRATCHPADDP__
18 #define __ARBITRATEDSCRATCHPADDP__
20 #include <nvhls_int.h>
21 #include <nvhls_types.h>
22 #include <nvhls_assert.h>
23 #include <nvhls_message.h>
24 #include <arbitrated_crossbar.h>
26 #include <hls_globals.h>
57 template<
unsigned int kNumBanks,
unsigned int kNumReadPorts,
unsigned int
58 kNumWritePorts,
unsigned int kEntriesPerBank,
typename WordType,
bool isSF=
true,
bool IsSPRAM=
false>
65 typedef NVUINTW(kReadPortIndexSize) ReadPortIndex;
66 typedef NVUINTW(kWritePortIndexSize) WritePortIndex;
67 typedef NVUINTW(kBankIndexSize) BankIndex;
68 typedef NVUINTW(kLocalIndexSize) LocalIndex;
70 typedef NVUINTW(kAddressSize) Address;
71 typedef NVUINTW(kNumReadPorts) ReadPortBitVector;
72 typedef NVUINTW(kNumWritePorts) WritePortBitVector;
78 LocalIndex localindex;
80 static const int width = WordType::width + LocalIndex::width;
81 template <
unsigned int Size>
82 void Marshall(Marshaller<Size>& m) {
90 LocalIndex localindex;
91 static const int width = LocalIndex::width;
93 template <
unsigned int Size>
94 void Marshall(Marshaller<Size>& m) {
103 static const int width = 1 + WordType::width;
105 template <
unsigned int Size>
106 void Marshall(Marshaller<Size>& m) {
117 void compute_bankread_request(Address read_address[kNumReadPorts],
bool read_req_valid[kNumReadPorts],
118 bankread_req_t bankread_req[kNumReadPorts],
119 BankIndex bankread_sel[kNumReadPorts],
120 bool bankread_req_valid[kNumReadPorts]) {
123 #pragma hls_unroll yes
124 for (
unsigned in_chan = 0; in_chan < kNumReadPorts; in_chan++) {
125 bankread_sel[in_chan] = GetBankIndex(read_address[in_chan]);
126 bankread_req[in_chan].localindex = GetLocalIndex(read_address[in_chan]);
127 bankread_req_valid[in_chan] = (read_req_valid[in_chan] ==
true);
131 void compute_bankwrite_request(Address write_address[kNumWritePorts],
bool write_req_valid[kNumWritePorts],
132 WordType write_data[kNumWritePorts],
133 bankwrite_req_t bankwrite_req[kNumWritePorts],
134 BankIndex bankwrite_sel[kNumWritePorts],
135 bool bankwrite_req_valid[kNumWritePorts]) {
138 #pragma hls_unroll yes
139 for (
unsigned in_chan = 0; in_chan < kNumWritePorts; in_chan++) {
140 bankwrite_sel[in_chan] = GetBankIndex(write_address[in_chan]);
141 bankwrite_req[in_chan].localindex = GetLocalIndex(write_address[in_chan]);
142 bankwrite_req[in_chan].data = write_data[in_chan];
143 bankwrite_req_valid[in_chan] = (write_req_valid[in_chan] ==
true);
148 void banks_load_store(bankread_req_t bankread_req[kNumBanks],
149 bool bankread_req_valid[kNumBanks],
150 bankwrite_req_t bankwrite_req[kNumBanks],
151 bool bankwrite_req_valid[kNumBanks],
152 bankread_rsp_t bankread_rsp[kNumBanks],
153 NVUINTW(kEntriesPerBank) valid_entry[kNumBanks]
155 #pragma hls_unroll yes
156 for (
unsigned bank = 0; bank < kNumBanks; bank++) {
157 if (IsSPRAM ==
false) {
158 if (bankread_req_valid[bank] ==
true) {
159 bankread_rsp[bank].valid =
true;
161 if (isSF && (bankwrite_req_valid[bank] ==
true) && (bankread_req[bank].localindex == bankwrite_req[bank].localindex)) {
162 bankread_rsp[bank].rdata = bankwrite_req[bank].data;
163 }
else if (valid_entry[bank][bankread_req[bank].localindex]) {
164 bankread_rsp[bank].rdata = banks.read(bankread_req[bank].localindex, bank);
166 bankread_rsp[bank].rdata = 0;
169 bankread_rsp[bank].rdata = 0;
170 bankread_rsp[bank].valid =
false;
172 if (bankwrite_req_valid[bank] ==
true) {
173 banks.write(bankwrite_req[bank].localindex, bank, bankwrite_req[bank].data);
194 if (bankwrite_req_valid[bank] ==
true) {
195 banks.write(bankwrite_req[bank].localindex, bank, bankwrite_req[bank].data);
196 NVHLS_ASSERT_MSG(bankread_req_valid[bank] ==
false,
"Bank read and write valid cannot be true simultaneously for single-port RAM");
197 bankread_rsp[bank].rdata = 0;
198 bankread_rsp[bank].valid =
false;
200 if (bankread_req_valid[bank] ==
true) {
201 bankread_rsp[bank].valid =
true;
202 if (valid_entry[bank][bankread_req[bank].localindex]) {
203 bankread_rsp[bank].rdata = banks.read(bankread_req[bank].localindex, bank);
211 bankread_rsp[bank].rdata = 0;
226 BankIndex GetBankIndex(Address a) {
227 if (kNumBanks == 1) {
234 LocalIndex GetLocalIndex(Address a) {
235 if (kNumBanks == 1) {
253 void run(Address read_address[kNumReadPorts],
bool read_req_valid[kNumReadPorts],
254 Address write_address[kNumWritePorts],
bool write_req_valid[kNumWritePorts],
255 WordType write_data[kNumWritePorts],
256 Ack read_ack[kNumReadPorts], Ack write_ack[kNumWritePorts],
257 bool read_ready[kNumReadPorts],
258 WordType port_read_out[kNumReadPorts],
bool port_read_out_valid[kNumReadPorts]
260 NVUINTW(kEntriesPerBank) valid_entry[kNumBanks];
261 #pragma hls_unroll yes
262 for (
unsigned i = 0; i < kNumBanks; i++) {
265 run(read_address, read_req_valid,
266 write_address, write_req_valid,
270 port_read_out, port_read_out_valid, valid_entry);
273 void run(Address read_address[kNumReadPorts],
bool read_req_valid[kNumReadPorts],
274 Address write_address[kNumWritePorts],
bool write_req_valid[kNumWritePorts],
275 WordType write_data[kNumWritePorts],
276 Ack read_ack[kNumReadPorts], Ack write_ack[kNumWritePorts],
277 bool read_ready[kNumReadPorts],
278 WordType port_read_out[kNumReadPorts],
bool port_read_out_valid[kNumReadPorts],
279 NVUINTW(kEntriesPerBank) valid_entry[kNumBanks]
282 bankread_req_t bankread_req[kNumReadPorts];
283 BankIndex bankread_sel[kNumReadPorts];
284 bool bankread_req_valid[kNumReadPorts];
285 compute_bankread_request(read_address, read_req_valid, bankread_req, bankread_sel,
288 bankwrite_req_t bankwrite_req[kNumWritePorts];
289 BankIndex bankwrite_sel[kNumWritePorts];
290 bool bankwrite_req_valid[kNumWritePorts];
291 compute_bankwrite_request(write_address, write_req_valid, write_data,
292 bankwrite_req, bankwrite_sel,
293 bankwrite_req_valid);
295 bool read_done[kNumReadPorts];
296 bankread_req_t bankread_req_winner[kNumBanks];
297 bool bankread_req_winner_valid[kNumBanks];
298 ReadPortIndex read_source[kNumBanks];
299 read_arbxbar.
run(bankread_req, bankread_sel, bankread_req_valid, bankread_req_winner,
300 bankread_req_winner_valid, read_done, read_source);
302 #pragma hls_unroll yes
303 for (
unsigned int i=0; i < kNumReadPorts; i++) {
304 read_ack[i] = read_done[i] && read_req_valid[i];
305 read_ready[i] = read_done[i] || (!read_req_valid[i]);
310 bankwrite_req_t bankwrite_req_winner[kNumBanks];
311 bool bankwrite_req_winner_valid[kNumBanks];
312 bool write_ready[kNumWritePorts];
313 WritePortIndex write_source[kNumBanks];
314 write_arbxbar.
run(bankwrite_req, bankwrite_sel, bankwrite_req_valid, bankwrite_req_winner,
315 bankwrite_req_winner_valid, write_ready, write_source);
317 #pragma hls_unroll yes
318 for (
unsigned int i=0; i < kNumWritePorts; i++)
319 write_ack[i] = write_ready[i] && write_req_valid[i];
321 #pragma hls_unroll yes
322 for (
unsigned bank = 0; bank < kNumBanks; bank++) {
323 if (bankread_req_winner_valid[bank] && bankwrite_req_winner_valid[bank]) {
324 bankread_req_winner_valid[bank] =
false;
325 read_ack[read_source[bank]] =
false;
329 bankread_rsp_t bankread_rsp[kNumBanks];
330 banks_load_store(bankread_req_winner,
331 bankread_req_winner_valid,
332 bankwrite_req_winner,
333 bankwrite_req_winner_valid,
334 bankread_rsp, valid_entry);
337 WordType bank_read_out[kNumBanks];
338 bool bank_read_out_valid[kNumBanks];
339 BankIndex bank_read_data_source[kNumReadPorts];
340 #pragma hls_unroll yes
341 for (
unsigned bank = 0; bank < kNumBanks; bank++) {
342 bank_read_out_valid[bank] = bankread_rsp[bank].valid;
343 bank_read_out[bank] = bankread_rsp[bank].rdata;
345 #pragma hls_unroll yes
346 for (
unsigned i = 0; i < kNumReadPorts; i++) {
347 bank_read_data_source[i] = bankread_sel[i];
350 WordType port_read_out_local[kNumReadPorts];
351 bool port_read_out_valid_local[kNumReadPorts];
352 crossbar<WordType, kNumBanks, kNumReadPorts>(bank_read_out, bank_read_out_valid, bank_read_data_source, read_ack,
353 port_read_out_local, port_read_out_valid_local);
354 #pragma hls_unroll yes
355 for (
unsigned i = 0; i < kNumReadPorts; i++) {
356 port_read_out_valid[i] = port_read_out_valid_local[i];
358 #pragma hls_unroll yes
359 for (
unsigned i = 0; i < kNumReadPorts; i++) {
360 if (port_read_out_valid[i]) {
361 port_read_out[i] = port_read_out_local[i];
ArbitratedScratchpad with dual port support.
void run(DataType data_in[NumInputs], OutputIdx dest_in[NumInputs], bool valid_in[NumInputs], DataType data_out[NumOutputs], bool valid_out[NumOutputs], bool ready[NumInputs], InputIdx source[NumOutputs])
Top-Level function for Arbitrated Crossbar.
#define NVHLS_ASSERT_MSG(X, MSG)
nvhls_t< W >::nvuint_t get_slc(type X, const unsigned int i)
Function that returns slice of bits.
Compute index width of a constant.