MatchLib
mem_array.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 MEM_ARRAY_H
17 #define MEM_ARRAY_H
18 
19 #include <nvhls_int.h>
20 #include <nvhls_types.h>
21 #include <nvhls_array.h>
22 #include <nvhls_marshaller.h>
23 #include <TypeToBits.h>
24 
25 // T: data type
26 // N: number of lines
27 template <typename T, int N>
28 class mem_array {
29  public:
30  T data[N];
31  mem_array() {
32  T value;
33  for (unsigned i = 0; i < N; i++) {
34 #ifndef SLEC_CPC
35  data[i] = value;
36 #endif
37  }
38  }
39 };
40 
41 // T: data type
42 // N: number of lines
43 // A: associativity
44 template <typename T, int N, int A>
45 class mem_array_2d {
46  public:
47  T data[N / A][A];
48 };
49 
50 template <typename T, int N, int A>
52  public:
53  T data[A][N / A];
54 };
55 
82 template <typename T, int NumEntries, int NumBanks, int NumByteEnables=1>
84  public:
85  typedef Wrapped<T> WData_t;
86  static const unsigned int NumEntriesPerBank = NumEntries/NumBanks;
87  static const unsigned int WordWidth = WData_t::width;
88  static const unsigned int SliceWidth = WordWidth/NumByteEnables;
89  typedef NVUINTW(nvhls::index_width<NumEntriesPerBank>::val) LocalIndex;
90  typedef NVUINTW(nvhls::index_width<NumEntriesPerBank*NumByteEnables>::val) LocalSliceIndex;
91  typedef NVUINTW(nvhls::index_width<NumBanks>::val) BankIndex;
92  typedef sc_lv<WordWidth> Data_t;
93  typedef sc_lv<SliceWidth> Slice_t;
94  typedef NVUINTW(NumByteEnables) WriteMask;
95  typedef NVUINTW(nvhls::index_width<NumByteEnables>::val) ByteEnableIndex;
96 
97  typedef Slice_t BankType[NumEntriesPerBank*NumByteEnables];
99  static const int width = NumEntries * WordWidth;
100 
101  mem_array_sep() {
102  Slice_t value;
103  for (unsigned i = 0; i < NumBanks; i++) {
104  for (unsigned j = 0; j < NumByteEnables* NumEntriesPerBank; j++) {
105 #ifndef SLEC_CPC
106  bank[i][j] = value;
107 #endif
108  }
109  }
110  }
111 
112  void clear() {
113  Slice_t value = 0;
114  for (unsigned i = 0; i < NumBanks; i++) {
115  for (unsigned j = 0; j < NumByteEnables * NumEntriesPerBank; j++) {
116  bank[i][j] = value;
117  }
118  }
119  }
120 
121  T read(LocalIndex idx, BankIndex bank_sel=0, WriteMask read_mask=~static_cast<WriteMask>(0)) {
122  Data_t read_data = TypeToBits<NVUINTW(WordWidth)>(0);
123  #pragma hls_unroll yes
124  for (int i = 0; i < NumByteEnables; i++) {
125  LocalSliceIndex local_slice_index = idx * NumByteEnables + i;
126  NVHLS_ASSERT_MSG(bank_sel<NumBanks, "bank index out of bounds");
127  NVHLS_ASSERT_MSG(idx<NumEntriesPerBank, "local index out of bounds");
128 #ifdef __SYNTHESIS__
129  read_data.range((i+1)*SliceWidth-1, i*SliceWidth) = bank[bank_sel][local_slice_index];
130 #else
131  if (read_mask[i] == 1) { // Prevent Xs from propagating to the output in C simulation
132  read_data.range((i+1)*SliceWidth-1, i*SliceWidth) = bank[bank_sel][local_slice_index];
133  }
134 #endif
135  }
136  CMOD_ASSERT_MSG(read_data.xor_reduce()!=sc_logic('X'), "Read data is X");
137  return BitsToType<T>(read_data);
138  }
139 
140  void write(LocalIndex idx, BankIndex bank_sel, T val, WriteMask write_mask=~static_cast<WriteMask>(0), bool wce=1) {
141  Slice_t tmp[NumByteEnables];
142  Data_t write_data = TypeToBits<T>(val);
143  #pragma hls_unroll yes
144  for (int i = 0; i < NumByteEnables; i++) {
145  tmp[i] = write_data.range((i+1)*SliceWidth-1, i*SliceWidth);
146  }
147  if (wce) {
148  #pragma hls_unroll yes
149  for (int i = 0; i < NumByteEnables; i++) {
150  if (write_mask[i] == 1) {
151  LocalSliceIndex local_slice_index = idx * NumByteEnables + i;
152  NVHLS_ASSERT_MSG(bank_sel<NumBanks, "bank index out of bounds");
153  NVHLS_ASSERT_MSG(idx<NumEntriesPerBank, "local index out of bounds");
154  bank[bank_sel][local_slice_index] = tmp[i];
155  CMOD_ASSERT_MSG(tmp[i].xor_reduce()!=sc_logic('X'), "Write data is X");
156  }
157  }
158  }
159  }
160 
161  template<unsigned int Size>
162  void Marshall(Marshaller<Size>& m) {
163  for (unsigned i = 0; i < NumBanks; i++) {
164  for (unsigned j = 0; j < NumByteEnables* NumEntriesPerBank; j++) {
165  m & bank[i][j];
166  }
167  }
168  }
169 };
170 
198 template <typename T, int NumEntriesPerBank, int NumBanks=1, int NumByteEnables=1>
200  public:
201  typedef Wrapped<T> WData_t;
202  static const unsigned int NumEntries = NumEntriesPerBank*NumBanks;
203  static const unsigned int WordWidth = WData_t::width;
204  static const unsigned int SliceWidth = WordWidth/NumByteEnables;
205  typedef NVUINTW(nvhls::index_width<NumEntriesPerBank>::val) LocalIndex;
206  typedef NVUINTW(nvhls::index_width<NumEntriesPerBank*NumByteEnables>::val) LocalSliceIndex;
207  typedef NVUINTW(nvhls::index_width<NumBanks>::val) BankIndex;
208  typedef sc_lv<WordWidth> Data_t;
209  typedef sc_lv<SliceWidth> Slice_t;
210  typedef NVUINTW(NumByteEnables) WriteMask;
211  typedef NVUINTW(nvhls::index_width<NumByteEnables>::val) ByteEnableIndex;
212 
213  typedef Slice_t BankType[NumEntriesPerBank*NumByteEnables];
214  #pragma hls_block_size NumEntriesPerBank
215  BankType bank[NumBanks];
216  static const int width = NumEntries * WordWidth;
217 
218  mem_array_opt() {
219  Slice_t value;
220  for (unsigned i = 0; i < NumBanks; i++) {
221  for (unsigned j = 0; j < NumByteEnables* NumEntriesPerBank; j++) {
222 #ifndef SLEC_CPC
223  bank[i][j] = value;
224 #endif
225  }
226  }
227 // T value;
228 // for (unsigned i = 0; i < N; i++) {
229 // #ifndef SLEC_CPC
230 // data[i] = value;
231 // #endif
232 // }
233  }
234 
235  void clear() {
236  Slice_t value = 0;
237  for (unsigned i = 0; i < NumBanks; i++) {
238  for (unsigned j = 0; j < NumByteEnables * NumEntriesPerBank; j++) {
239  bank[i][j] = value;
240  }
241  }
242  }
243 
244  T read(LocalIndex idx, BankIndex bank_sel=0, WriteMask read_mask=~static_cast<WriteMask>(0)) {
245  Data_t read_data = TypeToBits<NVUINTW(WordWidth)>(0);
246  #pragma hls_unroll yes
247  for (int i = 0; i < NumByteEnables; i++) {
248  LocalSliceIndex local_slice_index = idx * NumByteEnables + i;
249  NVHLS_ASSERT_MSG(bank_sel<NumBanks, "bank index out of bounds");
250  NVHLS_ASSERT_MSG(idx<NumEntriesPerBank, "local index out of bounds");
251 #ifdef __SYNTHESIS__
252  read_data.range((i+1)*SliceWidth-1, i*SliceWidth) = bank[bank_sel][local_slice_index];
253 #else
254  if (read_mask[i] == 1) { // Prevent Xs from propagating to the output in C simulation
255  read_data.range((i+1)*SliceWidth-1, i*SliceWidth) = bank[bank_sel][local_slice_index];
256  }
257 #endif
258  }
259  CMOD_ASSERT_MSG(read_data.xor_reduce()!=sc_logic('X'), "Read data is X");
260  return BitsToType<T>(read_data);
261  }
262 
263  void write(LocalIndex idx, BankIndex bank_sel, T val, WriteMask write_mask=~static_cast<WriteMask>(0), bool wce=1) {
264  Slice_t tmp[NumByteEnables];
265  Data_t write_data = TypeToBits<T>(val);
266  #pragma hls_unroll yes
267  for (int i = 0; i < NumByteEnables; i++) {
268  tmp[i] = write_data.range((i+1)*SliceWidth-1, i*SliceWidth);
269  }
270  if (wce) {
271  #pragma hls_unroll yes
272  for (int i = 0; i < NumByteEnables; i++) {
273  if (write_mask[i] == 1) {
274  LocalSliceIndex local_slice_index = idx * NumByteEnables + i;
275  NVHLS_ASSERT_MSG(bank_sel<NumBanks, "bank index out of bounds");
276  NVHLS_ASSERT_MSG(idx<NumEntriesPerBank, "local index out of bounds");
277  bank[bank_sel][local_slice_index] = tmp[i];
278  CMOD_ASSERT_MSG(tmp[i].xor_reduce()!=sc_logic('X'), "Write data is X");
279  }
280  }
281  }
282  }
283 
284  template<unsigned int Size>
285  void Marshall(Marshaller<Size>& m) {
286  for (unsigned i = 0; i < NumBanks; i++) {
287  for (unsigned j = 0; j < NumByteEnables* NumEntriesPerBank; j++) {
288  m & bank[i][j];
289  }
290  }
291  }
292 
293 };
294 
295 #endif
Abstract Memory Class.
Definition: mem_array.h:199
Abstract Memory Class.
Definition: mem_array.h:83
#define NVHLS_ASSERT_MSG(X, MSG)
Definition: nvhls_assert.h:135
#define CMOD_ASSERT_MSG(X, MSG)
Definition: nvhls_assert.h:166
Compute index width of a constant.
Definition: nvhls_int.h:285