forked from altera-fpga/hls-samples
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathonchip_memory_with_cache.hpp
executable file
·127 lines (105 loc) · 3.81 KB
/
onchip_memory_with_cache.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
#ifndef __ONCHIP_MEMORY_WITH_CACHE_HPP__
#define __ONCHIP_MEMORY_WITH_CACHE_HPP__
#include <sycl/ext/intel/ac_types/ac_int.hpp>
#include "constexpr_math.hpp" // From the include directory
#include "unrolled_loop.hpp" // From the include directory
namespace fpga_tools {
template <typename T, // type to store in the memory
size_t k_mem_depth, // depth of the memory
size_t k_cache_depth // number of elements in the cache
>
class OnchipMemoryWithCache {
public:
static constexpr int kNumAddrBits = fpga_tools::CeilLog2(k_mem_depth);
using addr_t = ac_int<kNumAddrBits, false>;
OnchipMemoryWithCache() {
UnrolledLoop<k_cache_depth>([&](auto i) {
cache_valid_[i] = false;
});
}
OnchipMemoryWithCache(T init_val) { init(init_val); }
void init(T init_val) {
for (int i = 0; i < k_mem_depth; i++) {
data_[i] = init_val;
}
UnrolledLoop<k_cache_depth>([&](auto i) {
cache_valid_[i] = false;
});
}
OnchipMemoryWithCache(const OnchipMemoryWithCache&) = delete;
OnchipMemoryWithCache& operator=(const OnchipMemoryWithCache&) = delete;
// explicitly communicate to developers that we don't want to support a
// square bracket operator that returns a reference, as it would allow
// modification of the memory without updating the cache
template <typename I>
T& operator[](I addr) = delete;
// we can support the square bracket operator that returns a const ref
const T& operator[](addr_t addr) const { return read(addr); }
void write(addr_t addr, T val) {
// write the value from the end of the cache into the memory
if (cache_valid_[0]) {
data_[cache_addr_[0]] = cache_val_[0];
}
// Shift the values in the cache
UnrolledLoop<k_cache_depth - 1>([&](auto i) {
if (cache_addr_[i + 1] == addr) {
cache_valid_[i] = false; // invalidate old cache entry at same addr
} else {
cache_valid_[i] = cache_valid_[i + 1];
}
cache_val_[i] = cache_val_[i + 1];
cache_addr_[i] = cache_addr_[i + 1];
});
// write the new value into the cache
cache_val_[k_cache_depth - 1] = val;
cache_addr_[k_cache_depth - 1] = addr;
cache_valid_[k_cache_depth - 1] = true;
}
T read(addr_t addr) {
T return_val;
bool in_cache = false;
// check the cache, newest value will take precedence
UnrolledLoop<k_cache_depth>([&](auto i) {
if ((cache_addr_[i] == addr) && (cache_valid_[i])) {
return_val = cache_val_[i];
in_cache = true;
}
});
// if not in the cache, fetch from memory
if (!in_cache) {
return_val = data_[addr];
}
return return_val;
}
private:
T data_[k_mem_depth];
T cache_val_[k_cache_depth];
addr_t cache_addr_[k_cache_depth];
bool cache_valid_[k_cache_depth];
}; // class OnchipMemoryWithCache
// specialization for cache size 0 (no cache)
template <typename T, // type to store in the memory
size_t k_mem_depth // depth of the memory
>
class OnchipMemoryWithCache<T, k_mem_depth, 0> {
public:
static constexpr int kNumAddrBits = fpga_tools::CeilLog2(k_mem_depth);
using addr_t = ac_int<kNumAddrBits, false>;
OnchipMemoryWithCache() {}
OnchipMemoryWithCache(T init_val) {
for (int i = 0; i < k_mem_depth; i++) {
data_[i] = init_val;
}
}
OnchipMemoryWithCache(const OnchipMemoryWithCache&) = delete;
OnchipMemoryWithCache& operator=(const OnchipMemoryWithCache&) = delete;
template <typename I>
T& operator[](I addr) = delete;
const T& operator[](addr_t addr) const { return read(addr); }
void write(addr_t addr, T val) { data_[addr] = val; }
T read(addr_t addr) { return data_[addr]; }
private:
T data_[k_mem_depth];
}; // class OnchipMemoryWithCache<T, k_mem_depth, 0>
} // namespace fpga_tools
#endif // __ONCHIP_MEMORY_WITH_CACHE_HPP__