MatchLib
Scratchpad.h
1 /*
2  * Copyright (c) 2016-2019, 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 #include <cstdio>
20 #include <systemc.h>
21 #include <nvhls_int.h>
22 #include <nvhls_types.h>
23 #include <hls_globals.h>
24 #include <nvhls_connections.h>
25 #include <crossbar.h>
26 
83 #include <Scratchpad/ScratchpadTypes.h>
84 #include <mem_array.h>
85 
86 template <typename T, int N, int CAPACITY_IN_BYTES>
87 class Scratchpad : public sc_module {
88  public:
89  static const int ADDR_WIDTH = nvhls::nbits<CAPACITY_IN_BYTES - 1>::val;
90  sc_in_clk clk;
91  sc_in<bool> rst;
92  Connections::In<cli_req_t<T, ADDR_WIDTH, N> > cli_req;
93  Connections::Out<cli_rsp_t<T, N> > cli_rsp;
94 
95  //------------Constants Here---------------------------
96  // Derived parameters
97  static const int NBANKS_LOG2 = nvhls::nbits<N - 1>::val;
98 
99  //------------Local typedefs---------------------------
100  typedef NVUINTW(NBANKS_LOG2) bank_sel_t;
101  typedef NVUINTW(ADDR_WIDTH - NBANKS_LOG2) bank_addr_t;
102  struct bank_req_t {
103  bank_addr_t addr;
104  T wdata;
105  };
106 
107  //------------Local Variables Here---------------------
109  bank_req_t input_reqs[N];
110  bool input_reqs_valid[N];
111  bank_req_t bank_reqs[N];
112  bool bank_reqs_valid[N];
113  T bank_rsps_data[N];
114  bool bank_rsps_valid[N];
115  bool load_rsps_valid[N];
116  cli_req_t<T, ADDR_WIDTH, N> curr_cli_req;
117  cli_rsp_t<T, N> load_rsp;
118  bank_sel_t bank_src_lane[N];
119  bank_sel_t bank_dst_lane[N];
120 
121  //----------- Constructor -----------------------------
122  // -Allocate and declare sub-modules
123  // -Declare all SC_METHODs and SC_THREADs
124  SC_HAS_PROCESS(Scratchpad);
125  Scratchpad(sc_module_name name_) : sc_module(name_) {
126  SC_THREAD(run);
127  sensitive << clk.pos();
129  //DCOUT("Capacity (bytes): " << CAPACITY_IN_BYTES << ", banks: " << N
130  // << ", addr width: " << ADDR_WIDTH << endl);
131  }
132 
133  void run() {
134 
135  // Reset behavior
136  cli_req.Reset();
137  cli_rsp.Reset();
138  wait();
139 
140  #pragma hls_pipeline_init_interval 1
141  #pragma pipeline_stall_mode flush
142  while (true) {
143 
144  bool is_load;
145  is_load = false;
146 
147  // Read client request
148  // (Implemented as a blocking read since there's no other work to do if no
149  // valid request in the channel)
150  curr_cli_req = cli_req.Pop();
151  is_load = (curr_cli_req.opcode == LOAD);
152 
153 // Pre-process the bank requests and compute lane selects from addresses
154 #pragma hls_unroll yes
155  for (int i = 0; i < N; i++) {
156  // For each request, figure out the target bank and update its bank_req
157  // fields
158  bank_sel_t bank_sel;
159  bank_sel = nvhls::get_slc<NBANKS_LOG2>(curr_cli_req.addr[i], 0);
160  bank_src_lane[bank_sel] = i;
161 
162  // Save the lane->bank mapping for the response xbar
163  bank_dst_lane[i] = bank_sel;
164 
165  // Convert from curr_cli_req to internal format
166  input_reqs_valid[i] = (curr_cli_req.valids[i] == true);
167  input_reqs[i].addr = nvhls::get_slc<ADDR_WIDTH - NBANKS_LOG2>(
168  curr_cli_req.addr[i], NBANKS_LOG2);
169  if (!is_load)
170  input_reqs[i].wdata = curr_cli_req.data[i];
171  }
172 
173  // Bank request crossbar
174  crossbar<bank_req_t, N, N>(input_reqs, input_reqs_valid, bank_src_lane,
175  bank_reqs, bank_reqs_valid);
176 
177 // Loop over scratchpad banks, execute load or store on each bank
178 #pragma hls_unroll yes
179  for (int i = 0; i < N; i++) {
180  if ((bank_reqs_valid[i] == true) && is_load) {
181  bank_rsps_valid[i] = true;
182  bank_rsps_data[i] = banks.read(bank_reqs[i].addr, i);
183  } else if ((bank_reqs_valid[i] == true) && !is_load) {
184  banks.write(bank_reqs[i].addr, i, bank_reqs[i].wdata);
185  bank_rsps_valid[i] = false;
186  } else {
187  bank_rsps_valid[i] = false;
188  }
189  }
190 
191  // Bank response crossbar
192  crossbar<T, N, N>(bank_rsps_data, bank_rsps_valid, bank_dst_lane,
193  load_rsp.data, load_rsps_valid);
194  #pragma hls_unroll yes
195  for (int i = 0; i < N; i++) {
196  load_rsp.valids[i] = load_rsps_valid[i]; // sc_lv to bool conversion
197  }
198  // Write client responses
199  if (is_load) {
200  cli_rsp.Push(load_rsp);
201  }
202 
203  wait();
204  }
205  }
206 };
207 
208 #endif
Parameterized banked scratchpad memory.
Definition: Scratchpad.h:87
nvhls_t< W >::nvuint_t get_slc(type X, const unsigned int i)
Function that returns slice of bits.
Definition: nvhls_int.h:437
Compute number of bits to represent a constant.
Definition: nvhls_int.h:118
#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&#39;s reset_signal_is() and async_reset_signal_is() so that ENABLE_SYNC_RESET can select type.
Definition: nvhls_module.h:39