fa_lru.cc revision 12745:e28c117a9806
19646SChris.Emmons@arm.com/* 210839Sandreas.sandberg@arm.com * Copyright (c) 2013,2016-2018 ARM Limited 39646SChris.Emmons@arm.com * All rights reserved. 49646SChris.Emmons@arm.com * 59646SChris.Emmons@arm.com * The license below extends only to copyright in the software and shall 69646SChris.Emmons@arm.com * not be construed as granting a license to any other intellectual 79646SChris.Emmons@arm.com * property including but not limited to intellectual property relating 89646SChris.Emmons@arm.com * to a hardware implementation of the functionality of the software 99646SChris.Emmons@arm.com * licensed hereunder. You may use the software subject to the license 109646SChris.Emmons@arm.com * terms below provided that you ensure that this notice is replicated 119646SChris.Emmons@arm.com * unmodified and in its entirety in all distributions of the software, 129646SChris.Emmons@arm.com * modified or unmodified, in source code or in binary form. 139646SChris.Emmons@arm.com * 149646SChris.Emmons@arm.com * Copyright (c) 2003-2005 The Regents of The University of Michigan 159646SChris.Emmons@arm.com * All rights reserved. 169646SChris.Emmons@arm.com * 179646SChris.Emmons@arm.com * Redistribution and use in source and binary forms, with or without 189646SChris.Emmons@arm.com * modification, are permitted provided that the following conditions are 199646SChris.Emmons@arm.com * met: redistributions of source code must retain the above copyright 209646SChris.Emmons@arm.com * notice, this list of conditions and the following disclaimer; 219646SChris.Emmons@arm.com * redistributions in binary form must reproduce the above copyright 229646SChris.Emmons@arm.com * notice, this list of conditions and the following disclaimer in the 239646SChris.Emmons@arm.com * documentation and/or other materials provided with the distribution; 249646SChris.Emmons@arm.com * neither the name of the copyright holders nor the names of its 259646SChris.Emmons@arm.com * contributors may be used to endorse or promote products derived from 269646SChris.Emmons@arm.com * this software without specific prior written permission. 279646SChris.Emmons@arm.com * 289646SChris.Emmons@arm.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 299646SChris.Emmons@arm.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 309646SChris.Emmons@arm.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 319646SChris.Emmons@arm.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 329646SChris.Emmons@arm.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 339646SChris.Emmons@arm.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 349646SChris.Emmons@arm.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 359646SChris.Emmons@arm.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 369646SChris.Emmons@arm.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 379646SChris.Emmons@arm.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 389646SChris.Emmons@arm.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 399646SChris.Emmons@arm.com * 4010839Sandreas.sandberg@arm.com * Authors: Erik Hallnor 4110839Sandreas.sandberg@arm.com * Nikos Nikoleris 429646SChris.Emmons@arm.com */ 439646SChris.Emmons@arm.com 449646SChris.Emmons@arm.com/** 459646SChris.Emmons@arm.com * @file 469646SChris.Emmons@arm.com * Definitions a fully associative LRU tagstore. 479646SChris.Emmons@arm.com */ 489646SChris.Emmons@arm.com 499646SChris.Emmons@arm.com#include "mem/cache/tags/fa_lru.hh" 509646SChris.Emmons@arm.com 519646SChris.Emmons@arm.com#include <cassert> 529646SChris.Emmons@arm.com#include <sstream> 539646SChris.Emmons@arm.com 549646SChris.Emmons@arm.com#include "base/intmath.hh" 559646SChris.Emmons@arm.com#include "base/logging.hh" 569646SChris.Emmons@arm.com#include "mem/cache/base.hh" 579646SChris.Emmons@arm.com 589646SChris.Emmons@arm.comFALRU::FALRU(const Params *p) 599646SChris.Emmons@arm.com : BaseTags(p), 609646SChris.Emmons@arm.com 619646SChris.Emmons@arm.com cacheTracking(p->min_tracked_cache_size, size, blkSize) 629646SChris.Emmons@arm.com{ 639646SChris.Emmons@arm.com if (!isPowerOf2(blkSize)) 649646SChris.Emmons@arm.com fatal("cache block size (in bytes) `%d' must be a power of two", 659646SChris.Emmons@arm.com blkSize); 6610839Sandreas.sandberg@arm.com if (!isPowerOf2(size)) 6710839Sandreas.sandberg@arm.com fatal("Cache Size must be power of 2 for now"); 689646SChris.Emmons@arm.com 699646SChris.Emmons@arm.com blks = new FALRUBlk[numBlocks]; 7010839Sandreas.sandberg@arm.com 719646SChris.Emmons@arm.com head = &(blks[0]); 729646SChris.Emmons@arm.com head->prev = nullptr; 739646SChris.Emmons@arm.com head->next = &(blks[1]); 749646SChris.Emmons@arm.com head->set = 0; 759646SChris.Emmons@arm.com head->way = 0; 769939Sdam.sunwoo@arm.com head->data = &dataBlks[0]; 7710840Sandreas.sandberg@arm.com 7810840Sandreas.sandberg@arm.com for (unsigned i = 1; i < numBlocks - 1; i++) { 799646SChris.Emmons@arm.com blks[i].prev = &(blks[i-1]); 809646SChris.Emmons@arm.com blks[i].next = &(blks[i+1]); 819646SChris.Emmons@arm.com blks[i].set = 0; 829646SChris.Emmons@arm.com blks[i].way = i; 839646SChris.Emmons@arm.com 849646SChris.Emmons@arm.com // Associate a data chunk to the block 859646SChris.Emmons@arm.com blks[i].data = &dataBlks[blkSize*i]; 8610839Sandreas.sandberg@arm.com } 879646SChris.Emmons@arm.com 889646SChris.Emmons@arm.com tail = &(blks[numBlocks - 1]); 899646SChris.Emmons@arm.com tail->prev = &(blks[numBlocks - 2]); 909646SChris.Emmons@arm.com tail->next = nullptr; 919646SChris.Emmons@arm.com tail->set = 0; 929646SChris.Emmons@arm.com tail->way = numBlocks - 1; 939646SChris.Emmons@arm.com tail->data = &dataBlks[(numBlocks - 1) * blkSize]; 949646SChris.Emmons@arm.com 959646SChris.Emmons@arm.com cacheTracking.init(head, tail); 969646SChris.Emmons@arm.com} 979646SChris.Emmons@arm.com 989646SChris.Emmons@arm.comFALRU::~FALRU() 999646SChris.Emmons@arm.com{ 1009646SChris.Emmons@arm.com delete[] blks; 1019646SChris.Emmons@arm.com} 1029646SChris.Emmons@arm.com 1039646SChris.Emmons@arm.comvoid 1049646SChris.Emmons@arm.comFALRU::regStats() 1059646SChris.Emmons@arm.com{ 1069646SChris.Emmons@arm.com BaseTags::regStats(); 1079646SChris.Emmons@arm.com cacheTracking.regStats(name()); 1089646SChris.Emmons@arm.com} 1099646SChris.Emmons@arm.com 1109646SChris.Emmons@arm.comFALRUBlk * 1119646SChris.Emmons@arm.comFALRU::hashLookup(Addr addr) const 1129646SChris.Emmons@arm.com{ 1139646SChris.Emmons@arm.com tagIterator iter = tagHash.find(addr); 1149646SChris.Emmons@arm.com if (iter != tagHash.end()) { 1159646SChris.Emmons@arm.com return (*iter).second; 1169646SChris.Emmons@arm.com } 1179646SChris.Emmons@arm.com return nullptr; 1189646SChris.Emmons@arm.com} 1199646SChris.Emmons@arm.com 1209646SChris.Emmons@arm.comvoid 1219646SChris.Emmons@arm.comFALRU::invalidate(CacheBlk *blk) 1229646SChris.Emmons@arm.com{ 1239646SChris.Emmons@arm.com BaseTags::invalidate(blk); 1249646SChris.Emmons@arm.com 1259646SChris.Emmons@arm.com // Decrease the number of tags in use 1269646SChris.Emmons@arm.com tagsInUse--; 1279646SChris.Emmons@arm.com 1289646SChris.Emmons@arm.com // Move the block to the tail to make it the next victim 1299646SChris.Emmons@arm.com moveToTail((FALRUBlk*)blk); 1309646SChris.Emmons@arm.com 1319646SChris.Emmons@arm.com // Erase block entry in the hash table 1329646SChris.Emmons@arm.com tagHash.erase(blk->tag); 1339646SChris.Emmons@arm.com} 1349646SChris.Emmons@arm.com 1359646SChris.Emmons@arm.comCacheBlk* 1369646SChris.Emmons@arm.comFALRU::accessBlock(Addr addr, bool is_secure, Cycles &lat) 1379646SChris.Emmons@arm.com{ 1389646SChris.Emmons@arm.com return accessBlock(addr, is_secure, lat, 0); 1399646SChris.Emmons@arm.com} 1409646SChris.Emmons@arm.com 1419646SChris.Emmons@arm.comCacheBlk* 1429646SChris.Emmons@arm.comFALRU::accessBlock(Addr addr, bool is_secure, Cycles &lat, 1439646SChris.Emmons@arm.com CachesMask *in_caches_mask) 1449646SChris.Emmons@arm.com{ 1459646SChris.Emmons@arm.com CachesMask mask = 0; 1469646SChris.Emmons@arm.com FALRUBlk* blk = static_cast<FALRUBlk*>(findBlock(addr, is_secure)); 1479646SChris.Emmons@arm.com 1489646SChris.Emmons@arm.com if (blk != nullptr) { 1499646SChris.Emmons@arm.com // If a cache hit 1509646SChris.Emmons@arm.com lat = accessLatency; 1519646SChris.Emmons@arm.com // Check if the block to be accessed is available. If not, 1529646SChris.Emmons@arm.com // apply the accessLatency on top of block->whenReady. 1539646SChris.Emmons@arm.com if (blk->whenReady > curTick() && 1549646SChris.Emmons@arm.com cache->ticksToCycles(blk->whenReady - curTick()) > 1559646SChris.Emmons@arm.com accessLatency) { 1569646SChris.Emmons@arm.com lat = cache->ticksToCycles(blk->whenReady - curTick()) + 1579646SChris.Emmons@arm.com accessLatency; 1589646SChris.Emmons@arm.com } 1599646SChris.Emmons@arm.com mask = blk->inCachesMask; 1609646SChris.Emmons@arm.com 1619646SChris.Emmons@arm.com moveToHead(blk); 1629646SChris.Emmons@arm.com } else { 1639646SChris.Emmons@arm.com // If a cache miss 1649646SChris.Emmons@arm.com lat = lookupLatency; 1659646SChris.Emmons@arm.com } 1669646SChris.Emmons@arm.com if (in_caches_mask) { 1679646SChris.Emmons@arm.com *in_caches_mask = mask; 1689646SChris.Emmons@arm.com } 1699646SChris.Emmons@arm.com 1709646SChris.Emmons@arm.com cacheTracking.recordAccess(blk); 1719646SChris.Emmons@arm.com 1729646SChris.Emmons@arm.com return blk; 1739646SChris.Emmons@arm.com} 1749646SChris.Emmons@arm.com 1759646SChris.Emmons@arm.comCacheBlk* 1769646SChris.Emmons@arm.comFALRU::findBlock(Addr addr, bool is_secure) const 1779646SChris.Emmons@arm.com{ 1789646SChris.Emmons@arm.com Addr tag = extractTag(addr); 1799646SChris.Emmons@arm.com FALRUBlk* blk = hashLookup(tag); 1809646SChris.Emmons@arm.com 1819646SChris.Emmons@arm.com if (blk && blk->isValid()) { 1829646SChris.Emmons@arm.com assert(blk->tag == tag); 1839646SChris.Emmons@arm.com assert(blk->isSecure() == is_secure); 1849646SChris.Emmons@arm.com } else { 1859646SChris.Emmons@arm.com blk = nullptr; 1869646SChris.Emmons@arm.com } 1879646SChris.Emmons@arm.com return blk; 1889646SChris.Emmons@arm.com} 1899646SChris.Emmons@arm.com 1909646SChris.Emmons@arm.comReplaceableEntry* 1919646SChris.Emmons@arm.comFALRU::findBlockBySetAndWay(int set, int way) const 1929646SChris.Emmons@arm.com{ 1939646SChris.Emmons@arm.com assert(set == 0); 1949646SChris.Emmons@arm.com return &blks[way]; 1959646SChris.Emmons@arm.com} 1969646SChris.Emmons@arm.com 1979646SChris.Emmons@arm.comCacheBlk* 1989646SChris.Emmons@arm.comFALRU::findVictim(Addr addr, std::vector<CacheBlk*>& evict_blks) const 1999646SChris.Emmons@arm.com{ 2009646SChris.Emmons@arm.com // The victim is always stored on the tail for the FALRU 2019646SChris.Emmons@arm.com FALRUBlk* victim = tail; 2029646SChris.Emmons@arm.com 2039646SChris.Emmons@arm.com // There is only one eviction for this replacement 2049646SChris.Emmons@arm.com evict_blks.push_back(victim); 2059646SChris.Emmons@arm.com 2069646SChris.Emmons@arm.com return victim; 2079646SChris.Emmons@arm.com} 2089646SChris.Emmons@arm.com 2099646SChris.Emmons@arm.comvoid 2109646SChris.Emmons@arm.comFALRU::insertBlock(PacketPtr pkt, CacheBlk *blk) 2119646SChris.Emmons@arm.com{ 2129646SChris.Emmons@arm.com FALRUBlk* falruBlk = static_cast<FALRUBlk*>(blk); 2139646SChris.Emmons@arm.com 2149646SChris.Emmons@arm.com // Make sure block is not present in the cache 2159646SChris.Emmons@arm.com assert(falruBlk->inCachesMask == 0); 2169646SChris.Emmons@arm.com 2179646SChris.Emmons@arm.com // Do common block insertion functionality 2189646SChris.Emmons@arm.com BaseTags::insertBlock(pkt, blk); 2199646SChris.Emmons@arm.com 2209646SChris.Emmons@arm.com // Increment tag counter 2219646SChris.Emmons@arm.com tagsInUse++; 2229646SChris.Emmons@arm.com 2239646SChris.Emmons@arm.com // New block is the MRU 2249646SChris.Emmons@arm.com moveToHead(falruBlk); 2259646SChris.Emmons@arm.com 2269646SChris.Emmons@arm.com // Insert new block in the hash table 2279646SChris.Emmons@arm.com tagHash[falruBlk->tag] = falruBlk; 2289646SChris.Emmons@arm.com} 2299646SChris.Emmons@arm.com 2309646SChris.Emmons@arm.comvoid 2319646SChris.Emmons@arm.comFALRU::moveToHead(FALRUBlk *blk) 2329646SChris.Emmons@arm.com{ 2339646SChris.Emmons@arm.com // If block is not already head, do the moving 2349646SChris.Emmons@arm.com if (blk != head) { 2359646SChris.Emmons@arm.com cacheTracking.moveBlockToHead(blk); 2369646SChris.Emmons@arm.com // If block is tail, set previous block as new tail 2379646SChris.Emmons@arm.com if (blk == tail){ 2389646SChris.Emmons@arm.com assert(blk->next == nullptr); 2399646SChris.Emmons@arm.com tail = blk->prev; 2409646SChris.Emmons@arm.com tail->next = nullptr; 2419646SChris.Emmons@arm.com // Inform block's surrounding blocks that it has been moved 2429646SChris.Emmons@arm.com } else { 2439646SChris.Emmons@arm.com blk->prev->next = blk->next; 2449646SChris.Emmons@arm.com blk->next->prev = blk->prev; 2459646SChris.Emmons@arm.com } 2469646SChris.Emmons@arm.com 2479646SChris.Emmons@arm.com // Swap pointers 2489646SChris.Emmons@arm.com blk->next = head; 2499646SChris.Emmons@arm.com blk->prev = nullptr; 2509646SChris.Emmons@arm.com head->prev = blk; 2519646SChris.Emmons@arm.com head = blk; 2529646SChris.Emmons@arm.com 2539646SChris.Emmons@arm.com cacheTracking.check(head, tail); 2549646SChris.Emmons@arm.com } 2559646SChris.Emmons@arm.com} 2569646SChris.Emmons@arm.com 2579646SChris.Emmons@arm.comvoid 2589646SChris.Emmons@arm.comFALRU::moveToTail(FALRUBlk *blk) 2599646SChris.Emmons@arm.com{ 2609646SChris.Emmons@arm.com // If block is not already tail, do the moving 2619646SChris.Emmons@arm.com if (blk != tail) { 2629646SChris.Emmons@arm.com cacheTracking.moveBlockToTail(blk); 2639646SChris.Emmons@arm.com // If block is head, set next block as new head 2649646SChris.Emmons@arm.com if (blk == head){ 2659646SChris.Emmons@arm.com assert(blk->prev == nullptr); 2669646SChris.Emmons@arm.com head = blk->next; 2679646SChris.Emmons@arm.com head->prev = nullptr; 2689646SChris.Emmons@arm.com // Inform block's surrounding blocks that it has been moved 2699646SChris.Emmons@arm.com } else { 2709646SChris.Emmons@arm.com blk->prev->next = blk->next; 2719646SChris.Emmons@arm.com blk->next->prev = blk->prev; 2729646SChris.Emmons@arm.com } 2739646SChris.Emmons@arm.com 2749646SChris.Emmons@arm.com // Swap pointers 2759646SChris.Emmons@arm.com blk->prev = tail; 2769646SChris.Emmons@arm.com blk->next = nullptr; 2779646SChris.Emmons@arm.com tail->next = blk; 2789646SChris.Emmons@arm.com tail = blk; 2799646SChris.Emmons@arm.com 2809646SChris.Emmons@arm.com cacheTracking.check(head, tail); 2819646SChris.Emmons@arm.com } 2829646SChris.Emmons@arm.com} 2839646SChris.Emmons@arm.com 2849648Sdam.sunwoo@arm.comFALRU * 2859646SChris.Emmons@arm.comFALRUParams::create() 2869646SChris.Emmons@arm.com{ 2879646SChris.Emmons@arm.com return new FALRU(this); 2889646SChris.Emmons@arm.com} 2899646SChris.Emmons@arm.com 2909646SChris.Emmons@arm.comvoid 2919646SChris.Emmons@arm.comFALRU::CacheTracking::check(FALRUBlk *head, FALRUBlk *tail) 2929646SChris.Emmons@arm.com{ 2939646SChris.Emmons@arm.com#ifdef FALRU_DEBUG 2949646SChris.Emmons@arm.com FALRUBlk* blk = head; 2959646SChris.Emmons@arm.com unsigned curr_size = 0; 2969646SChris.Emmons@arm.com unsigned tracked_cache_size = minTrackedSize; 2979646SChris.Emmons@arm.com CachesMask in_caches_mask = inAllCachesMask; 2989646SChris.Emmons@arm.com int j = 0; 2999646SChris.Emmons@arm.com 3009646SChris.Emmons@arm.com while (blk) { 3019646SChris.Emmons@arm.com panic_if(blk->inCachesMask != in_caches_mask, "Expected cache mask " 3029646SChris.Emmons@arm.com "%x found %x", blk->inCachesMask, in_caches_mask); 3039646SChris.Emmons@arm.com 3049646SChris.Emmons@arm.com curr_size += blkSize; 3059646SChris.Emmons@arm.com if (curr_size == tracked_cache_size && blk != tail) { 3069646SChris.Emmons@arm.com panic_if(boundaries[j] != blk, "Unexpected boundary for the %d-th " 3079646SChris.Emmons@arm.com "cache", j); 3089646SChris.Emmons@arm.com tracked_cache_size <<= 1; 3099646SChris.Emmons@arm.com // from this point, blocks fit only in the larger caches 3109646SChris.Emmons@arm.com in_caches_mask &= ~(1U << j); 3119646SChris.Emmons@arm.com ++j; 3129646SChris.Emmons@arm.com } 3139646SChris.Emmons@arm.com blk = blk->next; 3149646SChris.Emmons@arm.com } 3159646SChris.Emmons@arm.com#endif // FALRU_DEBUG 3169646SChris.Emmons@arm.com} 3179646SChris.Emmons@arm.com 31810839Sandreas.sandberg@arm.comvoid 31910839Sandreas.sandberg@arm.comFALRU::CacheTracking::init(FALRUBlk *head, FALRUBlk *tail) 32010839Sandreas.sandberg@arm.com{ 32110839Sandreas.sandberg@arm.com // early exit if we are not tracking any extra caches 32210839Sandreas.sandberg@arm.com FALRUBlk* blk = numTrackedCaches ? head : nullptr; 32310839Sandreas.sandberg@arm.com unsigned curr_size = 0; 32410839Sandreas.sandberg@arm.com unsigned tracked_cache_size = minTrackedSize; 32510839Sandreas.sandberg@arm.com CachesMask in_caches_mask = inAllCachesMask; 3269646SChris.Emmons@arm.com int j = 0; 3279646SChris.Emmons@arm.com 3289646SChris.Emmons@arm.com while (blk) { 3299646SChris.Emmons@arm.com blk->inCachesMask = in_caches_mask; 3309646SChris.Emmons@arm.com 3319646SChris.Emmons@arm.com curr_size += blkSize; 3329646SChris.Emmons@arm.com if (curr_size == tracked_cache_size && blk != tail) { 3339646SChris.Emmons@arm.com boundaries[j] = blk; 3349646SChris.Emmons@arm.com 3359646SChris.Emmons@arm.com tracked_cache_size <<= 1; 3369646SChris.Emmons@arm.com // from this point, blocks fit only in the larger caches 33710839Sandreas.sandberg@arm.com in_caches_mask &= ~(1U << j); 33810839Sandreas.sandberg@arm.com ++j; 33910839Sandreas.sandberg@arm.com } 34010839Sandreas.sandberg@arm.com blk = blk->next; 34110839Sandreas.sandberg@arm.com } 34210839Sandreas.sandberg@arm.com} 34310839Sandreas.sandberg@arm.com 3449646SChris.Emmons@arm.com 3459646SChris.Emmons@arm.comvoid 3469646SChris.Emmons@arm.comFALRU::CacheTracking::moveBlockToHead(FALRUBlk *blk) 3479646SChris.Emmons@arm.com{ 3489646SChris.Emmons@arm.com // Get the mask of all caches, in which the block didn't fit 3499646SChris.Emmons@arm.com // before moving it to the head 3509646SChris.Emmons@arm.com CachesMask update_caches_mask = inAllCachesMask ^ blk->inCachesMask; 3519646SChris.Emmons@arm.com 3529646SChris.Emmons@arm.com for (int i = 0; i < numTrackedCaches; i++) { 3539646SChris.Emmons@arm.com CachesMask current_cache_mask = 1U << i; 3549646SChris.Emmons@arm.com if (current_cache_mask & update_caches_mask) { 3559646SChris.Emmons@arm.com // if the ith cache didn't fit the block (before it is moved to 3569646SChris.Emmons@arm.com // the head), move the ith boundary 1 block closer to the 3579646SChris.Emmons@arm.com // MRU 3589646SChris.Emmons@arm.com boundaries[i]->inCachesMask &= ~current_cache_mask; 35910839Sandreas.sandberg@arm.com boundaries[i] = boundaries[i]->prev; 3609646SChris.Emmons@arm.com } else if (boundaries[i] == blk) { 3619646SChris.Emmons@arm.com // Make sure the boundary doesn't point to the block 3629646SChris.Emmons@arm.com // we are about to move 3639646SChris.Emmons@arm.com boundaries[i] = blk->prev; 3649646SChris.Emmons@arm.com } 3659646SChris.Emmons@arm.com } 3669646SChris.Emmons@arm.com 3679646SChris.Emmons@arm.com // Make block reside in all caches 3689646SChris.Emmons@arm.com blk->inCachesMask = inAllCachesMask; 3699646SChris.Emmons@arm.com} 3709646SChris.Emmons@arm.com 3719646SChris.Emmons@arm.comvoid 3729646SChris.Emmons@arm.comFALRU::CacheTracking::moveBlockToTail(FALRUBlk *blk) 3739646SChris.Emmons@arm.com{ 3749646SChris.Emmons@arm.com CachesMask update_caches_mask = blk->inCachesMask; 3759646SChris.Emmons@arm.com 3769646SChris.Emmons@arm.com for (int i = 0; i < numTrackedCaches; i++) { 3779646SChris.Emmons@arm.com CachesMask current_cache_mask = 1U << i; 3789646SChris.Emmons@arm.com if (current_cache_mask & update_caches_mask) { 37910839Sandreas.sandberg@arm.com // if the ith cache fitted the block (before it is moved to 3809646SChris.Emmons@arm.com // the tail), move the ith boundary 1 block closer to the 3819646SChris.Emmons@arm.com // LRU 3829646SChris.Emmons@arm.com boundaries[i] = boundaries[i]->next; 3839646SChris.Emmons@arm.com if (boundaries[i] == blk) { 3849646SChris.Emmons@arm.com // Make sure the boundary doesn't point to the block 3859646SChris.Emmons@arm.com // we are about to move 3869646SChris.Emmons@arm.com boundaries[i] = blk->next; 3879646SChris.Emmons@arm.com } 3889646SChris.Emmons@arm.com boundaries[i]->inCachesMask |= current_cache_mask; 3899646SChris.Emmons@arm.com } 3909646SChris.Emmons@arm.com } 3919646SChris.Emmons@arm.com 3929646SChris.Emmons@arm.com // The block now fits only in the actual cache 3939646SChris.Emmons@arm.com blk->inCachesMask = 0; 3949646SChris.Emmons@arm.com} 3959646SChris.Emmons@arm.com 3969646SChris.Emmons@arm.comvoid 3979646SChris.Emmons@arm.comFALRU::CacheTracking::recordAccess(FALRUBlk *blk) 3989646SChris.Emmons@arm.com{ 3999646SChris.Emmons@arm.com for (int i = 0; i < numTrackedCaches; i++) { 4009646SChris.Emmons@arm.com if (blk && ((1U << i) & blk->inCachesMask)) { 4019646SChris.Emmons@arm.com hits[i]++; 4029646SChris.Emmons@arm.com } else { 4039646SChris.Emmons@arm.com misses[i]++; 4049646SChris.Emmons@arm.com } 4059646SChris.Emmons@arm.com } 4069646SChris.Emmons@arm.com 4079646SChris.Emmons@arm.com // Record stats for the actual cache too 4089646SChris.Emmons@arm.com if (blk) { 4099646SChris.Emmons@arm.com hits[numTrackedCaches]++; 4109646SChris.Emmons@arm.com } else { 4119646SChris.Emmons@arm.com misses[numTrackedCaches]++; 4129646SChris.Emmons@arm.com } 4139646SChris.Emmons@arm.com 4149646SChris.Emmons@arm.com accesses++; 4159646SChris.Emmons@arm.com} 4169646SChris.Emmons@arm.com 4179646SChris.Emmons@arm.comvoid 4189646SChris.Emmons@arm.comprintSize(std::ostream &stream, size_t size) 4199646SChris.Emmons@arm.com{ 4209646SChris.Emmons@arm.com static const char *SIZES[] = { "B", "kB", "MB", "GB", "TB", "ZB" }; 4219646SChris.Emmons@arm.com int div = 0; 4229646SChris.Emmons@arm.com while (size >= 1024 && div < (sizeof SIZES / sizeof *SIZES)) { 4239646SChris.Emmons@arm.com div++; 4249646SChris.Emmons@arm.com size >>= 10; 4259646SChris.Emmons@arm.com } 4269646SChris.Emmons@arm.com stream << size << SIZES[div]; 4279646SChris.Emmons@arm.com} 4289646SChris.Emmons@arm.com 4299646SChris.Emmons@arm.comvoid 4309646SChris.Emmons@arm.comFALRU::CacheTracking::regStats(std::string name) 4319646SChris.Emmons@arm.com{ 4329646SChris.Emmons@arm.com hits 4339646SChris.Emmons@arm.com .init(numTrackedCaches + 1) 4349646SChris.Emmons@arm.com .name(name + ".falru_hits") 4359646SChris.Emmons@arm.com .desc("The number of hits in each cache size.") 4369646SChris.Emmons@arm.com ; 4379646SChris.Emmons@arm.com misses 4389646SChris.Emmons@arm.com .init(numTrackedCaches + 1) 43910839Sandreas.sandberg@arm.com .name(name + ".falru_misses") 44010839Sandreas.sandberg@arm.com .desc("The number of misses in each cache size.") 4419646SChris.Emmons@arm.com ; 4429646SChris.Emmons@arm.com accesses 44310839Sandreas.sandberg@arm.com .name(name + ".falru_accesses") 4449646SChris.Emmons@arm.com .desc("The number of accesses to the FA LRU cache.") 4459646SChris.Emmons@arm.com ; 4469646SChris.Emmons@arm.com 4479646SChris.Emmons@arm.com for (unsigned i = 0; i < numTrackedCaches + 1; ++i) { 4489646SChris.Emmons@arm.com std::stringstream size_str; 4499646SChris.Emmons@arm.com printSize(size_str, minTrackedSize << i); 4509646SChris.Emmons@arm.com hits.subname(i, size_str.str()); 4519646SChris.Emmons@arm.com hits.subdesc(i, "Hits in a " + size_str.str() + " cache"); 4529646SChris.Emmons@arm.com misses.subname(i, size_str.str()); 4539646SChris.Emmons@arm.com misses.subdesc(i, "Misses in a " + size_str.str() + " cache"); 4549646SChris.Emmons@arm.com } 4559646SChris.Emmons@arm.com} 4569646SChris.Emmons@arm.com