fa_lru.cc revision 12676
12810Srdreslin@umich.edu/* 212665Snikos.nikoleris@arm.com * Copyright (c) 2013,2016-2018 ARM Limited 39796Sprakash.ramrakhyani@arm.com * All rights reserved. 49796Sprakash.ramrakhyani@arm.com * 59796Sprakash.ramrakhyani@arm.com * The license below extends only to copyright in the software and shall 69796Sprakash.ramrakhyani@arm.com * not be construed as granting a license to any other intellectual 79796Sprakash.ramrakhyani@arm.com * property including but not limited to intellectual property relating 89796Sprakash.ramrakhyani@arm.com * to a hardware implementation of the functionality of the software 99796Sprakash.ramrakhyani@arm.com * licensed hereunder. You may use the software subject to the license 109796Sprakash.ramrakhyani@arm.com * terms below provided that you ensure that this notice is replicated 119796Sprakash.ramrakhyani@arm.com * unmodified and in its entirety in all distributions of the software, 129796Sprakash.ramrakhyani@arm.com * modified or unmodified, in source code or in binary form. 139796Sprakash.ramrakhyani@arm.com * 142810Srdreslin@umich.edu * Copyright (c) 2003-2005 The Regents of The University of Michigan 152810Srdreslin@umich.edu * All rights reserved. 162810Srdreslin@umich.edu * 172810Srdreslin@umich.edu * Redistribution and use in source and binary forms, with or without 182810Srdreslin@umich.edu * modification, are permitted provided that the following conditions are 192810Srdreslin@umich.edu * met: redistributions of source code must retain the above copyright 202810Srdreslin@umich.edu * notice, this list of conditions and the following disclaimer; 212810Srdreslin@umich.edu * redistributions in binary form must reproduce the above copyright 222810Srdreslin@umich.edu * notice, this list of conditions and the following disclaimer in the 232810Srdreslin@umich.edu * documentation and/or other materials provided with the distribution; 242810Srdreslin@umich.edu * neither the name of the copyright holders nor the names of its 252810Srdreslin@umich.edu * contributors may be used to endorse or promote products derived from 262810Srdreslin@umich.edu * this software without specific prior written permission. 272810Srdreslin@umich.edu * 282810Srdreslin@umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 292810Srdreslin@umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 302810Srdreslin@umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 312810Srdreslin@umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 322810Srdreslin@umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 332810Srdreslin@umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 342810Srdreslin@umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 352810Srdreslin@umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 362810Srdreslin@umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 372810Srdreslin@umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 382810Srdreslin@umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 392810Srdreslin@umich.edu * 402810Srdreslin@umich.edu * Authors: Erik Hallnor 4112665Snikos.nikoleris@arm.com * Nikos Nikoleris 422810Srdreslin@umich.edu */ 432810Srdreslin@umich.edu 442810Srdreslin@umich.edu/** 452810Srdreslin@umich.edu * @file 462810Srdreslin@umich.edu * Definitions a fully associative LRU tagstore. 472810Srdreslin@umich.edu */ 482810Srdreslin@umich.edu 4911486Snikos.nikoleris@arm.com#include "mem/cache/tags/fa_lru.hh" 5011486Snikos.nikoleris@arm.com 516216Snate@binkert.org#include <cassert> 522810Srdreslin@umich.edu#include <sstream> 532810Srdreslin@umich.edu 542810Srdreslin@umich.edu#include "base/intmath.hh" 5512334Sgabeblack@google.com#include "base/logging.hh" 562810Srdreslin@umich.edu 579796Sprakash.ramrakhyani@arm.comFALRU::FALRU(const Params *p) 5812665Snikos.nikoleris@arm.com : BaseTags(p), 5912665Snikos.nikoleris@arm.com 6012665Snikos.nikoleris@arm.com cacheTracking(p->min_tracked_cache_size, size, blkSize) 612810Srdreslin@umich.edu{ 622810Srdreslin@umich.edu if (!isPowerOf2(blkSize)) 632810Srdreslin@umich.edu fatal("cache block size (in bytes) `%d' must be a power of two", 642810Srdreslin@umich.edu blkSize); 652810Srdreslin@umich.edu if (!isPowerOf2(size)) 662810Srdreslin@umich.edu fatal("Cache Size must be power of 2 for now"); 672810Srdreslin@umich.edu 6812665Snikos.nikoleris@arm.com blks = new FALRUBlk[numBlocks]; 692810Srdreslin@umich.edu 702810Srdreslin@umich.edu head = &(blks[0]); 7111484Snikos.nikoleris@arm.com head->prev = nullptr; 722810Srdreslin@umich.edu head->next = &(blks[1]); 7312665Snikos.nikoleris@arm.com head->set = 0; 7412665Snikos.nikoleris@arm.com head->way = 0; 7512629Sodanrc@yahoo.com.br head->data = &dataBlks[0]; 762810Srdreslin@umich.edu 776978SLisa.Hsu@amd.com for (unsigned i = 1; i < numBlocks - 1; i++) { 782810Srdreslin@umich.edu blks[i].prev = &(blks[i-1]); 792810Srdreslin@umich.edu blks[i].next = &(blks[i+1]); 8010941Sdavid.guillen@arm.com blks[i].set = 0; 8110941Sdavid.guillen@arm.com blks[i].way = i; 8212629Sodanrc@yahoo.com.br 8312629Sodanrc@yahoo.com.br // Associate a data chunk to the block 8412629Sodanrc@yahoo.com.br blks[i].data = &dataBlks[blkSize*i]; 852810Srdreslin@umich.edu } 8612665Snikos.nikoleris@arm.com 8712665Snikos.nikoleris@arm.com tail = &(blks[numBlocks - 1]); 8812665Snikos.nikoleris@arm.com tail->prev = &(blks[numBlocks - 2]); 8912665Snikos.nikoleris@arm.com tail->next = nullptr; 9012665Snikos.nikoleris@arm.com tail->set = 0; 9112665Snikos.nikoleris@arm.com tail->way = numBlocks - 1; 9212665Snikos.nikoleris@arm.com tail->data = &dataBlks[(numBlocks - 1) * blkSize]; 9312665Snikos.nikoleris@arm.com 9412665Snikos.nikoleris@arm.com cacheTracking.init(head, tail); 952810Srdreslin@umich.edu} 962810Srdreslin@umich.edu 979086Sandreas.hansson@arm.comFALRU::~FALRU() 989086Sandreas.hansson@arm.com{ 999086Sandreas.hansson@arm.com delete[] blks; 1009086Sandreas.hansson@arm.com} 1019086Sandreas.hansson@arm.com 1022810Srdreslin@umich.eduvoid 1039796Sprakash.ramrakhyani@arm.comFALRU::regStats() 1042810Srdreslin@umich.edu{ 1059796Sprakash.ramrakhyani@arm.com BaseTags::regStats(); 10612665Snikos.nikoleris@arm.com cacheTracking.regStats(name()); 1072810Srdreslin@umich.edu} 1082810Srdreslin@umich.edu 1092810Srdreslin@umich.eduFALRUBlk * 1102810Srdreslin@umich.eduFALRU::hashLookup(Addr addr) const 1112810Srdreslin@umich.edu{ 1122810Srdreslin@umich.edu tagIterator iter = tagHash.find(addr); 1132810Srdreslin@umich.edu if (iter != tagHash.end()) { 1142810Srdreslin@umich.edu return (*iter).second; 1152810Srdreslin@umich.edu } 11611484Snikos.nikoleris@arm.com return nullptr; 1172810Srdreslin@umich.edu} 1182810Srdreslin@umich.edu 1192810Srdreslin@umich.eduvoid 12010815Sdavid.guillen@arm.comFALRU::invalidate(CacheBlk *blk) 1212810Srdreslin@umich.edu{ 12212566Snikos.nikoleris@arm.com BaseTags::invalidate(blk); 12312636Sodanrc@yahoo.com.br 12412648Sodanrc@yahoo.com.br // Move the block to the tail to make it the next victim 12512648Sodanrc@yahoo.com.br moveToTail((FALRUBlk*)blk); 12612648Sodanrc@yahoo.com.br 12712636Sodanrc@yahoo.com.br // Erase block entry in the hash table 12812636Sodanrc@yahoo.com.br tagHash.erase(blk->tag); 1292810Srdreslin@umich.edu} 1302810Srdreslin@umich.edu 13110815Sdavid.guillen@arm.comCacheBlk* 13211870Snikos.nikoleris@arm.comFALRU::accessBlock(Addr addr, bool is_secure, Cycles &lat) 13310815Sdavid.guillen@arm.com{ 13411870Snikos.nikoleris@arm.com return accessBlock(addr, is_secure, lat, 0); 13510815Sdavid.guillen@arm.com} 13610815Sdavid.guillen@arm.com 13710815Sdavid.guillen@arm.comCacheBlk* 13812665Snikos.nikoleris@arm.comFALRU::accessBlock(Addr addr, bool is_secure, Cycles &lat, 13912665Snikos.nikoleris@arm.com CachesMask *in_caches_mask) 1402810Srdreslin@umich.edu{ 14112665Snikos.nikoleris@arm.com CachesMask mask = 0; 1422810Srdreslin@umich.edu Addr blkAddr = blkAlign(addr); 1432810Srdreslin@umich.edu FALRUBlk* blk = hashLookup(blkAddr); 1442810Srdreslin@umich.edu 1452810Srdreslin@umich.edu if (blk && blk->isValid()) { 14611722Ssophiane.senni@gmail.com // If a cache hit 14711722Ssophiane.senni@gmail.com lat = accessLatency; 14811722Ssophiane.senni@gmail.com // Check if the block to be accessed is available. If not, 14911722Ssophiane.senni@gmail.com // apply the accessLatency on top of block->whenReady. 15011722Ssophiane.senni@gmail.com if (blk->whenReady > curTick() && 15111722Ssophiane.senni@gmail.com cache->ticksToCycles(blk->whenReady - curTick()) > 15211722Ssophiane.senni@gmail.com accessLatency) { 15311722Ssophiane.senni@gmail.com lat = cache->ticksToCycles(blk->whenReady - curTick()) + 15411722Ssophiane.senni@gmail.com accessLatency; 15511722Ssophiane.senni@gmail.com } 1562810Srdreslin@umich.edu assert(blk->tag == blkAddr); 15712665Snikos.nikoleris@arm.com mask = blk->inCachesMask; 15812665Snikos.nikoleris@arm.com moveToHead(blk); 1592810Srdreslin@umich.edu } else { 16011722Ssophiane.senni@gmail.com // If a cache miss 16111722Ssophiane.senni@gmail.com lat = lookupLatency; 16211484Snikos.nikoleris@arm.com blk = nullptr; 1632810Srdreslin@umich.edu } 16412665Snikos.nikoleris@arm.com if (in_caches_mask) { 16512665Snikos.nikoleris@arm.com *in_caches_mask = mask; 1662810Srdreslin@umich.edu } 1672810Srdreslin@umich.edu 16812665Snikos.nikoleris@arm.com cacheTracking.recordAccess(blk); 16912665Snikos.nikoleris@arm.com 1702810Srdreslin@umich.edu return blk; 1712810Srdreslin@umich.edu} 1722810Srdreslin@umich.edu 1732810Srdreslin@umich.edu 17410815Sdavid.guillen@arm.comCacheBlk* 17510028SGiacomo.Gabrielli@arm.comFALRU::findBlock(Addr addr, bool is_secure) const 1762810Srdreslin@umich.edu{ 1772810Srdreslin@umich.edu Addr blkAddr = blkAlign(addr); 1782810Srdreslin@umich.edu FALRUBlk* blk = hashLookup(blkAddr); 1792810Srdreslin@umich.edu 1802810Srdreslin@umich.edu if (blk && blk->isValid()) { 1812810Srdreslin@umich.edu assert(blk->tag == blkAddr); 18212676Sodanrc@yahoo.com.br assert(blk->isSecure() == is_secure); 1832810Srdreslin@umich.edu } else { 18411484Snikos.nikoleris@arm.com blk = nullptr; 1852810Srdreslin@umich.edu } 1862810Srdreslin@umich.edu return blk; 1872810Srdreslin@umich.edu} 1882810Srdreslin@umich.edu 18910815Sdavid.guillen@arm.comCacheBlk* 19010941Sdavid.guillen@arm.comFALRU::findBlockBySetAndWay(int set, int way) const 19110941Sdavid.guillen@arm.com{ 19210941Sdavid.guillen@arm.com assert(set == 0); 19310941Sdavid.guillen@arm.com return &blks[way]; 19410941Sdavid.guillen@arm.com} 19510941Sdavid.guillen@arm.com 19610941Sdavid.guillen@arm.comCacheBlk* 19710048Saminfar@gmail.comFALRU::findVictim(Addr addr) 1982810Srdreslin@umich.edu{ 19912636Sodanrc@yahoo.com.br return tail; 2002810Srdreslin@umich.edu} 2012810Srdreslin@umich.edu 2022810Srdreslin@umich.eduvoid 20310815Sdavid.guillen@arm.comFALRU::insertBlock(PacketPtr pkt, CacheBlk *blk) 2045717Shsul@eecs.umich.edu{ 20512636Sodanrc@yahoo.com.br FALRUBlk* falruBlk = static_cast<FALRUBlk*>(blk); 20612636Sodanrc@yahoo.com.br 20712636Sodanrc@yahoo.com.br // Make sure block is not present in the cache 20812665Snikos.nikoleris@arm.com assert(falruBlk->inCachesMask == 0); 20912636Sodanrc@yahoo.com.br 21012636Sodanrc@yahoo.com.br // Do common block insertion functionality 21112636Sodanrc@yahoo.com.br BaseTags::insertBlock(pkt, blk); 21212636Sodanrc@yahoo.com.br 21312636Sodanrc@yahoo.com.br // New block is the MRU 21412636Sodanrc@yahoo.com.br moveToHead(falruBlk); 21512636Sodanrc@yahoo.com.br 21612636Sodanrc@yahoo.com.br // Insert new block in the hash table 21712636Sodanrc@yahoo.com.br tagHash[falruBlk->tag] = falruBlk; 2185717Shsul@eecs.umich.edu} 2195717Shsul@eecs.umich.edu 2205717Shsul@eecs.umich.eduvoid 2212810Srdreslin@umich.eduFALRU::moveToHead(FALRUBlk *blk) 2222810Srdreslin@umich.edu{ 22312648Sodanrc@yahoo.com.br // If block is not already head, do the moving 22412648Sodanrc@yahoo.com.br if (blk != head) { 22512665Snikos.nikoleris@arm.com cacheTracking.moveBlockToHead(blk); 22612648Sodanrc@yahoo.com.br // If block is tail, set previous block as new tail 2272810Srdreslin@umich.edu if (blk == tail){ 22811484Snikos.nikoleris@arm.com assert(blk->next == nullptr); 2292810Srdreslin@umich.edu tail = blk->prev; 23011484Snikos.nikoleris@arm.com tail->next = nullptr; 23112648Sodanrc@yahoo.com.br // Inform block's surrounding blocks that it has been moved 2322810Srdreslin@umich.edu } else { 2332810Srdreslin@umich.edu blk->prev->next = blk->next; 2342810Srdreslin@umich.edu blk->next->prev = blk->prev; 2352810Srdreslin@umich.edu } 23612648Sodanrc@yahoo.com.br 23712648Sodanrc@yahoo.com.br // Swap pointers 2382810Srdreslin@umich.edu blk->next = head; 23911484Snikos.nikoleris@arm.com blk->prev = nullptr; 2402810Srdreslin@umich.edu head->prev = blk; 2412810Srdreslin@umich.edu head = blk; 24212665Snikos.nikoleris@arm.com 24312665Snikos.nikoleris@arm.com cacheTracking.check(head, tail); 2442810Srdreslin@umich.edu } 2452810Srdreslin@umich.edu} 2462810Srdreslin@umich.edu 24712648Sodanrc@yahoo.com.brvoid 24812648Sodanrc@yahoo.com.brFALRU::moveToTail(FALRUBlk *blk) 24912648Sodanrc@yahoo.com.br{ 25012648Sodanrc@yahoo.com.br // If block is not already tail, do the moving 25112648Sodanrc@yahoo.com.br if (blk != tail) { 25212665Snikos.nikoleris@arm.com cacheTracking.moveBlockToTail(blk); 25312648Sodanrc@yahoo.com.br // If block is head, set next block as new head 25412648Sodanrc@yahoo.com.br if (blk == head){ 25512648Sodanrc@yahoo.com.br assert(blk->prev == nullptr); 25612648Sodanrc@yahoo.com.br head = blk->next; 25712648Sodanrc@yahoo.com.br head->prev = nullptr; 25812648Sodanrc@yahoo.com.br // Inform block's surrounding blocks that it has been moved 25912648Sodanrc@yahoo.com.br } else { 26012648Sodanrc@yahoo.com.br blk->prev->next = blk->next; 26112648Sodanrc@yahoo.com.br blk->next->prev = blk->prev; 26212648Sodanrc@yahoo.com.br } 26312648Sodanrc@yahoo.com.br 26412648Sodanrc@yahoo.com.br // Swap pointers 26512648Sodanrc@yahoo.com.br blk->prev = tail; 26612648Sodanrc@yahoo.com.br blk->next = nullptr; 26712648Sodanrc@yahoo.com.br tail->next = blk; 26812648Sodanrc@yahoo.com.br tail = blk; 26912665Snikos.nikoleris@arm.com 27012665Snikos.nikoleris@arm.com cacheTracking.check(head, tail); 27112648Sodanrc@yahoo.com.br } 27212648Sodanrc@yahoo.com.br} 27312648Sodanrc@yahoo.com.br 2749796Sprakash.ramrakhyani@arm.comFALRU * 2759796Sprakash.ramrakhyani@arm.comFALRUParams::create() 2769796Sprakash.ramrakhyani@arm.com{ 2779796Sprakash.ramrakhyani@arm.com return new FALRU(this); 2789796Sprakash.ramrakhyani@arm.com} 2799796Sprakash.ramrakhyani@arm.com 28012665Snikos.nikoleris@arm.comvoid 28112665Snikos.nikoleris@arm.comFALRU::CacheTracking::check(FALRUBlk *head, FALRUBlk *tail) 28212665Snikos.nikoleris@arm.com{ 28312665Snikos.nikoleris@arm.com#ifdef FALRU_DEBUG 28412665Snikos.nikoleris@arm.com FALRUBlk* blk = head; 28512665Snikos.nikoleris@arm.com unsigned curr_size = 0; 28612665Snikos.nikoleris@arm.com unsigned tracked_cache_size = minTrackedSize; 28712665Snikos.nikoleris@arm.com CachesMask in_caches_mask = inAllCachesMask; 28812665Snikos.nikoleris@arm.com int j = 0; 28912665Snikos.nikoleris@arm.com 29012665Snikos.nikoleris@arm.com while (blk) { 29112665Snikos.nikoleris@arm.com panic_if(blk->inCachesMask != in_caches_mask, "Expected cache mask " 29212665Snikos.nikoleris@arm.com "%x found %x", blk->inCachesMask, in_caches_mask); 29312665Snikos.nikoleris@arm.com 29412665Snikos.nikoleris@arm.com curr_size += blkSize; 29512665Snikos.nikoleris@arm.com if (curr_size == tracked_cache_size && blk != tail) { 29612665Snikos.nikoleris@arm.com panic_if(boundaries[j] != blk, "Unexpected boundary for the %d-th " 29712665Snikos.nikoleris@arm.com "cache", j); 29812665Snikos.nikoleris@arm.com tracked_cache_size <<= 1; 29912665Snikos.nikoleris@arm.com // from this point, blocks fit only in the larger caches 30012665Snikos.nikoleris@arm.com in_caches_mask &= ~(1U << j); 30112665Snikos.nikoleris@arm.com ++j; 30212665Snikos.nikoleris@arm.com } 30312665Snikos.nikoleris@arm.com blk = blk->next; 30412665Snikos.nikoleris@arm.com } 30512665Snikos.nikoleris@arm.com#endif // FALRU_DEBUG 30612665Snikos.nikoleris@arm.com} 30712665Snikos.nikoleris@arm.com 30812665Snikos.nikoleris@arm.comvoid 30912665Snikos.nikoleris@arm.comFALRU::CacheTracking::init(FALRUBlk *head, FALRUBlk *tail) 31012665Snikos.nikoleris@arm.com{ 31112665Snikos.nikoleris@arm.com // early exit if we are not tracking any extra caches 31212665Snikos.nikoleris@arm.com FALRUBlk* blk = numTrackedCaches ? head : nullptr; 31312665Snikos.nikoleris@arm.com unsigned curr_size = 0; 31412665Snikos.nikoleris@arm.com unsigned tracked_cache_size = minTrackedSize; 31512665Snikos.nikoleris@arm.com CachesMask in_caches_mask = inAllCachesMask; 31612665Snikos.nikoleris@arm.com int j = 0; 31712665Snikos.nikoleris@arm.com 31812665Snikos.nikoleris@arm.com while (blk) { 31912665Snikos.nikoleris@arm.com blk->inCachesMask = in_caches_mask; 32012665Snikos.nikoleris@arm.com 32112665Snikos.nikoleris@arm.com curr_size += blkSize; 32212665Snikos.nikoleris@arm.com if (curr_size == tracked_cache_size && blk != tail) { 32312665Snikos.nikoleris@arm.com boundaries[j] = blk; 32412665Snikos.nikoleris@arm.com 32512665Snikos.nikoleris@arm.com tracked_cache_size <<= 1; 32612665Snikos.nikoleris@arm.com // from this point, blocks fit only in the larger caches 32712665Snikos.nikoleris@arm.com in_caches_mask &= ~(1U << j); 32812665Snikos.nikoleris@arm.com ++j; 32912665Snikos.nikoleris@arm.com } 33012665Snikos.nikoleris@arm.com blk = blk->next; 33112665Snikos.nikoleris@arm.com } 33212665Snikos.nikoleris@arm.com} 33312665Snikos.nikoleris@arm.com 33412665Snikos.nikoleris@arm.com 33512665Snikos.nikoleris@arm.comvoid 33612665Snikos.nikoleris@arm.comFALRU::CacheTracking::moveBlockToHead(FALRUBlk *blk) 33712665Snikos.nikoleris@arm.com{ 33812665Snikos.nikoleris@arm.com // Get the mask of all caches, in which the block didn't fit 33912665Snikos.nikoleris@arm.com // before moving it to the head 34012665Snikos.nikoleris@arm.com CachesMask update_caches_mask = inAllCachesMask ^ blk->inCachesMask; 34112665Snikos.nikoleris@arm.com 34212665Snikos.nikoleris@arm.com for (int i = 0; i < numTrackedCaches; i++) { 34312665Snikos.nikoleris@arm.com CachesMask current_cache_mask = 1U << i; 34412665Snikos.nikoleris@arm.com if (current_cache_mask & update_caches_mask) { 34512665Snikos.nikoleris@arm.com // if the ith cache didn't fit the block (before it is moved to 34612665Snikos.nikoleris@arm.com // the head), move the ith boundary 1 block closer to the 34712665Snikos.nikoleris@arm.com // MRU 34812665Snikos.nikoleris@arm.com boundaries[i]->inCachesMask &= ~current_cache_mask; 34912665Snikos.nikoleris@arm.com boundaries[i] = boundaries[i]->prev; 35012665Snikos.nikoleris@arm.com } else if (boundaries[i] == blk) { 35112665Snikos.nikoleris@arm.com // Make sure the boundary doesn't point to the block 35212665Snikos.nikoleris@arm.com // we are about to move 35312665Snikos.nikoleris@arm.com boundaries[i] = blk->prev; 35412665Snikos.nikoleris@arm.com } 35512665Snikos.nikoleris@arm.com } 35612665Snikos.nikoleris@arm.com 35712665Snikos.nikoleris@arm.com // Make block reside in all caches 35812665Snikos.nikoleris@arm.com blk->inCachesMask = inAllCachesMask; 35912665Snikos.nikoleris@arm.com} 36012665Snikos.nikoleris@arm.com 36112665Snikos.nikoleris@arm.comvoid 36212665Snikos.nikoleris@arm.comFALRU::CacheTracking::moveBlockToTail(FALRUBlk *blk) 36312665Snikos.nikoleris@arm.com{ 36412665Snikos.nikoleris@arm.com CachesMask update_caches_mask = blk->inCachesMask; 36512665Snikos.nikoleris@arm.com 36612665Snikos.nikoleris@arm.com for (int i = 0; i < numTrackedCaches; i++) { 36712665Snikos.nikoleris@arm.com CachesMask current_cache_mask = 1U << i; 36812665Snikos.nikoleris@arm.com if (current_cache_mask & update_caches_mask) { 36912665Snikos.nikoleris@arm.com // if the ith cache fitted the block (before it is moved to 37012665Snikos.nikoleris@arm.com // the tail), move the ith boundary 1 block closer to the 37112665Snikos.nikoleris@arm.com // LRU 37212665Snikos.nikoleris@arm.com boundaries[i] = boundaries[i]->next; 37312665Snikos.nikoleris@arm.com if (boundaries[i] == blk) { 37412665Snikos.nikoleris@arm.com // Make sure the boundary doesn't point to the block 37512665Snikos.nikoleris@arm.com // we are about to move 37612665Snikos.nikoleris@arm.com boundaries[i] = blk->next; 37712665Snikos.nikoleris@arm.com } 37812665Snikos.nikoleris@arm.com boundaries[i]->inCachesMask |= current_cache_mask; 37912665Snikos.nikoleris@arm.com } 38012665Snikos.nikoleris@arm.com } 38112665Snikos.nikoleris@arm.com 38212665Snikos.nikoleris@arm.com // The block now fits only in the actual cache 38312665Snikos.nikoleris@arm.com blk->inCachesMask = 0; 38412665Snikos.nikoleris@arm.com} 38512665Snikos.nikoleris@arm.com 38612665Snikos.nikoleris@arm.comvoid 38712665Snikos.nikoleris@arm.comFALRU::CacheTracking::recordAccess(FALRUBlk *blk) 38812665Snikos.nikoleris@arm.com{ 38912665Snikos.nikoleris@arm.com for (int i = 0; i < numTrackedCaches; i++) { 39012665Snikos.nikoleris@arm.com if (blk && ((1U << i) & blk->inCachesMask)) { 39112665Snikos.nikoleris@arm.com hits[i]++; 39212665Snikos.nikoleris@arm.com } else { 39312665Snikos.nikoleris@arm.com misses[i]++; 39412665Snikos.nikoleris@arm.com } 39512665Snikos.nikoleris@arm.com } 39612665Snikos.nikoleris@arm.com 39712665Snikos.nikoleris@arm.com // Record stats for the actual cache too 39812665Snikos.nikoleris@arm.com if (blk) { 39912665Snikos.nikoleris@arm.com hits[numTrackedCaches]++; 40012665Snikos.nikoleris@arm.com } else { 40112665Snikos.nikoleris@arm.com misses[numTrackedCaches]++; 40212665Snikos.nikoleris@arm.com } 40312665Snikos.nikoleris@arm.com 40412665Snikos.nikoleris@arm.com accesses++; 40512665Snikos.nikoleris@arm.com} 40612665Snikos.nikoleris@arm.com 40712665Snikos.nikoleris@arm.comvoid 40812665Snikos.nikoleris@arm.comprintSize(std::ostream &stream, size_t size) 40912665Snikos.nikoleris@arm.com{ 41012665Snikos.nikoleris@arm.com static const char *SIZES[] = { "B", "kB", "MB", "GB", "TB", "ZB" }; 41112665Snikos.nikoleris@arm.com int div = 0; 41212665Snikos.nikoleris@arm.com while (size >= 1024 && div < (sizeof SIZES / sizeof *SIZES)) { 41312665Snikos.nikoleris@arm.com div++; 41412665Snikos.nikoleris@arm.com size >>= 10; 41512665Snikos.nikoleris@arm.com } 41612665Snikos.nikoleris@arm.com stream << size << SIZES[div]; 41712665Snikos.nikoleris@arm.com} 41812665Snikos.nikoleris@arm.com 41912665Snikos.nikoleris@arm.comvoid 42012665Snikos.nikoleris@arm.comFALRU::CacheTracking::regStats(std::string name) 42112665Snikos.nikoleris@arm.com{ 42212665Snikos.nikoleris@arm.com hits 42312665Snikos.nikoleris@arm.com .init(numTrackedCaches + 1) 42412665Snikos.nikoleris@arm.com .name(name + ".falru_hits") 42512665Snikos.nikoleris@arm.com .desc("The number of hits in each cache size.") 42612665Snikos.nikoleris@arm.com ; 42712665Snikos.nikoleris@arm.com misses 42812665Snikos.nikoleris@arm.com .init(numTrackedCaches + 1) 42912665Snikos.nikoleris@arm.com .name(name + ".falru_misses") 43012665Snikos.nikoleris@arm.com .desc("The number of misses in each cache size.") 43112665Snikos.nikoleris@arm.com ; 43212665Snikos.nikoleris@arm.com accesses 43312665Snikos.nikoleris@arm.com .name(name + ".falru_accesses") 43412665Snikos.nikoleris@arm.com .desc("The number of accesses to the FA LRU cache.") 43512665Snikos.nikoleris@arm.com ; 43612665Snikos.nikoleris@arm.com 43712665Snikos.nikoleris@arm.com for (unsigned i = 0; i < numTrackedCaches + 1; ++i) { 43812665Snikos.nikoleris@arm.com std::stringstream size_str; 43912665Snikos.nikoleris@arm.com printSize(size_str, minTrackedSize << i); 44012665Snikos.nikoleris@arm.com hits.subname(i, size_str.str()); 44112665Snikos.nikoleris@arm.com hits.subdesc(i, "Hits in a " + size_str.str() + " cache"); 44212665Snikos.nikoleris@arm.com misses.subname(i, size_str.str()); 44312665Snikos.nikoleris@arm.com misses.subdesc(i, "Misses in a " + size_str.str() + " cache"); 44412665Snikos.nikoleris@arm.com } 44512665Snikos.nikoleris@arm.com} 446