MatchLib
All Classes Namespaces Files Functions Modules Pages
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
27template <typename T, int N>
28class 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
44template <typename T, int N, int A>
46 public:
47 T data[N / A][A];
48};
49
50template <typename T, int N, int A>
52 public:
53 T data[A][N / A];
54};
55
82template <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;
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
198template <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;
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
An implementation of array that declares VectorLength variables for array of size VectorLength.
#define NVHLS_ASSERT_MSG(X, MSG)
#define CMOD_ASSERT_MSG(X, MSG)
#define NVUINTW(width)
Definition nvhls_types.h:35
Compute index width of a constant.
Definition nvhls_int.h:285