12810Srdreslin@umich.edu/* 213165Sodanrc@yahoo.com.br * Copyright (c) 2018 Inria 312665Snikos.nikoleris@arm.com * Copyright (c) 2013,2016-2018 ARM Limited 49796Sprakash.ramrakhyani@arm.com * All rights reserved. 59796Sprakash.ramrakhyani@arm.com * 69796Sprakash.ramrakhyani@arm.com * The license below extends only to copyright in the software and shall 79796Sprakash.ramrakhyani@arm.com * not be construed as granting a license to any other intellectual 89796Sprakash.ramrakhyani@arm.com * property including but not limited to intellectual property relating 99796Sprakash.ramrakhyani@arm.com * to a hardware implementation of the functionality of the software 109796Sprakash.ramrakhyani@arm.com * licensed hereunder. You may use the software subject to the license 119796Sprakash.ramrakhyani@arm.com * terms below provided that you ensure that this notice is replicated 129796Sprakash.ramrakhyani@arm.com * unmodified and in its entirety in all distributions of the software, 139796Sprakash.ramrakhyani@arm.com * modified or unmodified, in source code or in binary form. 149796Sprakash.ramrakhyani@arm.com * 152810Srdreslin@umich.edu * Copyright (c) 2003-2005 The Regents of The University of Michigan 162810Srdreslin@umich.edu * All rights reserved. 172810Srdreslin@umich.edu * 182810Srdreslin@umich.edu * Redistribution and use in source and binary forms, with or without 192810Srdreslin@umich.edu * modification, are permitted provided that the following conditions are 202810Srdreslin@umich.edu * met: redistributions of source code must retain the above copyright 212810Srdreslin@umich.edu * notice, this list of conditions and the following disclaimer; 222810Srdreslin@umich.edu * redistributions in binary form must reproduce the above copyright 232810Srdreslin@umich.edu * notice, this list of conditions and the following disclaimer in the 242810Srdreslin@umich.edu * documentation and/or other materials provided with the distribution; 252810Srdreslin@umich.edu * neither the name of the copyright holders nor the names of its 262810Srdreslin@umich.edu * contributors may be used to endorse or promote products derived from 272810Srdreslin@umich.edu * this software without specific prior written permission. 282810Srdreslin@umich.edu * 292810Srdreslin@umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 302810Srdreslin@umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 312810Srdreslin@umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 322810Srdreslin@umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 332810Srdreslin@umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 342810Srdreslin@umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 352810Srdreslin@umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 362810Srdreslin@umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 372810Srdreslin@umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 382810Srdreslin@umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 392810Srdreslin@umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 402810Srdreslin@umich.edu * 412810Srdreslin@umich.edu * Authors: Erik Hallnor 4212665Snikos.nikoleris@arm.com * Nikos Nikoleris 4313165Sodanrc@yahoo.com.br * Daniel Carvalho 442810Srdreslin@umich.edu */ 452810Srdreslin@umich.edu 462810Srdreslin@umich.edu/** 472810Srdreslin@umich.edu * @file 482810Srdreslin@umich.edu * Definitions a fully associative LRU tagstore. 492810Srdreslin@umich.edu */ 502810Srdreslin@umich.edu 5111486Snikos.nikoleris@arm.com#include "mem/cache/tags/fa_lru.hh" 5211486Snikos.nikoleris@arm.com 536216Snate@binkert.org#include <cassert> 542810Srdreslin@umich.edu#include <sstream> 552810Srdreslin@umich.edu 562810Srdreslin@umich.edu#include "base/intmath.hh" 5712334Sgabeblack@google.com#include "base/logging.hh" 5812727Snikos.nikoleris@arm.com#include "mem/cache/base.hh" 5913225Sodanrc@yahoo.com.br#include "mem/cache/replacement_policies/replaceable_entry.hh" 602810Srdreslin@umich.edu 6113222Sodanrc@yahoo.com.brstd::string 6213222Sodanrc@yahoo.com.brFALRUBlk::print() const 6313222Sodanrc@yahoo.com.br{ 6413222Sodanrc@yahoo.com.br return csprintf("%s inCachesMask: %#x", CacheBlk::print(), inCachesMask); 6513222Sodanrc@yahoo.com.br} 6613222Sodanrc@yahoo.com.br 679796Sprakash.ramrakhyani@arm.comFALRU::FALRU(const Params *p) 6812665Snikos.nikoleris@arm.com : BaseTags(p), 6912665Snikos.nikoleris@arm.com 7012665Snikos.nikoleris@arm.com cacheTracking(p->min_tracked_cache_size, size, blkSize) 712810Srdreslin@umich.edu{ 722810Srdreslin@umich.edu if (!isPowerOf2(blkSize)) 732810Srdreslin@umich.edu fatal("cache block size (in bytes) `%d' must be a power of two", 742810Srdreslin@umich.edu blkSize); 752810Srdreslin@umich.edu if (!isPowerOf2(size)) 762810Srdreslin@umich.edu fatal("Cache Size must be power of 2 for now"); 772810Srdreslin@umich.edu 7812665Snikos.nikoleris@arm.com blks = new FALRUBlk[numBlocks]; 7913216Sodanrc@yahoo.com.br} 8013216Sodanrc@yahoo.com.br 8113216Sodanrc@yahoo.com.brFALRU::~FALRU() 8213216Sodanrc@yahoo.com.br{ 8313216Sodanrc@yahoo.com.br delete[] blks; 8413216Sodanrc@yahoo.com.br} 8513216Sodanrc@yahoo.com.br 8613216Sodanrc@yahoo.com.brvoid 8713419Sodanrc@yahoo.com.brFALRU::tagsInit() 8813216Sodanrc@yahoo.com.br{ 892810Srdreslin@umich.edu head = &(blks[0]); 9011484Snikos.nikoleris@arm.com head->prev = nullptr; 912810Srdreslin@umich.edu head->next = &(blks[1]); 9213218Sodanrc@yahoo.com.br head->setPosition(0, 0); 9312629Sodanrc@yahoo.com.br head->data = &dataBlks[0]; 942810Srdreslin@umich.edu 956978SLisa.Hsu@amd.com for (unsigned i = 1; i < numBlocks - 1; i++) { 962810Srdreslin@umich.edu blks[i].prev = &(blks[i-1]); 972810Srdreslin@umich.edu blks[i].next = &(blks[i+1]); 9813218Sodanrc@yahoo.com.br blks[i].setPosition(0, i); 9912629Sodanrc@yahoo.com.br 10012629Sodanrc@yahoo.com.br // Associate a data chunk to the block 10112629Sodanrc@yahoo.com.br blks[i].data = &dataBlks[blkSize*i]; 1022810Srdreslin@umich.edu } 10312665Snikos.nikoleris@arm.com 10412665Snikos.nikoleris@arm.com tail = &(blks[numBlocks - 1]); 10512665Snikos.nikoleris@arm.com tail->prev = &(blks[numBlocks - 2]); 10612665Snikos.nikoleris@arm.com tail->next = nullptr; 10713218Sodanrc@yahoo.com.br tail->setPosition(0, numBlocks - 1); 10812665Snikos.nikoleris@arm.com tail->data = &dataBlks[(numBlocks - 1) * blkSize]; 10912665Snikos.nikoleris@arm.com 11012665Snikos.nikoleris@arm.com cacheTracking.init(head, tail); 1112810Srdreslin@umich.edu} 1122810Srdreslin@umich.edu 1132810Srdreslin@umich.eduvoid 1149796Sprakash.ramrakhyani@arm.comFALRU::regStats() 1152810Srdreslin@umich.edu{ 1169796Sprakash.ramrakhyani@arm.com BaseTags::regStats(); 11712665Snikos.nikoleris@arm.com cacheTracking.regStats(name()); 1182810Srdreslin@umich.edu} 1192810Srdreslin@umich.edu 1202810Srdreslin@umich.eduvoid 12110815Sdavid.guillen@arm.comFALRU::invalidate(CacheBlk *blk) 1222810Srdreslin@umich.edu{ 12313165Sodanrc@yahoo.com.br // Erase block entry reference in the hash table 12413353Snikos.nikoleris@arm.com auto num_erased M5_VAR_USED = 12513353Snikos.nikoleris@arm.com tagHash.erase(std::make_pair(blk->tag, blk->isSecure())); 12613165Sodanrc@yahoo.com.br 12713165Sodanrc@yahoo.com.br // Sanity check; only one block reference should be erased 12813165Sodanrc@yahoo.com.br assert(num_erased == 1); 12913165Sodanrc@yahoo.com.br 13013165Sodanrc@yahoo.com.br // Invalidate block entry. Must be done after the hash is erased 13112566Snikos.nikoleris@arm.com BaseTags::invalidate(blk); 13212636Sodanrc@yahoo.com.br 13312745Sodanrc@yahoo.com.br // Decrease the number of tags in use 13412745Sodanrc@yahoo.com.br tagsInUse--; 13512745Sodanrc@yahoo.com.br 13612648Sodanrc@yahoo.com.br // Move the block to the tail to make it the next victim 13712648Sodanrc@yahoo.com.br moveToTail((FALRUBlk*)blk); 1382810Srdreslin@umich.edu} 1392810Srdreslin@umich.edu 14010815Sdavid.guillen@arm.comCacheBlk* 14111870Snikos.nikoleris@arm.comFALRU::accessBlock(Addr addr, bool is_secure, Cycles &lat) 14210815Sdavid.guillen@arm.com{ 14311870Snikos.nikoleris@arm.com return accessBlock(addr, is_secure, lat, 0); 14410815Sdavid.guillen@arm.com} 14510815Sdavid.guillen@arm.com 14610815Sdavid.guillen@arm.comCacheBlk* 14712665Snikos.nikoleris@arm.comFALRU::accessBlock(Addr addr, bool is_secure, Cycles &lat, 14812665Snikos.nikoleris@arm.com CachesMask *in_caches_mask) 1492810Srdreslin@umich.edu{ 15012665Snikos.nikoleris@arm.com CachesMask mask = 0; 15112677Sodanrc@yahoo.com.br FALRUBlk* blk = static_cast<FALRUBlk*>(findBlock(addr, is_secure)); 1522810Srdreslin@umich.edu 15313418Sodanrc@yahoo.com.br // If a cache hit 15412775Snikos.nikoleris@arm.com if (blk && blk->isValid()) { 15512665Snikos.nikoleris@arm.com mask = blk->inCachesMask; 15612677Sodanrc@yahoo.com.br 15712665Snikos.nikoleris@arm.com moveToHead(blk); 1582810Srdreslin@umich.edu } 15913418Sodanrc@yahoo.com.br 16012665Snikos.nikoleris@arm.com if (in_caches_mask) { 16112665Snikos.nikoleris@arm.com *in_caches_mask = mask; 1622810Srdreslin@umich.edu } 1632810Srdreslin@umich.edu 16412665Snikos.nikoleris@arm.com cacheTracking.recordAccess(blk); 16512665Snikos.nikoleris@arm.com 16613418Sodanrc@yahoo.com.br // The tag lookup latency is the same for a hit or a miss 16713418Sodanrc@yahoo.com.br lat = lookupLatency; 16813418Sodanrc@yahoo.com.br 1692810Srdreslin@umich.edu return blk; 1702810Srdreslin@umich.edu} 1712810Srdreslin@umich.edu 17210815Sdavid.guillen@arm.comCacheBlk* 17310028SGiacomo.Gabrielli@arm.comFALRU::findBlock(Addr addr, bool is_secure) const 1742810Srdreslin@umich.edu{ 17512775Snikos.nikoleris@arm.com FALRUBlk* blk = nullptr; 17612775Snikos.nikoleris@arm.com 17712677Sodanrc@yahoo.com.br Addr tag = extractTag(addr); 17812775Snikos.nikoleris@arm.com auto iter = tagHash.find(std::make_pair(tag, is_secure)); 17912775Snikos.nikoleris@arm.com if (iter != tagHash.end()) { 18012775Snikos.nikoleris@arm.com blk = (*iter).second; 18112775Snikos.nikoleris@arm.com } 1822810Srdreslin@umich.edu 1832810Srdreslin@umich.edu if (blk && blk->isValid()) { 18412677Sodanrc@yahoo.com.br assert(blk->tag == tag); 18512676Sodanrc@yahoo.com.br assert(blk->isSecure() == is_secure); 1862810Srdreslin@umich.edu } 18712775Snikos.nikoleris@arm.com 1882810Srdreslin@umich.edu return blk; 1892810Srdreslin@umich.edu} 1902810Srdreslin@umich.edu 19112743Sodanrc@yahoo.com.brReplaceableEntry* 19210941Sdavid.guillen@arm.comFALRU::findBlockBySetAndWay(int set, int way) const 19310941Sdavid.guillen@arm.com{ 19410941Sdavid.guillen@arm.com assert(set == 0); 19510941Sdavid.guillen@arm.com return &blks[way]; 19610941Sdavid.guillen@arm.com} 19710941Sdavid.guillen@arm.com 19810941Sdavid.guillen@arm.comCacheBlk* 19913941Sodanrc@yahoo.com.brFALRU::findVictim(Addr addr, const bool is_secure, const std::size_t size, 20012746Sodanrc@yahoo.com.br std::vector<CacheBlk*>& evict_blks) const 2012810Srdreslin@umich.edu{ 20212744Sodanrc@yahoo.com.br // The victim is always stored on the tail for the FALRU 20312744Sodanrc@yahoo.com.br FALRUBlk* victim = tail; 20412744Sodanrc@yahoo.com.br 20512744Sodanrc@yahoo.com.br // There is only one eviction for this replacement 20612744Sodanrc@yahoo.com.br evict_blks.push_back(victim); 20712744Sodanrc@yahoo.com.br 20812744Sodanrc@yahoo.com.br return victim; 2092810Srdreslin@umich.edu} 2102810Srdreslin@umich.edu 2112810Srdreslin@umich.eduvoid 21213752Sodanrc@yahoo.com.brFALRU::insertBlock(const PacketPtr pkt, CacheBlk *blk) 2135717Shsul@eecs.umich.edu{ 21412636Sodanrc@yahoo.com.br FALRUBlk* falruBlk = static_cast<FALRUBlk*>(blk); 21512636Sodanrc@yahoo.com.br 21612636Sodanrc@yahoo.com.br // Make sure block is not present in the cache 21712665Snikos.nikoleris@arm.com assert(falruBlk->inCachesMask == 0); 21812636Sodanrc@yahoo.com.br 21912636Sodanrc@yahoo.com.br // Do common block insertion functionality 22013752Sodanrc@yahoo.com.br BaseTags::insertBlock(pkt, blk); 22112636Sodanrc@yahoo.com.br 22212745Sodanrc@yahoo.com.br // Increment tag counter 22312745Sodanrc@yahoo.com.br tagsInUse++; 22412745Sodanrc@yahoo.com.br 22512636Sodanrc@yahoo.com.br // New block is the MRU 22612636Sodanrc@yahoo.com.br moveToHead(falruBlk); 22712636Sodanrc@yahoo.com.br 22812636Sodanrc@yahoo.com.br // Insert new block in the hash table 22912775Snikos.nikoleris@arm.com tagHash[std::make_pair(blk->tag, blk->isSecure())] = falruBlk; 2305717Shsul@eecs.umich.edu} 2315717Shsul@eecs.umich.edu 2325717Shsul@eecs.umich.eduvoid 2332810Srdreslin@umich.eduFALRU::moveToHead(FALRUBlk *blk) 2342810Srdreslin@umich.edu{ 23512648Sodanrc@yahoo.com.br // If block is not already head, do the moving 23612648Sodanrc@yahoo.com.br if (blk != head) { 23712665Snikos.nikoleris@arm.com cacheTracking.moveBlockToHead(blk); 23812648Sodanrc@yahoo.com.br // If block is tail, set previous block as new tail 2392810Srdreslin@umich.edu if (blk == tail){ 24011484Snikos.nikoleris@arm.com assert(blk->next == nullptr); 2412810Srdreslin@umich.edu tail = blk->prev; 24211484Snikos.nikoleris@arm.com tail->next = nullptr; 24312648Sodanrc@yahoo.com.br // Inform block's surrounding blocks that it has been moved 2442810Srdreslin@umich.edu } else { 2452810Srdreslin@umich.edu blk->prev->next = blk->next; 2462810Srdreslin@umich.edu blk->next->prev = blk->prev; 2472810Srdreslin@umich.edu } 24812648Sodanrc@yahoo.com.br 24912648Sodanrc@yahoo.com.br // Swap pointers 2502810Srdreslin@umich.edu blk->next = head; 25111484Snikos.nikoleris@arm.com blk->prev = nullptr; 2522810Srdreslin@umich.edu head->prev = blk; 2532810Srdreslin@umich.edu head = blk; 25412665Snikos.nikoleris@arm.com 25512665Snikos.nikoleris@arm.com cacheTracking.check(head, tail); 2562810Srdreslin@umich.edu } 2572810Srdreslin@umich.edu} 2582810Srdreslin@umich.edu 25912648Sodanrc@yahoo.com.brvoid 26012648Sodanrc@yahoo.com.brFALRU::moveToTail(FALRUBlk *blk) 26112648Sodanrc@yahoo.com.br{ 26212648Sodanrc@yahoo.com.br // If block is not already tail, do the moving 26312648Sodanrc@yahoo.com.br if (blk != tail) { 26412665Snikos.nikoleris@arm.com cacheTracking.moveBlockToTail(blk); 26512648Sodanrc@yahoo.com.br // If block is head, set next block as new head 26612648Sodanrc@yahoo.com.br if (blk == head){ 26712648Sodanrc@yahoo.com.br assert(blk->prev == nullptr); 26812648Sodanrc@yahoo.com.br head = blk->next; 26912648Sodanrc@yahoo.com.br head->prev = nullptr; 27012648Sodanrc@yahoo.com.br // Inform block's surrounding blocks that it has been moved 27112648Sodanrc@yahoo.com.br } else { 27212648Sodanrc@yahoo.com.br blk->prev->next = blk->next; 27312648Sodanrc@yahoo.com.br blk->next->prev = blk->prev; 27412648Sodanrc@yahoo.com.br } 27512648Sodanrc@yahoo.com.br 27612648Sodanrc@yahoo.com.br // Swap pointers 27712648Sodanrc@yahoo.com.br blk->prev = tail; 27812648Sodanrc@yahoo.com.br blk->next = nullptr; 27912648Sodanrc@yahoo.com.br tail->next = blk; 28012648Sodanrc@yahoo.com.br tail = blk; 28112665Snikos.nikoleris@arm.com 28212665Snikos.nikoleris@arm.com cacheTracking.check(head, tail); 28312648Sodanrc@yahoo.com.br } 28412648Sodanrc@yahoo.com.br} 28512648Sodanrc@yahoo.com.br 2869796Sprakash.ramrakhyani@arm.comFALRU * 2879796Sprakash.ramrakhyani@arm.comFALRUParams::create() 2889796Sprakash.ramrakhyani@arm.com{ 2899796Sprakash.ramrakhyani@arm.com return new FALRU(this); 2909796Sprakash.ramrakhyani@arm.com} 2919796Sprakash.ramrakhyani@arm.com 29212665Snikos.nikoleris@arm.comvoid 29313164Sodanrc@yahoo.com.brFALRU::CacheTracking::check(const FALRUBlk *head, const FALRUBlk *tail) const 29412665Snikos.nikoleris@arm.com{ 29512665Snikos.nikoleris@arm.com#ifdef FALRU_DEBUG 29613164Sodanrc@yahoo.com.br const FALRUBlk* blk = head; 29712665Snikos.nikoleris@arm.com unsigned curr_size = 0; 29812665Snikos.nikoleris@arm.com unsigned tracked_cache_size = minTrackedSize; 29912665Snikos.nikoleris@arm.com CachesMask in_caches_mask = inAllCachesMask; 30012665Snikos.nikoleris@arm.com int j = 0; 30112665Snikos.nikoleris@arm.com 30212665Snikos.nikoleris@arm.com while (blk) { 30312665Snikos.nikoleris@arm.com panic_if(blk->inCachesMask != in_caches_mask, "Expected cache mask " 30412665Snikos.nikoleris@arm.com "%x found %x", blk->inCachesMask, in_caches_mask); 30512665Snikos.nikoleris@arm.com 30612665Snikos.nikoleris@arm.com curr_size += blkSize; 30712665Snikos.nikoleris@arm.com if (curr_size == tracked_cache_size && blk != tail) { 30812665Snikos.nikoleris@arm.com panic_if(boundaries[j] != blk, "Unexpected boundary for the %d-th " 30912665Snikos.nikoleris@arm.com "cache", j); 31012665Snikos.nikoleris@arm.com tracked_cache_size <<= 1; 31112665Snikos.nikoleris@arm.com // from this point, blocks fit only in the larger caches 31212665Snikos.nikoleris@arm.com in_caches_mask &= ~(1U << j); 31312665Snikos.nikoleris@arm.com ++j; 31412665Snikos.nikoleris@arm.com } 31512665Snikos.nikoleris@arm.com blk = blk->next; 31612665Snikos.nikoleris@arm.com } 31712665Snikos.nikoleris@arm.com#endif // FALRU_DEBUG 31812665Snikos.nikoleris@arm.com} 31912665Snikos.nikoleris@arm.com 32012665Snikos.nikoleris@arm.comvoid 32112665Snikos.nikoleris@arm.comFALRU::CacheTracking::init(FALRUBlk *head, FALRUBlk *tail) 32212665Snikos.nikoleris@arm.com{ 32312665Snikos.nikoleris@arm.com // early exit if we are not tracking any extra caches 32412665Snikos.nikoleris@arm.com FALRUBlk* blk = numTrackedCaches ? head : nullptr; 32512665Snikos.nikoleris@arm.com unsigned curr_size = 0; 32612665Snikos.nikoleris@arm.com unsigned tracked_cache_size = minTrackedSize; 32712665Snikos.nikoleris@arm.com CachesMask in_caches_mask = inAllCachesMask; 32812665Snikos.nikoleris@arm.com int j = 0; 32912665Snikos.nikoleris@arm.com 33012665Snikos.nikoleris@arm.com while (blk) { 33112665Snikos.nikoleris@arm.com blk->inCachesMask = in_caches_mask; 33212665Snikos.nikoleris@arm.com 33312665Snikos.nikoleris@arm.com curr_size += blkSize; 33412665Snikos.nikoleris@arm.com if (curr_size == tracked_cache_size && blk != tail) { 33512665Snikos.nikoleris@arm.com boundaries[j] = blk; 33612665Snikos.nikoleris@arm.com 33712665Snikos.nikoleris@arm.com tracked_cache_size <<= 1; 33812665Snikos.nikoleris@arm.com // from this point, blocks fit only in the larger caches 33912665Snikos.nikoleris@arm.com in_caches_mask &= ~(1U << j); 34012665Snikos.nikoleris@arm.com ++j; 34112665Snikos.nikoleris@arm.com } 34212665Snikos.nikoleris@arm.com blk = blk->next; 34312665Snikos.nikoleris@arm.com } 34412665Snikos.nikoleris@arm.com} 34512665Snikos.nikoleris@arm.com 34612665Snikos.nikoleris@arm.com 34712665Snikos.nikoleris@arm.comvoid 34812665Snikos.nikoleris@arm.comFALRU::CacheTracking::moveBlockToHead(FALRUBlk *blk) 34912665Snikos.nikoleris@arm.com{ 35012665Snikos.nikoleris@arm.com // Get the mask of all caches, in which the block didn't fit 35112665Snikos.nikoleris@arm.com // before moving it to the head 35212665Snikos.nikoleris@arm.com CachesMask update_caches_mask = inAllCachesMask ^ blk->inCachesMask; 35312665Snikos.nikoleris@arm.com 35412665Snikos.nikoleris@arm.com for (int i = 0; i < numTrackedCaches; i++) { 35512665Snikos.nikoleris@arm.com CachesMask current_cache_mask = 1U << i; 35612665Snikos.nikoleris@arm.com if (current_cache_mask & update_caches_mask) { 35712665Snikos.nikoleris@arm.com // if the ith cache didn't fit the block (before it is moved to 35812665Snikos.nikoleris@arm.com // the head), move the ith boundary 1 block closer to the 35912665Snikos.nikoleris@arm.com // MRU 36012665Snikos.nikoleris@arm.com boundaries[i]->inCachesMask &= ~current_cache_mask; 36112665Snikos.nikoleris@arm.com boundaries[i] = boundaries[i]->prev; 36212665Snikos.nikoleris@arm.com } else if (boundaries[i] == blk) { 36312665Snikos.nikoleris@arm.com // Make sure the boundary doesn't point to the block 36412665Snikos.nikoleris@arm.com // we are about to move 36512665Snikos.nikoleris@arm.com boundaries[i] = blk->prev; 36612665Snikos.nikoleris@arm.com } 36712665Snikos.nikoleris@arm.com } 36812665Snikos.nikoleris@arm.com 36912665Snikos.nikoleris@arm.com // Make block reside in all caches 37012665Snikos.nikoleris@arm.com blk->inCachesMask = inAllCachesMask; 37112665Snikos.nikoleris@arm.com} 37212665Snikos.nikoleris@arm.com 37312665Snikos.nikoleris@arm.comvoid 37412665Snikos.nikoleris@arm.comFALRU::CacheTracking::moveBlockToTail(FALRUBlk *blk) 37512665Snikos.nikoleris@arm.com{ 37612665Snikos.nikoleris@arm.com CachesMask update_caches_mask = blk->inCachesMask; 37712665Snikos.nikoleris@arm.com 37812665Snikos.nikoleris@arm.com for (int i = 0; i < numTrackedCaches; i++) { 37912665Snikos.nikoleris@arm.com CachesMask current_cache_mask = 1U << i; 38012665Snikos.nikoleris@arm.com if (current_cache_mask & update_caches_mask) { 38112665Snikos.nikoleris@arm.com // if the ith cache fitted the block (before it is moved to 38212665Snikos.nikoleris@arm.com // the tail), move the ith boundary 1 block closer to the 38312665Snikos.nikoleris@arm.com // LRU 38412665Snikos.nikoleris@arm.com boundaries[i] = boundaries[i]->next; 38512665Snikos.nikoleris@arm.com if (boundaries[i] == blk) { 38612665Snikos.nikoleris@arm.com // Make sure the boundary doesn't point to the block 38712665Snikos.nikoleris@arm.com // we are about to move 38812665Snikos.nikoleris@arm.com boundaries[i] = blk->next; 38912665Snikos.nikoleris@arm.com } 39012665Snikos.nikoleris@arm.com boundaries[i]->inCachesMask |= current_cache_mask; 39112665Snikos.nikoleris@arm.com } 39212665Snikos.nikoleris@arm.com } 39312665Snikos.nikoleris@arm.com 39412665Snikos.nikoleris@arm.com // The block now fits only in the actual cache 39512665Snikos.nikoleris@arm.com blk->inCachesMask = 0; 39612665Snikos.nikoleris@arm.com} 39712665Snikos.nikoleris@arm.com 39812665Snikos.nikoleris@arm.comvoid 39912665Snikos.nikoleris@arm.comFALRU::CacheTracking::recordAccess(FALRUBlk *blk) 40012665Snikos.nikoleris@arm.com{ 40112665Snikos.nikoleris@arm.com for (int i = 0; i < numTrackedCaches; i++) { 40212665Snikos.nikoleris@arm.com if (blk && ((1U << i) & blk->inCachesMask)) { 40312665Snikos.nikoleris@arm.com hits[i]++; 40412665Snikos.nikoleris@arm.com } else { 40512665Snikos.nikoleris@arm.com misses[i]++; 40612665Snikos.nikoleris@arm.com } 40712665Snikos.nikoleris@arm.com } 40812665Snikos.nikoleris@arm.com 40912665Snikos.nikoleris@arm.com // Record stats for the actual cache too 41012775Snikos.nikoleris@arm.com if (blk && blk->isValid()) { 41112665Snikos.nikoleris@arm.com hits[numTrackedCaches]++; 41212665Snikos.nikoleris@arm.com } else { 41312665Snikos.nikoleris@arm.com misses[numTrackedCaches]++; 41412665Snikos.nikoleris@arm.com } 41512665Snikos.nikoleris@arm.com 41612665Snikos.nikoleris@arm.com accesses++; 41712665Snikos.nikoleris@arm.com} 41812665Snikos.nikoleris@arm.com 41912665Snikos.nikoleris@arm.comvoid 42012665Snikos.nikoleris@arm.comprintSize(std::ostream &stream, size_t size) 42112665Snikos.nikoleris@arm.com{ 42212665Snikos.nikoleris@arm.com static const char *SIZES[] = { "B", "kB", "MB", "GB", "TB", "ZB" }; 42312665Snikos.nikoleris@arm.com int div = 0; 42412665Snikos.nikoleris@arm.com while (size >= 1024 && div < (sizeof SIZES / sizeof *SIZES)) { 42512665Snikos.nikoleris@arm.com div++; 42612665Snikos.nikoleris@arm.com size >>= 10; 42712665Snikos.nikoleris@arm.com } 42812665Snikos.nikoleris@arm.com stream << size << SIZES[div]; 42912665Snikos.nikoleris@arm.com} 43012665Snikos.nikoleris@arm.com 43112665Snikos.nikoleris@arm.comvoid 43212665Snikos.nikoleris@arm.comFALRU::CacheTracking::regStats(std::string name) 43312665Snikos.nikoleris@arm.com{ 43412665Snikos.nikoleris@arm.com hits 43512665Snikos.nikoleris@arm.com .init(numTrackedCaches + 1) 43612665Snikos.nikoleris@arm.com .name(name + ".falru_hits") 43712665Snikos.nikoleris@arm.com .desc("The number of hits in each cache size.") 43812665Snikos.nikoleris@arm.com ; 43912665Snikos.nikoleris@arm.com misses 44012665Snikos.nikoleris@arm.com .init(numTrackedCaches + 1) 44112665Snikos.nikoleris@arm.com .name(name + ".falru_misses") 44212665Snikos.nikoleris@arm.com .desc("The number of misses in each cache size.") 44312665Snikos.nikoleris@arm.com ; 44412665Snikos.nikoleris@arm.com accesses 44512665Snikos.nikoleris@arm.com .name(name + ".falru_accesses") 44612665Snikos.nikoleris@arm.com .desc("The number of accesses to the FA LRU cache.") 44712665Snikos.nikoleris@arm.com ; 44812665Snikos.nikoleris@arm.com 44912665Snikos.nikoleris@arm.com for (unsigned i = 0; i < numTrackedCaches + 1; ++i) { 45012665Snikos.nikoleris@arm.com std::stringstream size_str; 45112665Snikos.nikoleris@arm.com printSize(size_str, minTrackedSize << i); 45212665Snikos.nikoleris@arm.com hits.subname(i, size_str.str()); 45312665Snikos.nikoleris@arm.com hits.subdesc(i, "Hits in a " + size_str.str() + " cache"); 45412665Snikos.nikoleris@arm.com misses.subname(i, size_str.str()); 45512665Snikos.nikoleris@arm.com misses.subdesc(i, "Misses in a " + size_str.str() + " cache"); 45612665Snikos.nikoleris@arm.com } 45712665Snikos.nikoleris@arm.com} 458