MatchLib
Scratchpad.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 #ifndef SC_SCRATCHPAD
17 #define SC_SCRATCHPAD
18 
19 
20 #include <cstdio>
21 #include <systemc.h>
22 #include <nvhls_int.h>
23 #include <nvhls_types.h>
24 #include <hls_globals.h>
25 #include <nvhls_connections.h>
26 #include <crossbar.h>
27 #include <mem_array.h>
28 
29 #include <Scratchpad/ScratchpadTypes.h>
30 
100 template <typename T, int N, int CAPACITY_IN_WORDS>
102  public:
103 
104  static const int ADDR_WIDTH = nvhls::nbits<CAPACITY_IN_WORDS - 1>::val;
105  //------------Constants Here---------------------------
106  // Derived parameters
107  static const int NBANKS_LOG2 = nvhls::nbits<N - 1>::val;
108 
109  //------------Local typedefs---------------------------
110  typedef NVUINTW(NBANKS_LOG2) bank_sel_t;
111  typedef NVUINTW(ADDR_WIDTH - NBANKS_LOG2) bank_addr_t;
112  struct bank_req_t {
113  bank_addr_t addr;
114  T wdata;
115  };
117  typedef cli_rsp_t<T, N> rsp_t;
118 
119  //------------Local Variables Here---------------------
121  bank_req_t input_reqs[N];
122  bool input_reqs_valid[N];
123  bank_req_t bank_reqs[N];
124  bool bank_reqs_valid[N];
125  T bank_rsps_data[N];
126  bool bank_rsps_valid[N];
127  bool load_rsps_valid[N];
128  cli_rsp_t<T, N> load_rsp;
129  bank_sel_t bank_src_lane[N];
130  bank_sel_t bank_dst_lane[N];
131 
132  void store(req_t req) {
133  rsp_t load_rsp;
134  req.opcode = STORE;
135  load_store(req, load_rsp);
136  }
137 
138  rsp_t load(req_t req) {
139  rsp_t load_rsp;
140  req.opcode = LOAD;
141  load_store(req, load_rsp);
142  return load_rsp;
143  }
144 
145  void load_store(req_t curr_cli_req, rsp_t& load_rsp) {
146  bool is_load;
147 
148  is_load = (curr_cli_req.opcode == LOAD);
149 
150  // Pre-process the bank requests and compute lane selects from addresses
151  #pragma hls_unroll yes
152  for (int i = 0; i < N; i++) {
153  // For each request, figure out the target bank and update its bank_req
154  // fields
155  bank_sel_t bank_sel;
156  bank_sel = nvhls::get_slc<NBANKS_LOG2>(curr_cli_req.addr[i], 0);
157  bank_src_lane[bank_sel] = i;
158 
159  // Save the lane->bank mapping for the response xbar
160  bank_dst_lane[i] = bank_sel;
161 
162 #ifndef __SYNTHESIS__
163  for (int j=0; j < i; j++) {
164  if (bank_dst_lane[j] == bank_sel) {
165  std::cout << "Conflicting bank requests indexes are: "
166  << std::dec << i << " " << j << "\n";
167  }
168  NVHLS_ASSERT_MSG(bank_dst_lane[j] != bank_sel, "conflicting bank requests");
169  }
170 #endif
171 
172  // Convert from curr_cli_req to internal format
173  input_reqs_valid[i] = (curr_cli_req.valids[i] == true);
174  input_reqs[i].addr = nvhls::get_slc<ADDR_WIDTH - NBANKS_LOG2>(
175  curr_cli_req.addr[i], NBANKS_LOG2);
176  if (!is_load)
177  input_reqs[i].wdata = curr_cli_req.data[i];
178  }
179 
180  // Bank request crossbar
181  crossbar<bank_req_t, N, N>(input_reqs, input_reqs_valid, bank_src_lane,
182  bank_reqs, bank_reqs_valid);
183 
184  // Loop over scratchpad banks, execute load or store on each bank
185  #pragma hls_unroll yes
186  for (int i = 0; i < N; i++) {
187  if ((bank_reqs_valid[i] == true) && is_load) {
188  bank_rsps_valid[i] = true;
189  bank_rsps_data[i] = banks.read(bank_reqs[i].addr, i);
190  } else if ((bank_reqs_valid[i] == true) && !is_load) {
191  banks.write(bank_reqs[i].addr, i, bank_reqs[i].wdata);
192  bank_rsps_valid[i] = false;
193  } else {
194  bank_rsps_valid[i] = false;
195  }
196  }
197 
198  // Bank response crossbar
199  crossbar<T, N, N>(bank_rsps_data, bank_rsps_valid, bank_dst_lane,
200  load_rsp.data, load_rsps_valid);
201  #pragma hls_unroll yes
202  for (int i = 0; i < N; i++) {
203  load_rsp.valids[i] = load_rsps_valid[i]; // sc_lv to bool conversion
204  }
205  }
206 };
207 
258 template <typename T, int N, int CAPACITY_IN_WORDS>
259 class Scratchpad : public sc_module {
260  public:
261  static const int ADDR_WIDTH = nvhls::nbits<CAPACITY_IN_WORDS - 1>::val;
262  sc_in_clk clk;
263  sc_in<bool> rst;
264  Connections::In<cli_req_t<T, ADDR_WIDTH, N> > cli_req;
265  Connections::Out<cli_rsp_t<T, N> > cli_rsp;
266 
267  //------------Constants Here---------------------------
268  // Derived parameters
269  static const int NBANKS_LOG2 = nvhls::nbits<N - 1>::val;
270 
271  //------------Local typedefs---------------------------
272  typedef NVUINTW(NBANKS_LOG2) bank_sel_t;
273  typedef NVUINTW(ADDR_WIDTH - NBANKS_LOG2) bank_addr_t;
274  struct bank_req_t {
275  bank_addr_t addr;
276  T wdata;
277  };
279  typedef cli_rsp_t<T, N> rsp_t;
280 
282 
283  //----------- Constructor -----------------------------
284  // -Allocate and declare sub-modules
285  // -Declare all SC_METHODs and SC_THREADs
286  SC_HAS_PROCESS(Scratchpad);
287  Scratchpad(sc_module_name name_) : sc_module(name_) {
288  SC_THREAD(run);
289  sensitive << clk.pos();
291  //DCOUT("Capacity (words): " << CAPACITY_IN_WORDS << ", banks: " << N
292  // << ", addr width: " << ADDR_WIDTH << endl);
293  }
294 
295  void run() {
296 
297  // Reset behavior
298  cli_req.Reset();
299  cli_rsp.Reset();
300  wait();
301 
302  #pragma hls_pipeline_init_interval 1
303  #pragma pipeline_stall_mode flush
304  while (true) {
305 
306  bool is_load;
307  is_load = false;
308 
309  req_t curr_cli_req;
310  rsp_t load_rsp;
311 
312  // Read client request
313  // (Implemented as a blocking read since there's no other work to do if no
314  // valid request in the channel)
315 
316  curr_cli_req = cli_req.Pop();
317 
318  scratchpad_class.load_store(curr_cli_req, load_rsp);
319  is_load = (curr_cli_req.opcode == LOAD);
320 
321  // Write client responses
322  if (is_load) {
323  cli_rsp.Push(load_rsp);
324  }
325 
326  wait();
327  }
328  }
329 };
330 
395 template <typename WORD_TYPE, int NUM_BANKS, int CAPACITY_IN_WORDS>
397  typedef WORD_TYPE word_type;
398  static const int num_banks = NUM_BANKS;
399  static const int capacity_in_words = CAPACITY_IN_WORDS;
400 
401  static const int num_inputs = num_banks; // Note: for Scratchpad num_banks must equal num_inputs
402  static const int words_per_bank = capacity_in_words / num_banks;
403 
404 
407 
408  typedef typename mem_class_t::req_t base_req_t;
409  typedef typename mem_class_t::rsp_t base_rsp_t;
410 
411  static const int addr_width = mem_class_t::ADDR_WIDTH;
412  static const int bank_sel_width = mem_class_t::NBANKS_LOG2;
413  typedef typename mem_class_t::bank_sel_t bank_sel_t;
414 
415  typedef ac_int<addr_width, false> addr_t;
416 
417  struct scratchpad_req_t : public base_req_t {
418  // Note that it is important to initialize all valids to false since unitialized valids
419  // may lead to pre-HLS versus post-HLS simulation mismatches.
420  // This initialization should probably be moved into the base class..
421  scratchpad_req_t() {
422  for (unsigned i=0; i < num_inputs; i++)
423  this->valids[i] = 0;
424  }
425 
426  void set(unsigned idx, addr_t _addr, word_type _data=0) {
427  sc_assert(idx < num_inputs);
428  this->valids[idx] = 1;
429  this->addr[idx] = _addr;
430  this->data[idx] = _data;
431  }
432  };
433 };
434 
435 #endif
Parameterized banked scratchpad memory implemented as a C++ class (i.e. not a SystemC module)
Definition: Scratchpad.h:101
Parameterized banked scratchpad memory implemented as a SystemC module.
Definition: Scratchpad.h:259
#define NVHLS_ASSERT_MSG(X, MSG)
Definition: nvhls_assert.h:135
nvhls_t< W >::nvuint_t get_slc(type X, const unsigned int i)
Function that returns slice of bits.
Definition: nvhls_int.h:437
#define NVHLS_NEG_RESET_SIGNAL_IS(port)
ENABLE_SYNC_RESET define: Select synchronous or asynchronous reset.
Definition: nvhls_module.h:39
Traits class for Scratchpad and ScratchpadClass.
Definition: Scratchpad.h:396
Compute number of bits to represent a constant.
Definition: nvhls_int.h:118