gem5 [DEVELOP-FOR-25.1]
Loading...
Searching...
No Matches
fa_lru.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2023-2024 ARM Limited
3 * Copyright (c) 2018 Inria
4 * Copyright (c) 2013,2016-2018 ARM Limited
5 * All rights reserved.
6 *
7 * The license below extends only to copyright in the software and shall
8 * not be construed as granting a license to any other intellectual
9 * property including but not limited to intellectual property relating
10 * to a hardware implementation of the functionality of the software
11 * licensed hereunder. You may use the software subject to the license
12 * terms below provided that you ensure that this notice is replicated
13 * unmodified and in its entirety in all distributions of the software,
14 * modified or unmodified, in source code or in binary form.
15 *
16 * Copyright (c) 2003-2005 The Regents of The University of Michigan
17 * All rights reserved.
18 *
19 * Redistribution and use in source and binary forms, with or without
20 * modification, are permitted provided that the following conditions are
21 * met: redistributions of source code must retain the above copyright
22 * notice, this list of conditions and the following disclaimer;
23 * redistributions in binary form must reproduce the above copyright
24 * notice, this list of conditions and the following disclaimer in the
25 * documentation and/or other materials provided with the distribution;
26 * neither the name of the copyright holders nor the names of its
27 * contributors may be used to endorse or promote products derived from
28 * this software without specific prior written permission.
29 *
30 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
31 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
32 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
33 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
34 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
35 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
36 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
37 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
38 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
39 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
40 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
41 */
42
47
49
50#include <cassert>
51#include <sstream>
52
53#include "base/compiler.hh"
54#include "base/intmath.hh"
55#include "base/logging.hh"
57
58namespace gem5
59{
60
61std::string
63{
64 return csprintf("%s inCachesMask: %#x", CacheBlk::print(), inCachesMask);
65}
66
68 : BaseTags(p),
69
70 cacheTracking(p.min_tracked_cache_size, size, blkSize, this)
71{
72 if (!isPowerOf2(blkSize))
73 fatal("cache block size (in bytes) `%d' must be a power of two",
74 blkSize);
75 if (!isPowerOf2(size))
76 fatal("Cache Size must be power of 2 for now");
78 fatal("Cannot use Cache Partitioning Policies with FALRU");
79
80 blks = new FALRUBlk[numBlocks];
81}
82
84{
85 delete[] blks;
86}
87
88void
90{
91 head = &(blks[0]);
92 head->prev = nullptr;
93 head->next = &(blks[1]);
94 head->setPosition(0, 0);
95 head->data = &dataBlks[0];
96
97 for (unsigned i = 1; i < numBlocks - 1; i++) {
98 blks[i].prev = &(blks[i-1]);
99 blks[i].next = &(blks[i+1]);
100 blks[i].setPosition(0, i);
101
102 // Associate a data chunk to the block
103 blks[i].data = &dataBlks[blkSize*i];
104 }
105
106 tail = &(blks[numBlocks - 1]);
107 tail->prev = &(blks[numBlocks - 2]);
108 tail->next = nullptr;
109 tail->setPosition(0, numBlocks - 1);
110 tail->data = &dataBlks[(numBlocks - 1) * blkSize];
111
112 cacheTracking.init(head, tail);
113}
114
115void
117{
118 // Erase block entry reference in the hash table
119 [[maybe_unused]] auto num_erased =
120 tagHash.erase(std::make_pair(blk->getTag(), blk->isSecure()));
121
122 // Sanity check; only one block reference should be erased
123 assert(num_erased == 1);
124
125 // Invalidate block entry. Must be done after the hash is erased
127
128 // Decrease the number of tags in use
129 stats.tagsInUse--;
130
131 // Move the block to the tail to make it the next victim
132 moveToTail((FALRUBlk*)blk);
133}
134
137{
138 return accessBlock(pkt, lat, 0);
139}
140
143 CachesMask *in_caches_mask)
144{
145 CachesMask mask = 0;
146 FALRUBlk* blk =
147 static_cast<FALRUBlk*>(findBlock({pkt->getAddr(), pkt->isSecure()}));
148
149 // If a cache hit
150 if (blk && blk->isValid()) {
151 mask = blk->inCachesMask;
152
153 moveToHead(blk);
154 }
155
156 if (in_caches_mask) {
157 *in_caches_mask = mask;
158 }
159
160 cacheTracking.recordAccess(blk);
161
162 // The tag lookup latency is the same for a hit or a miss
163 lat = lookupLatency;
164
165 return blk;
166}
167
170{
171 FALRUBlk* blk = nullptr;
172
173 Addr tag = extractTag(lookup.address);
174 auto key = std::make_pair(tag, lookup.secure);
175 auto iter = tagHash.find(key);
176 if (iter != tagHash.end()) {
177 blk = (*iter).second;
178 }
179
180 if (blk && blk->isValid()) {
181 assert(blk->getTag() == tag);
182 assert(blk->isSecure() == lookup.secure);
183 }
184
185 return blk;
186}
187
190{
191 assert(set == 0);
192 return &blks[way];
193}
194
196FALRU::findVictim(const CacheBlk::KeyType& key, const std::size_t size,
197 std::vector<CacheBlk*>& evict_blks,
198 const uint64_t partition_id)
199{
200 // The victim is always stored on the tail for the FALRU
201 FALRUBlk* victim = tail;
202
203 // There is only one eviction for this replacement
204 evict_blks.push_back(victim);
205
206 return victim;
207}
208
209void
211{
212 FALRUBlk* falruBlk = static_cast<FALRUBlk*>(blk);
213
214 // Make sure block is not present in the cache
215 assert(falruBlk->inCachesMask == 0);
216
217 // Do common block insertion functionality
218 BaseTags::insertBlock(pkt, blk);
219
220 // Increment tag counter
221 stats.tagsInUse++;
222
223 // New block is the MRU
224 moveToHead(falruBlk);
225
226 // Insert new block in the hash table
227 tagHash[std::make_pair(blk->getTag(), blk->isSecure())] = falruBlk;
228}
229
230void
232{
233 panic("Moving blocks in FALRU has not been implemented");
234}
235
236void
238{
239 // If block is not already head, do the moving
240 if (blk != head) {
241 cacheTracking.moveBlockToHead(blk);
242 // If block is tail, set previous block as new tail
243 if (blk == tail){
244 assert(blk->next == nullptr);
245 tail = blk->prev;
246 tail->next = nullptr;
247 // Inform block's surrounding blocks that it has been moved
248 } else {
249 blk->prev->next = blk->next;
250 blk->next->prev = blk->prev;
251 }
252
253 // Swap pointers
254 blk->next = head;
255 blk->prev = nullptr;
256 head->prev = blk;
257 head = blk;
258
259 cacheTracking.check(head, tail);
260 }
261}
262
263void
265{
266 // If block is not already tail, do the moving
267 if (blk != tail) {
268 cacheTracking.moveBlockToTail(blk);
269 // If block is head, set next block as new head
270 if (blk == head){
271 assert(blk->prev == nullptr);
272 head = blk->next;
273 head->prev = nullptr;
274 // Inform block's surrounding blocks that it has been moved
275 } else {
276 blk->prev->next = blk->next;
277 blk->next->prev = blk->prev;
278 }
279
280 // Swap pointers
281 blk->prev = tail;
282 blk->next = nullptr;
283 tail->next = blk;
284 tail = blk;
285
286 cacheTracking.check(head, tail);
287 }
288}
289
290void
291printSize(std::ostream &stream, size_t size)
292{
293 static const char *SIZES[] = { "B", "kB", "MB", "GB", "TB", "ZB" };
294 int div = 0;
295 while (size >= 1024 && div < (sizeof SIZES / sizeof *SIZES)) {
296 div++;
297 size >>= 10;
298 }
299 stream << size << SIZES[div];
300}
301
302FALRU::CacheTracking::CacheTracking(unsigned min_size, unsigned max_size,
303 unsigned block_size, statistics::Group *parent)
304 : statistics::Group(parent),
305 blkSize(block_size),
306 minTrackedSize(min_size),
307 numTrackedCaches(max_size > min_size ?
308 floorLog2(max_size) - floorLog2(min_size) : 0),
311 ADD_STAT(hits, statistics::units::Count::get(),
312 "The number of hits in each cache size."),
313 ADD_STAT(misses, statistics::units::Count::get(),
314 "The number of misses in each cache size."),
315 ADD_STAT(accesses, statistics::units::Count::get(),
316 "The number of accesses to the FA LRU cache.")
317{
319 "Not enough bits (%s) in type CachesMask type to keep "
320 "track of %d caches\n", sizeof(CachesMask),
322
323 hits
324 .init(numTrackedCaches + 1);
325 misses
326 .init(numTrackedCaches + 1);
327
328 for (unsigned i = 0; i < numTrackedCaches + 1; ++i) {
329 std::stringstream size_str;
330 printSize(size_str, minTrackedSize << i);
331 hits.subname(i, size_str.str());
332 hits.subdesc(i, "Hits in a " + size_str.str() + " cache");
333 misses.subname(i, size_str.str());
334 misses.subdesc(i, "Misses in a " + size_str.str() + " cache");
335 }
336}
337
338void
340{
341#ifdef FALRU_DEBUG
342 const FALRUBlk* blk = head;
343 unsigned curr_size = 0;
344 unsigned tracked_cache_size = minTrackedSize;
345 CachesMask in_caches_mask = inAllCachesMask;
346 int j = 0;
347
348 while (blk) {
349 panic_if(blk->inCachesMask != in_caches_mask, "Expected cache mask "
350 "%x found %x", blk->inCachesMask, in_caches_mask);
351
352 curr_size += blkSize;
353 if (curr_size == tracked_cache_size && blk != tail) {
354 panic_if(boundaries[j] != blk, "Unexpected boundary for the %d-th "
355 "cache", j);
356 tracked_cache_size <<= 1;
357 // from this point, blocks fit only in the larger caches
358 in_caches_mask &= ~(1U << j);
359 ++j;
360 }
361 blk = blk->next;
362 }
363#endif // FALRU_DEBUG
364}
365
366void
368{
369 // early exit if we are not tracking any extra caches
370 FALRUBlk* blk = numTrackedCaches ? head : nullptr;
371 unsigned curr_size = 0;
372 unsigned tracked_cache_size = minTrackedSize;
373 CachesMask in_caches_mask = inAllCachesMask;
374 int j = 0;
375
376 while (blk) {
377 blk->inCachesMask = in_caches_mask;
378
379 curr_size += blkSize;
380 if (curr_size == tracked_cache_size && blk != tail) {
381 boundaries[j] = blk;
382
383 tracked_cache_size <<= 1;
384 // from this point, blocks fit only in the larger caches
385 in_caches_mask &= ~(1U << j);
386 ++j;
387 }
388 blk = blk->next;
389 }
390}
391
392
393void
395{
396 // Get the mask of all caches, in which the block didn't fit
397 // before moving it to the head
398 CachesMask update_caches_mask = inAllCachesMask ^ blk->inCachesMask;
399
400 for (int i = 0; i < numTrackedCaches; i++) {
401 CachesMask current_cache_mask = 1U << i;
402 if (current_cache_mask & update_caches_mask) {
403 // if the ith cache didn't fit the block (before it is moved to
404 // the head), move the ith boundary 1 block closer to the
405 // MRU
406 boundaries[i]->inCachesMask &= ~current_cache_mask;
407 boundaries[i] = boundaries[i]->prev;
408 } else if (boundaries[i] == blk) {
409 // Make sure the boundary doesn't point to the block
410 // we are about to move
411 boundaries[i] = blk->prev;
412 }
413 }
414
415 // Make block reside in all caches
417}
418
419void
421{
422 CachesMask update_caches_mask = blk->inCachesMask;
423
424 for (int i = 0; i < numTrackedCaches; i++) {
425 CachesMask current_cache_mask = 1U << i;
426 if (current_cache_mask & update_caches_mask) {
427 // if the ith cache fitted the block (before it is moved to
428 // the tail), move the ith boundary 1 block closer to the
429 // LRU
430 boundaries[i] = boundaries[i]->next;
431 if (boundaries[i] == blk) {
432 // Make sure the boundary doesn't point to the block
433 // we are about to move
434 boundaries[i] = blk->next;
435 }
436 boundaries[i]->inCachesMask |= current_cache_mask;
437 }
438 }
439
440 // The block now fits only in the actual cache
441 blk->inCachesMask = 0;
442}
443
444void
446{
447 for (int i = 0; i < numTrackedCaches; i++) {
448 if (blk && ((1U << i) & blk->inCachesMask)) {
449 hits[i]++;
450 } else {
451 misses[i]++;
452 }
453 }
454
455 // Record stats for the actual cache too
456 if (blk && blk->isValid()) {
458 } else {
460 }
461
462 accesses++;
463}
464
465} // namespace gem5
partitioning_policy::PartitionManager * partitionManager
Partitioning manager.
Definition base.hh:92
virtual void insertBlock(const PacketPtr pkt, CacheBlk *blk)
Insert the new block into the cache and update stats.
Definition base.cc:101
BaseTags(const Params &p)
Definition base.cc:62
const unsigned size
The size of the cache.
Definition base.hh:81
const unsigned numBlocks
the number of blocks in the cache
Definition base.hh:103
virtual void invalidate(CacheBlk *blk)
This function updates the tags when a block is invalidated.
Definition base.hh:257
gem5::BaseTags::BaseTagStats stats
std::unique_ptr< uint8_t[]> dataBlks
The data blocks, 1 per cache block.
Definition base.hh:106
const Cycles lookupLatency
The tag lookup latency of the cache.
Definition base.hh:83
const unsigned blkSize
The block size of the cache.
Definition base.hh:77
A Basic Cache block.
Definition cache_blk.hh:72
std::string print() const override
Pretty-print tag, set and way, and interpret state bits to readable form including mapping to a MOESI...
Definition cache_blk.hh:372
Cycles is a wrapper class for representing cycle counts, i.e.
Definition types.hh:79
A fully associative cache block.
Definition fa_lru.hh:86
FALRUBlk * next
The next block in LRU order.
Definition fa_lru.hh:94
FALRUBlk * prev
The previous block in LRU order.
Definition fa_lru.hh:92
std::string print() const override
Pretty-print inCachesMask and other CacheBlk information.
Definition fa_lru.cc:62
CachesMask inCachesMask
A bit mask of the caches that fit this block.
Definition fa_lru.hh:97
void check(const FALRUBlk *head, const FALRUBlk *tail) const
Check that the tracking mechanism is in consistent state.
Definition fa_lru.cc:339
void recordAccess(FALRUBlk *blk)
Notify of a block access.
Definition fa_lru.cc:445
const CachesMask inAllCachesMask
A mask for all cache being tracked.
Definition fa_lru.hh:346
void init(FALRUBlk *head, FALRUBlk *tail)
Initialiaze cache blocks and the tracking mechanism.
Definition fa_lru.cc:367
void moveBlockToHead(FALRUBlk *blk)
Update boundaries as a block will be moved to the MRU.
Definition fa_lru.cc:394
void moveBlockToTail(FALRUBlk *blk)
Update boundaries as a block will be moved to the LRU.
Definition fa_lru.cc:420
std::vector< FALRUBlk * > boundaries
Array of pointers to blocks at the cache boundaries.
Definition fa_lru.hh:348
const unsigned blkSize
The size of the cache block.
Definition fa_lru.hh:340
const unsigned minTrackedSize
The smallest cache we are tracking.
Definition fa_lru.hh:342
CacheTracking(unsigned min_size, unsigned max_size, unsigned block_size, statistics::Group *parent)
Definition fa_lru.cc:302
const int numTrackedCaches
The number of different size caches being tracked.
Definition fa_lru.hh:344
void moveToTail(FALRUBlk *blk)
Move a cache block to the LRU position.
Definition fa_lru.cc:264
CacheBlk * accessBlock(const PacketPtr pkt, Cycles &lat, CachesMask *in_cache_mask)
Access block and update replacement data.
Definition fa_lru.cc:142
TagHash tagHash
The address hash table.
Definition fa_lru.hh:139
Addr extractTag(Addr addr) const override
Generate the tag from the addres.
Definition fa_lru.hh:244
FALRU(const Params &p)
Construct and initialize this cache tagstore.
Definition fa_lru.cc:67
ReplaceableEntry * findBlockBySetAndWay(int set, int way) const override
Find a block given set and way.
Definition fa_lru.cc:189
void moveBlock(CacheBlk *src_blk, CacheBlk *dest_blk) override
Move a block's metadata to another location decided by the replacement policy.
Definition fa_lru.cc:231
void invalidate(CacheBlk *blk) override
Invalidate a cache block.
Definition fa_lru.cc:116
void moveToHead(FALRUBlk *blk)
Move a cache block to the MRU position.
Definition fa_lru.cc:237
CacheTracking cacheTracking
Definition fa_lru.hh:369
void tagsInit() override
Initialize blocks as FALRUBlk instances.
Definition fa_lru.cc:89
FALRUBlk * tail
The LRU block.
Definition fa_lru.hh:124
FALRUParams Params
Definition fa_lru.hh:156
FALRUBlk * head
The MRU block.
Definition fa_lru.hh:122
void insertBlock(const PacketPtr pkt, CacheBlk *blk) override
Insert the new block into the cache and update replacement data.
Definition fa_lru.cc:210
CacheBlk * findVictim(const CacheBlk::KeyType &key, const std::size_t size, std::vector< CacheBlk * > &evict_blks, const uint64_t partition_id=0) override
Find replacement victim based on address.
Definition fa_lru.cc:196
CacheBlk * findBlock(const CacheBlk::KeyType &lookup) const override
Find the block in the cache, do not update the replacement data.
Definition fa_lru.cc:169
FALRUBlk * blks
The cache blocks.
Definition fa_lru.hh:119
bool isSecure() const
Definition packet.hh:836
Addr getAddr() const
Definition packet.hh:807
A replaceable entry is a basic entry in a 2d table-like structure that needs to have replacement func...
virtual bool isValid() const
Checks if the entry is valid.
TaggedTypes::KeyType KeyType
bool isSecure() const
Check if this block holds data from the secure memory space.
virtual Addr getTag() const
Get tag associated to this block.
Statistics container.
Definition group.hh:93
STL vector class.
Definition stl.hh:37
Declaration of a fully associative LRU tag store.
#define ADD_STAT(n,...)
Convenience macro to add a stat to a statistics group.
Definition group.hh:75
statistics::Vector hits
Hits in each cache.
Definition fa_lru.hh:359
statistics::Vector misses
Misses in each cache.
Definition fa_lru.hh:361
statistics::Scalar accesses
Total number of accesses.
Definition fa_lru.hh:363
static constexpr std::enable_if_t< std::is_integral_v< T >, int > floorLog2(T x)
Definition intmath.hh:59
static constexpr bool isPowerOf2(const T &n)
Definition intmath.hh:98
#define panic(...)
This implements a cprintf based panic() function.
Definition logging.hh:220
#define fatal_if(cond,...)
Conditional fatal macro that checks the supplied condition and only causes a fatal error if the condi...
Definition logging.hh:268
#define fatal(...)
This implements a cprintf based fatal() function.
Definition logging.hh:232
#define panic_if(cond,...)
Conditional panic macro that checks the supplied condition and only panics if the condition is true a...
Definition logging.hh:246
Bitfield< 3, 0 > mask
Definition pcstate.hh:63
Bitfield< 7 > i
Definition misc_types.hh:67
Bitfield< 12, 11 > set
Bitfield< 0 > p
T div(T rs1, T rs2)
Definition utility.hh:192
Units for Stats.
Definition units.hh:113
Copyright (c) 2024 Arm Limited All rights reserved.
Definition binary32.hh:36
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
Definition types.hh:147
uint32_t CachesMask
Definition fa_lru.hh:80
Packet * PacketPtr
std::string csprintf(const char *format, const Args &...args)
Definition cprintf.hh:161
void printSize(std::ostream &stream, size_t size)
Definition fa_lru.cc:291

Generated on Mon Oct 27 2025 04:13:03 for gem5 by doxygen 1.14.0