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

Generated on Wed Sep 30 2020 14:02:12 for gem5 by doxygen 1.8.17