gem5 [DEVELOP-FOR-25.0]
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"
56#include "mem/cache/base.hh"
58
59namespace gem5
60{
61
62std::string
64{
65 return csprintf("%s inCachesMask: %#x", CacheBlk::print(), inCachesMask);
66}
67
69 : BaseTags(p),
70
71 cacheTracking(p.min_tracked_cache_size, size, blkSize, this)
72{
73 if (!isPowerOf2(blkSize))
74 fatal("cache block size (in bytes) `%d' must be a power of two",
75 blkSize);
76 if (!isPowerOf2(size))
77 fatal("Cache Size must be power of 2 for now");
79 fatal("Cannot use Cache Partitioning Policies with FALRU");
80
81 blks = new FALRUBlk[numBlocks];
82}
83
85{
86 delete[] blks;
87}
88
89void
91{
92 head = &(blks[0]);
93 head->prev = nullptr;
94 head->next = &(blks[1]);
95 head->setPosition(0, 0);
96 head->data = &dataBlks[0];
97
98 for (unsigned i = 1; i < numBlocks - 1; i++) {
99 blks[i].prev = &(blks[i-1]);
100 blks[i].next = &(blks[i+1]);
101 blks[i].setPosition(0, i);
102
103 // Associate a data chunk to the block
104 blks[i].data = &dataBlks[blkSize*i];
105 }
106
107 tail = &(blks[numBlocks - 1]);
108 tail->prev = &(blks[numBlocks - 2]);
109 tail->next = nullptr;
110 tail->setPosition(0, numBlocks - 1);
111 tail->data = &dataBlks[(numBlocks - 1) * blkSize];
112
113 cacheTracking.init(head, tail);
114}
115
116void
118{
119 // Erase block entry reference in the hash table
120 [[maybe_unused]] auto num_erased =
121 tagHash.erase(std::make_pair(blk->getTag(), blk->isSecure()));
122
123 // Sanity check; only one block reference should be erased
124 assert(num_erased == 1);
125
126 // Invalidate block entry. Must be done after the hash is erased
128
129 // Decrease the number of tags in use
130 stats.tagsInUse--;
131
132 // Move the block to the tail to make it the next victim
133 moveToTail((FALRUBlk*)blk);
134}
135
138{
139 return accessBlock(pkt, lat, 0);
140}
141
144 CachesMask *in_caches_mask)
145{
146 CachesMask mask = 0;
147 FALRUBlk* blk =
148 static_cast<FALRUBlk*>(findBlock({pkt->getAddr(), pkt->isSecure()}));
149
150 // If a cache hit
151 if (blk && blk->isValid()) {
152 mask = blk->inCachesMask;
153
154 moveToHead(blk);
155 }
156
157 if (in_caches_mask) {
158 *in_caches_mask = mask;
159 }
160
161 cacheTracking.recordAccess(blk);
162
163 // The tag lookup latency is the same for a hit or a miss
164 lat = lookupLatency;
165
166 return blk;
167}
168
171{
172 FALRUBlk* blk = nullptr;
173
174 Addr tag = extractTag(lookup.address);
175 auto key = std::make_pair(tag, lookup.secure);
176 auto iter = tagHash.find(key);
177 if (iter != tagHash.end()) {
178 blk = (*iter).second;
179 }
180
181 if (blk && blk->isValid()) {
182 assert(blk->getTag() == tag);
183 assert(blk->isSecure() == lookup.secure);
184 }
185
186 return blk;
187}
188
191{
192 assert(set == 0);
193 return &blks[way];
194}
195
197FALRU::findVictim(const CacheBlk::KeyType& key, const std::size_t size,
198 std::vector<CacheBlk*>& evict_blks,
199 const uint64_t partition_id)
200{
201 // The victim is always stored on the tail for the FALRU
202 FALRUBlk* victim = tail;
203
204 // There is only one eviction for this replacement
205 evict_blks.push_back(victim);
206
207 return victim;
208}
209
210void
212{
213 FALRUBlk* falruBlk = static_cast<FALRUBlk*>(blk);
214
215 // Make sure block is not present in the cache
216 assert(falruBlk->inCachesMask == 0);
217
218 // Do common block insertion functionality
219 BaseTags::insertBlock(pkt, blk);
220
221 // Increment tag counter
222 stats.tagsInUse++;
223
224 // New block is the MRU
225 moveToHead(falruBlk);
226
227 // Insert new block in the hash table
228 tagHash[std::make_pair(blk->getTag(), blk->isSecure())] = falruBlk;
229}
230
231void
233{
234 panic("Moving blocks in FALRU has not been implemented");
235}
236
237void
239{
240 // If block is not already head, do the moving
241 if (blk != head) {
242 cacheTracking.moveBlockToHead(blk);
243 // If block is tail, set previous block as new tail
244 if (blk == tail){
245 assert(blk->next == nullptr);
246 tail = blk->prev;
247 tail->next = nullptr;
248 // Inform block's surrounding blocks that it has been moved
249 } else {
250 blk->prev->next = blk->next;
251 blk->next->prev = blk->prev;
252 }
253
254 // Swap pointers
255 blk->next = head;
256 blk->prev = nullptr;
257 head->prev = blk;
258 head = blk;
259
260 cacheTracking.check(head, tail);
261 }
262}
263
264void
266{
267 // If block is not already tail, do the moving
268 if (blk != tail) {
269 cacheTracking.moveBlockToTail(blk);
270 // If block is head, set next block as new head
271 if (blk == head){
272 assert(blk->prev == nullptr);
273 head = blk->next;
274 head->prev = nullptr;
275 // Inform block's surrounding blocks that it has been moved
276 } else {
277 blk->prev->next = blk->next;
278 blk->next->prev = blk->prev;
279 }
280
281 // Swap pointers
282 blk->prev = tail;
283 blk->next = nullptr;
284 tail->next = blk;
285 tail = blk;
286
287 cacheTracking.check(head, tail);
288 }
289}
290
291void
292printSize(std::ostream &stream, size_t size)
293{
294 static const char *SIZES[] = { "B", "kB", "MB", "GB", "TB", "ZB" };
295 int div = 0;
296 while (size >= 1024 && div < (sizeof SIZES / sizeof *SIZES)) {
297 div++;
298 size >>= 10;
299 }
300 stream << size << SIZES[div];
301}
302
303FALRU::CacheTracking::CacheTracking(unsigned min_size, unsigned max_size,
304 unsigned block_size, statistics::Group *parent)
305 : statistics::Group(parent),
306 blkSize(block_size),
307 minTrackedSize(min_size),
308 numTrackedCaches(max_size > min_size ?
309 floorLog2(max_size) - floorLog2(min_size) : 0),
312 ADD_STAT(hits, statistics::units::Count::get(),
313 "The number of hits in each cache size."),
314 ADD_STAT(misses, statistics::units::Count::get(),
315 "The number of misses in each cache size."),
316 ADD_STAT(accesses, statistics::units::Count::get(),
317 "The number of accesses to the FA LRU cache.")
318{
320 "Not enough bits (%s) in type CachesMask type to keep "
321 "track of %d caches\n", sizeof(CachesMask),
323
324 hits
325 .init(numTrackedCaches + 1);
326 misses
327 .init(numTrackedCaches + 1);
328
329 for (unsigned i = 0; i < numTrackedCaches + 1; ++i) {
330 std::stringstream size_str;
331 printSize(size_str, minTrackedSize << i);
332 hits.subname(i, size_str.str());
333 hits.subdesc(i, "Hits in a " + size_str.str() + " cache");
334 misses.subname(i, size_str.str());
335 misses.subdesc(i, "Misses in a " + size_str.str() + " cache");
336 }
337}
338
339void
341{
342#ifdef FALRU_DEBUG
343 const FALRUBlk* blk = head;
344 unsigned curr_size = 0;
345 unsigned tracked_cache_size = minTrackedSize;
346 CachesMask in_caches_mask = inAllCachesMask;
347 int j = 0;
348
349 while (blk) {
350 panic_if(blk->inCachesMask != in_caches_mask, "Expected cache mask "
351 "%x found %x", blk->inCachesMask, in_caches_mask);
352
353 curr_size += blkSize;
354 if (curr_size == tracked_cache_size && blk != tail) {
355 panic_if(boundaries[j] != blk, "Unexpected boundary for the %d-th "
356 "cache", j);
357 tracked_cache_size <<= 1;
358 // from this point, blocks fit only in the larger caches
359 in_caches_mask &= ~(1U << j);
360 ++j;
361 }
362 blk = blk->next;
363 }
364#endif // FALRU_DEBUG
365}
366
367void
369{
370 // early exit if we are not tracking any extra caches
371 FALRUBlk* blk = numTrackedCaches ? head : nullptr;
372 unsigned curr_size = 0;
373 unsigned tracked_cache_size = minTrackedSize;
374 CachesMask in_caches_mask = inAllCachesMask;
375 int j = 0;
376
377 while (blk) {
378 blk->inCachesMask = in_caches_mask;
379
380 curr_size += blkSize;
381 if (curr_size == tracked_cache_size && blk != tail) {
382 boundaries[j] = blk;
383
384 tracked_cache_size <<= 1;
385 // from this point, blocks fit only in the larger caches
386 in_caches_mask &= ~(1U << j);
387 ++j;
388 }
389 blk = blk->next;
390 }
391}
392
393
394void
396{
397 // Get the mask of all caches, in which the block didn't fit
398 // before moving it to the head
399 CachesMask update_caches_mask = inAllCachesMask ^ blk->inCachesMask;
400
401 for (int i = 0; i < numTrackedCaches; i++) {
402 CachesMask current_cache_mask = 1U << i;
403 if (current_cache_mask & update_caches_mask) {
404 // if the ith cache didn't fit the block (before it is moved to
405 // the head), move the ith boundary 1 block closer to the
406 // MRU
407 boundaries[i]->inCachesMask &= ~current_cache_mask;
408 boundaries[i] = boundaries[i]->prev;
409 } else if (boundaries[i] == blk) {
410 // Make sure the boundary doesn't point to the block
411 // we are about to move
412 boundaries[i] = blk->prev;
413 }
414 }
415
416 // Make block reside in all caches
418}
419
420void
422{
423 CachesMask update_caches_mask = blk->inCachesMask;
424
425 for (int i = 0; i < numTrackedCaches; i++) {
426 CachesMask current_cache_mask = 1U << i;
427 if (current_cache_mask & update_caches_mask) {
428 // if the ith cache fitted the block (before it is moved to
429 // the tail), move the ith boundary 1 block closer to the
430 // LRU
431 boundaries[i] = boundaries[i]->next;
432 if (boundaries[i] == blk) {
433 // Make sure the boundary doesn't point to the block
434 // we are about to move
435 boundaries[i] = blk->next;
436 }
437 boundaries[i]->inCachesMask |= current_cache_mask;
438 }
439 }
440
441 // The block now fits only in the actual cache
442 blk->inCachesMask = 0;
443}
444
445void
447{
448 for (int i = 0; i < numTrackedCaches; i++) {
449 if (blk && ((1U << i) & blk->inCachesMask)) {
450 hits[i]++;
451 } else {
452 misses[i]++;
453 }
454 }
455
456 // Record stats for the actual cache too
457 if (blk && blk->isValid()) {
459 } else {
461 }
462
463 accesses++;
464}
465
466} // 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:63
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:340
void recordAccess(FALRUBlk *blk)
Notify of a block access.
Definition fa_lru.cc:446
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:368
void moveBlockToHead(FALRUBlk *blk)
Update boundaries as a block will be moved to the MRU.
Definition fa_lru.cc:395
void moveBlockToTail(FALRUBlk *blk)
Update boundaries as a block will be moved to the LRU.
Definition fa_lru.cc:421
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:303
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:265
CacheBlk * accessBlock(const PacketPtr pkt, Cycles &lat, CachesMask *in_cache_mask)
Access block and update replacement data.
Definition fa_lru.cc:143
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:68
ReplaceableEntry * findBlockBySetAndWay(int set, int way) const override
Find a block given set and way.
Definition fa_lru.cc:190
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:232
void invalidate(CacheBlk *blk) override
Invalidate a cache block.
Definition fa_lru.cc:117
void moveToHead(FALRUBlk *blk)
Move a cache block to the MRU position.
Definition fa_lru.cc:238
CacheTracking cacheTracking
Definition fa_lru.hh:369
void tagsInit() override
Initialize blocks as FALRUBlk instances.
Definition fa_lru.cc:90
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:211
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:197
CacheBlk * findBlock(const CacheBlk::KeyType &lookup) const override
Find the block in the cache, do not update the replacement data.
Definition fa_lru.cc:170
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
Declares a basic cache interface BaseCache.
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:292

Generated on Mon May 26 2025 09:19:11 for gem5 by doxygen 1.13.2