ChampSim
lru_table.h
Go to the documentation of this file.
1 /*
2  * Copyright 2023 The ChampSim Contributors
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 
17 #ifndef MSL_LRU_TABLE_H
18 #define MSL_LRU_TABLE_H
19 
20 #include <algorithm>
21 #include <cassert>
22 #include <cstdint>
23 #include <optional>
24 #include <utility>
25 #include <vector>
26 
27 #include "msl/bits.h"
28 
29 namespace champsim::msl
30 {
31 namespace detail
32 {
33 template <typename T>
34 struct table_indexer {
35  auto operator()(const T& t) const { return t.index(); }
36 };
37 
38 template <typename T>
39 struct table_tagger {
40  auto operator()(const T& t) const { return t.tag(); }
41 };
42 } // namespace detail
43 
44 template <typename T, typename SetProj = detail::table_indexer<T>, typename TagProj = detail::table_tagger<T>>
45 class lru_table
46 {
47 public:
48  using value_type = T;
49 
50 private:
51  struct block_t {
52  uint64_t last_used = 0;
54  };
55  using block_vec_type = std::vector<block_t>;
56 
57  SetProj set_projection;
58  TagProj tag_projection;
59 
60  std::size_t NUM_SET, NUM_WAY;
61  uint64_t access_count = 0;
63 
64  auto get_set_span(const value_type& elem)
65  {
66  using diff_type = typename block_vec_type::difference_type;
67  auto set_idx = static_cast<diff_type>(set_projection(elem) & bitmask(lg2(NUM_SET)));
68  auto set_begin = std::next(std::begin(block), set_idx * static_cast<diff_type>(NUM_WAY));
69  auto set_end = std::next(set_begin, static_cast<diff_type>(NUM_WAY));
70  return std::pair{set_begin, set_end};
71  }
72 
73  auto match_func(const value_type& elem)
74  {
75  return [tag = tag_projection(elem), proj = this->tag_projection](const block_t& x) {
76  return x.last_used > 0 && proj(x.data) == tag;
77  };
78  }
79 
80  template <typename U>
81  auto match_and_check(U tag)
82  {
83  return [tag, proj = this->tag_projection](const auto& x, const auto& y) {
84  auto x_valid = x.last_used > 0;
85  auto y_valid = y.last_used > 0;
86  auto x_match = proj(x.data) == tag;
87  auto y_match = proj(y.data) == tag;
88  auto cmp_lru = x.last_used < y.last_used;
89  return !x_valid || (y_valid && ((!x_match && y_match) || ((x_match == y_match) && cmp_lru)));
90  };
91  }
92 
93 public:
94  std::optional<value_type> check_hit(const value_type& elem)
95  {
96  auto [set_begin, set_end] = get_set_span(elem);
97  auto hit = std::find_if(set_begin, set_end, match_func(elem));
98 
99  if (hit == set_end)
100  return std::nullopt;
101 
102  hit->last_used = ++access_count;
103  return hit->data;
104  }
105 
106  void fill(const value_type& elem)
107  {
108  auto tag = tag_projection(elem);
109  auto [set_begin, set_end] = get_set_span(elem);
110  if (set_begin != set_end) {
111  auto [miss, hit] = std::minmax_element(set_begin, set_end, match_and_check(tag));
112 
113  if (tag_projection(hit->data) == tag)
114  *hit = {++access_count, elem};
115  else
116  *miss = {++access_count, elem};
117  }
118  }
119 
120  std::optional<value_type> invalidate(const value_type& elem)
121  {
122  auto [set_begin, set_end] = get_set_span(elem);
123  auto hit = std::find_if(set_begin, set_end, match_func(elem));
124 
125  if (hit == set_end)
126  return std::nullopt;
127 
128  return std::exchange(*hit, {}).data;
129  }
130 
131  lru_table(std::size_t sets, std::size_t ways, SetProj set_proj, TagProj tag_proj)
132  : set_projection(set_proj), tag_projection(tag_proj), NUM_SET(sets), NUM_WAY(ways)
133  {
134  assert(sets == 0 || sets == (1ull << lg2(sets)));
135  }
136 
137  lru_table(std::size_t sets, std::size_t ways, SetProj set_proj) : lru_table(sets, ways, set_proj, {}) {}
138  lru_table(std::size_t sets, std::size_t ways) : lru_table(sets, ways, {}, {}) {}
139 };
140 } // namespace champsim::msl
141 
142 #endif
Definition: lru_table.h:46
SetProj set_projection
Definition: lru_table.h:57
T value_type
Definition: lru_table.h:48
TagProj tag_projection
Definition: lru_table.h:58
uint64_t access_count
Definition: lru_table.h:61
block_vec_type block
Definition: lru_table.h:62
lru_table(std::size_t sets, std::size_t ways, SetProj set_proj, TagProj tag_proj)
Definition: lru_table.h:131
std::optional< value_type > check_hit(const value_type &elem)
Definition: lru_table.h:94
std::size_t NUM_WAY
Definition: lru_table.h:60
std::optional< value_type > invalidate(const value_type &elem)
Definition: lru_table.h:120
void fill(const value_type &elem)
Definition: lru_table.h:106
std::vector< block_t > block_vec_type
Definition: lru_table.h:55
lru_table(std::size_t sets, std::size_t ways)
Definition: lru_table.h:138
std::size_t NUM_SET
Definition: lru_table.h:60
auto get_set_span(const value_type &elem)
Definition: lru_table.h:64
auto match_and_check(U tag)
Definition: lru_table.h:81
lru_table(std::size_t sets, std::size_t ways, SetProj set_proj)
Definition: lru_table.h:137
auto match_func(const value_type &elem)
Definition: lru_table.h:73
Definition: bits.h:24
constexpr uint64_t bitmask(std::size_t begin, std::size_t end=0)
Definition: bits.h:27
constexpr unsigned lg2(uint64_t n)
Definition: bits.h:25
Definition: lru_table.h:34
auto operator()(const T &t) const
Definition: lru_table.h:35
Definition: lru_table.h:39
auto operator()(const T &t) const
Definition: lru_table.h:40
Definition: lru_table.h:51
uint64_t last_used
Definition: lru_table.h:52
value_type data
Definition: lru_table.h:53