16782SN/A/* 28683SN/A * Copyright (c) 1999-2012 Mark D. Hill and David A. Wood 310973Sdavid.hashe@amd.com * Copyright (c) 2013 Advanced Micro Devices, Inc. 46782SN/A * All rights reserved. 56782SN/A * 66782SN/A * Redistribution and use in source and binary forms, with or without 76782SN/A * modification, are permitted provided that the following conditions are 86782SN/A * met: redistributions of source code must retain the above copyright 96782SN/A * notice, this list of conditions and the following disclaimer; 106782SN/A * redistributions in binary form must reproduce the above copyright 116782SN/A * notice, this list of conditions and the following disclaimer in the 126782SN/A * documentation and/or other materials provided with the distribution; 136782SN/A * neither the name of the copyright holders nor the names of its 146782SN/A * contributors may be used to endorse or promote products derived from 156782SN/A * this software without specific prior written permission. 166782SN/A * 176782SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 186782SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 196782SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 206782SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 216782SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 226782SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 236782SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 246782SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 256782SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 266782SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 276782SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 286782SN/A */ 296782SN/A 3011793Sbrandon.potter@amd.com#include "mem/ruby/structures/CacheMemory.hh" 3111793Sbrandon.potter@amd.com 327056SN/A#include "base/intmath.hh" 3313449Sgabeblack@google.com#include "base/logging.hh" 348232SN/A#include "debug/RubyCache.hh" 358937SN/A#include "debug/RubyCacheTrace.hh" 369105SN/A#include "debug/RubyResourceStalls.hh" 379104SN/A#include "debug/RubyStats.hh" 3814184Sgabeblack@google.com#include "mem/ruby/protocol/AccessPermission.hh" 3911108Sdavid.hashe@amd.com#include "mem/ruby/system/RubySystem.hh" 4011308Santhony.gutierrez@amd.com#include "mem/ruby/system/WeightedLRUPolicy.hh" 416782SN/A 427055SN/Ausing namespace std; 437055SN/A 447039SN/Aostream& 457039SN/Aoperator<<(ostream& out, const CacheMemory& obj) 466782SN/A{ 477039SN/A obj.print(out); 487039SN/A out << flush; 497039SN/A return out; 506782SN/A} 516782SN/A 526876SN/ACacheMemory * 536876SN/ARubyCacheParams::create() 546782SN/A{ 556876SN/A return new CacheMemory(this); 566782SN/A} 576782SN/A 586876SN/ACacheMemory::CacheMemory(const Params *p) 599105SN/A : SimObject(p), 6010919Sbrandon.potter@amd.com dataArray(p->dataArrayBanks, p->dataAccessLatency, 6110919Sbrandon.potter@amd.com p->start_index_bit, p->ruby_system), 6210919Sbrandon.potter@amd.com tagArray(p->tagArrayBanks, p->tagAccessLatency, 6310919Sbrandon.potter@amd.com p->start_index_bit, p->ruby_system) 646782SN/A{ 656882SN/A m_cache_size = p->size; 666876SN/A m_cache_assoc = p->assoc; 6710970Sdavid.hashe@amd.com m_replacementPolicy_ptr = p->replacement_policy; 6810980Sdavid.hashe@amd.com m_replacementPolicy_ptr->setCache(this); 697564SN/A m_start_index_bit = p->start_index_bit; 708653SN/A m_is_instruction_only_cache = p->is_icache; 719105SN/A m_resource_stalls = p->resourceStalls; 7211308Santhony.gutierrez@amd.com m_block_size = p->block_size; // may be 0 at this point. Updated in init() 736876SN/A} 746876SN/A 757039SN/Avoid 767039SN/ACacheMemory::init() 776876SN/A{ 7811308Santhony.gutierrez@amd.com if (m_block_size == 0) { 7911308Santhony.gutierrez@amd.com m_block_size = RubySystem::getBlockSizeBytes(); 8011308Santhony.gutierrez@amd.com } 8111308Santhony.gutierrez@amd.com m_cache_num_sets = (m_cache_size / m_cache_assoc) / m_block_size; 826882SN/A assert(m_cache_num_sets > 1); 837056SN/A m_cache_num_set_bits = floorLog2(m_cache_num_sets); 846882SN/A assert(m_cache_num_set_bits > 0); 857039SN/A 8611308Santhony.gutierrez@amd.com m_cache.resize(m_cache_num_sets, 8711308Santhony.gutierrez@amd.com std::vector<AbstractCacheEntry*>(m_cache_assoc, nullptr)); 886782SN/A} 896782SN/A 906782SN/ACacheMemory::~CacheMemory() 916782SN/A{ 9211308Santhony.gutierrez@amd.com if (m_replacementPolicy_ptr) 937039SN/A delete m_replacementPolicy_ptr; 947039SN/A for (int i = 0; i < m_cache_num_sets; i++) { 957039SN/A for (int j = 0; j < m_cache_assoc; j++) { 967039SN/A delete m_cache[i][j]; 977039SN/A } 986783SN/A } 996782SN/A} 1006782SN/A 1016782SN/A// convert a Address to its location in the cache 10211061Snilay@cs.wisc.eduint64_t 10311025Snilay@cs.wisc.eduCacheMemory::addressToCacheSet(Addr address) const 1046782SN/A{ 10511025Snilay@cs.wisc.edu assert(address == makeLineAddress(address)); 10611025Snilay@cs.wisc.edu return bitSelect(address, m_start_index_bit, 10711025Snilay@cs.wisc.edu m_start_index_bit + m_cache_num_set_bits - 1); 1086782SN/A} 1096782SN/A 1106782SN/A// Given a cache index: returns the index of the tag in a set. 1116782SN/A// returns -1 if the tag is not found. 1127039SN/Aint 11311061Snilay@cs.wisc.eduCacheMemory::findTagInSet(int64_t cacheSet, Addr tag) const 1146782SN/A{ 11511025Snilay@cs.wisc.edu assert(tag == makeLineAddress(tag)); 1167039SN/A // search the set for the tags 11711168Sandreas.hansson@arm.com auto it = m_tag_index.find(tag); 1187039SN/A if (it != m_tag_index.end()) 1197039SN/A if (m_cache[cacheSet][it->second]->m_Permission != 1207039SN/A AccessPermission_NotPresent) 1217039SN/A return it->second; 1227039SN/A return -1; // Not found 1236782SN/A} 1246782SN/A 1256782SN/A// Given a cache index: returns the index of the tag in a set. 1266782SN/A// returns -1 if the tag is not found. 1277039SN/Aint 12811061Snilay@cs.wisc.eduCacheMemory::findTagInSetIgnorePermissions(int64_t cacheSet, 12911025Snilay@cs.wisc.edu Addr tag) const 1306782SN/A{ 13111025Snilay@cs.wisc.edu assert(tag == makeLineAddress(tag)); 1327039SN/A // search the set for the tags 13311168Sandreas.hansson@arm.com auto it = m_tag_index.find(tag); 1347039SN/A if (it != m_tag_index.end()) 1357039SN/A return it->second; 1367039SN/A return -1; // Not found 1376782SN/A} 1386782SN/A 13910973Sdavid.hashe@amd.com// Given an unique cache block identifier (idx): return the valid address 14010973Sdavid.hashe@amd.com// stored by the cache block. If the block is invalid/notpresent, the 14110973Sdavid.hashe@amd.com// function returns the 0 address 14211025Snilay@cs.wisc.eduAddr 14310973Sdavid.hashe@amd.comCacheMemory::getAddressAtIdx(int idx) const 14410973Sdavid.hashe@amd.com{ 14511025Snilay@cs.wisc.edu Addr tmp(0); 14610973Sdavid.hashe@amd.com 14710973Sdavid.hashe@amd.com int set = idx / m_cache_assoc; 14810973Sdavid.hashe@amd.com assert(set < m_cache_num_sets); 14910973Sdavid.hashe@amd.com 15010973Sdavid.hashe@amd.com int way = idx - set * m_cache_assoc; 15110973Sdavid.hashe@amd.com assert (way < m_cache_assoc); 15210973Sdavid.hashe@amd.com 15310973Sdavid.hashe@amd.com AbstractCacheEntry* entry = m_cache[set][way]; 15410973Sdavid.hashe@amd.com if (entry == NULL || 15510973Sdavid.hashe@amd.com entry->m_Permission == AccessPermission_Invalid || 15610973Sdavid.hashe@amd.com entry->m_Permission == AccessPermission_NotPresent) { 15710973Sdavid.hashe@amd.com return tmp; 15810973Sdavid.hashe@amd.com } 15910973Sdavid.hashe@amd.com return entry->m_Address; 16010973Sdavid.hashe@amd.com} 16110973Sdavid.hashe@amd.com 16211049Snilay@cs.wisc.edubool 16311049Snilay@cs.wisc.eduCacheMemory::tryCacheAccess(Addr address, RubyRequestType type, 16411049Snilay@cs.wisc.edu DataBlock*& data_ptr) 16511049Snilay@cs.wisc.edu{ 16611049Snilay@cs.wisc.edu assert(address == makeLineAddress(address)); 16711118Snilay@cs.wisc.edu DPRINTF(RubyCache, "address: %#x\n", address); 16811061Snilay@cs.wisc.edu int64_t cacheSet = addressToCacheSet(address); 16911049Snilay@cs.wisc.edu int loc = findTagInSet(cacheSet, address); 17011049Snilay@cs.wisc.edu if (loc != -1) { 17111049Snilay@cs.wisc.edu // Do we even have a tag match? 17211049Snilay@cs.wisc.edu AbstractCacheEntry* entry = m_cache[cacheSet][loc]; 17311049Snilay@cs.wisc.edu m_replacementPolicy_ptr->touch(cacheSet, loc, curTick()); 17411049Snilay@cs.wisc.edu data_ptr = &(entry->getDataBlk()); 17511049Snilay@cs.wisc.edu 17611049Snilay@cs.wisc.edu if (entry->m_Permission == AccessPermission_Read_Write) { 17711049Snilay@cs.wisc.edu return true; 17811049Snilay@cs.wisc.edu } 17911049Snilay@cs.wisc.edu if ((entry->m_Permission == AccessPermission_Read_Only) && 18011049Snilay@cs.wisc.edu (type == RubyRequestType_LD || type == RubyRequestType_IFETCH)) { 18111049Snilay@cs.wisc.edu return true; 18211049Snilay@cs.wisc.edu } 18311049Snilay@cs.wisc.edu // The line must not be accessible 18411049Snilay@cs.wisc.edu } 18511049Snilay@cs.wisc.edu data_ptr = NULL; 18611049Snilay@cs.wisc.edu return false; 18711049Snilay@cs.wisc.edu} 18811049Snilay@cs.wisc.edu 18911049Snilay@cs.wisc.edubool 19011049Snilay@cs.wisc.eduCacheMemory::testCacheAccess(Addr address, RubyRequestType type, 19111049Snilay@cs.wisc.edu DataBlock*& data_ptr) 19211049Snilay@cs.wisc.edu{ 19311049Snilay@cs.wisc.edu assert(address == makeLineAddress(address)); 19411118Snilay@cs.wisc.edu DPRINTF(RubyCache, "address: %#x\n", address); 19511061Snilay@cs.wisc.edu int64_t cacheSet = addressToCacheSet(address); 19611049Snilay@cs.wisc.edu int loc = findTagInSet(cacheSet, address); 19711049Snilay@cs.wisc.edu 19811049Snilay@cs.wisc.edu if (loc != -1) { 19911049Snilay@cs.wisc.edu // Do we even have a tag match? 20011049Snilay@cs.wisc.edu AbstractCacheEntry* entry = m_cache[cacheSet][loc]; 20111049Snilay@cs.wisc.edu m_replacementPolicy_ptr->touch(cacheSet, loc, curTick()); 20211049Snilay@cs.wisc.edu data_ptr = &(entry->getDataBlk()); 20311049Snilay@cs.wisc.edu 20411049Snilay@cs.wisc.edu return m_cache[cacheSet][loc]->m_Permission != 20511049Snilay@cs.wisc.edu AccessPermission_NotPresent; 20611049Snilay@cs.wisc.edu } 20711049Snilay@cs.wisc.edu 20811049Snilay@cs.wisc.edu data_ptr = NULL; 20911049Snilay@cs.wisc.edu return false; 21011049Snilay@cs.wisc.edu} 21111049Snilay@cs.wisc.edu 2126782SN/A// tests to see if an address is present in the cache 2137039SN/Abool 21411025Snilay@cs.wisc.eduCacheMemory::isTagPresent(Addr address) const 2156782SN/A{ 21611025Snilay@cs.wisc.edu assert(address == makeLineAddress(address)); 21711061Snilay@cs.wisc.edu int64_t cacheSet = addressToCacheSet(address); 2187039SN/A int loc = findTagInSet(cacheSet, address); 2196782SN/A 2207039SN/A if (loc == -1) { 2217039SN/A // We didn't find the tag 22211118Snilay@cs.wisc.edu DPRINTF(RubyCache, "No tag match for address: %#x\n", address); 2237039SN/A return false; 2247039SN/A } 22511118Snilay@cs.wisc.edu DPRINTF(RubyCache, "address: %#x found\n", address); 2267039SN/A return true; 2276782SN/A} 2286782SN/A 2296782SN/A// Returns true if there is: 2306782SN/A// a) a tag match on this address or there is 2316782SN/A// b) an unused line in the same cache "way" 2327039SN/Abool 23311025Snilay@cs.wisc.eduCacheMemory::cacheAvail(Addr address) const 2346782SN/A{ 23511025Snilay@cs.wisc.edu assert(address == makeLineAddress(address)); 2366782SN/A 23711061Snilay@cs.wisc.edu int64_t cacheSet = addressToCacheSet(address); 2386782SN/A 2397039SN/A for (int i = 0; i < m_cache_assoc; i++) { 2407039SN/A AbstractCacheEntry* entry = m_cache[cacheSet][i]; 2417039SN/A if (entry != NULL) { 2427039SN/A if (entry->m_Address == address || 2437039SN/A entry->m_Permission == AccessPermission_NotPresent) { 2447039SN/A // Already in the cache or we found an empty entry 2457039SN/A return true; 2467039SN/A } 2477039SN/A } else { 2487039SN/A return true; 2497039SN/A } 2506782SN/A } 2517039SN/A return false; 2526782SN/A} 2536782SN/A 2547839SN/AAbstractCacheEntry* 25511086Snilay@cs.wisc.eduCacheMemory::allocate(Addr address, AbstractCacheEntry *entry, bool touch) 2566782SN/A{ 25711025Snilay@cs.wisc.edu assert(address == makeLineAddress(address)); 2587039SN/A assert(!isTagPresent(address)); 2597039SN/A assert(cacheAvail(address)); 26011118Snilay@cs.wisc.edu DPRINTF(RubyCache, "address: %#x\n", address); 2616782SN/A 2627039SN/A // Find the first open slot 26311061Snilay@cs.wisc.edu int64_t cacheSet = addressToCacheSet(address); 2647454SN/A std::vector<AbstractCacheEntry*> &set = m_cache[cacheSet]; 2657039SN/A for (int i = 0; i < m_cache_assoc; i++) { 2667039SN/A if (!set[i] || set[i]->m_Permission == AccessPermission_NotPresent) { 26711145Sjthestness@gmail.com if (set[i] && (set[i] != entry)) { 26811145Sjthestness@gmail.com warn_once("This protocol contains a cache entry handling bug: " 26911145Sjthestness@gmail.com "Entries in the cache should never be NotPresent! If\n" 27011145Sjthestness@gmail.com "this entry (%#x) is not tracked elsewhere, it will memory " 27111145Sjthestness@gmail.com "leak here. Fix your protocol to eliminate these!", 27211145Sjthestness@gmail.com address); 27311145Sjthestness@gmail.com } 2747039SN/A set[i] = entry; // Init entry 2757039SN/A set[i]->m_Address = address; 2767039SN/A set[i]->m_Permission = AccessPermission_Invalid; 2777039SN/A DPRINTF(RubyCache, "Allocate clearing lock for addr: %x\n", 2787039SN/A address); 2797839SN/A set[i]->m_locked = -1; 2807039SN/A m_tag_index[address] = i; 28111086Snilay@cs.wisc.edu entry->setSetIndex(cacheSet); 28211086Snilay@cs.wisc.edu entry->setWayIndex(i); 2836782SN/A 28410974Sdavid.hashe@amd.com if (touch) { 28510974Sdavid.hashe@amd.com m_replacementPolicy_ptr->touch(cacheSet, i, curTick()); 28610974Sdavid.hashe@amd.com } 2876782SN/A 2887839SN/A return entry; 2897039SN/A } 2906782SN/A } 2917805SN/A panic("Allocate didn't find an available entry"); 2926782SN/A} 2936782SN/A 2947039SN/Avoid 29511025Snilay@cs.wisc.eduCacheMemory::deallocate(Addr address) 2966782SN/A{ 29711025Snilay@cs.wisc.edu assert(address == makeLineAddress(address)); 2987039SN/A assert(isTagPresent(address)); 29911118Snilay@cs.wisc.edu DPRINTF(RubyCache, "address: %#x\n", address); 30011061Snilay@cs.wisc.edu int64_t cacheSet = addressToCacheSet(address); 3017039SN/A int loc = findTagInSet(cacheSet, address); 3027039SN/A if (loc != -1) { 3037039SN/A delete m_cache[cacheSet][loc]; 3047039SN/A m_cache[cacheSet][loc] = NULL; 3057039SN/A m_tag_index.erase(address); 3067039SN/A } 3076782SN/A} 3086782SN/A 3096782SN/A// Returns with the physical address of the conflicting cache line 31011025Snilay@cs.wisc.eduAddr 31111025Snilay@cs.wisc.eduCacheMemory::cacheProbe(Addr address) const 3126782SN/A{ 31311025Snilay@cs.wisc.edu assert(address == makeLineAddress(address)); 3147039SN/A assert(!cacheAvail(address)); 3156782SN/A 31611061Snilay@cs.wisc.edu int64_t cacheSet = addressToCacheSet(address); 3177039SN/A return m_cache[cacheSet][m_replacementPolicy_ptr->getVictim(cacheSet)]-> 3187039SN/A m_Address; 3196782SN/A} 3206782SN/A 3216782SN/A// looks an address up in the cache 3227839SN/AAbstractCacheEntry* 32311025Snilay@cs.wisc.eduCacheMemory::lookup(Addr address) 3246782SN/A{ 32511025Snilay@cs.wisc.edu assert(address == makeLineAddress(address)); 32611061Snilay@cs.wisc.edu int64_t cacheSet = addressToCacheSet(address); 3277039SN/A int loc = findTagInSet(cacheSet, address); 32811321Ssteve.reinhardt@amd.com if (loc == -1) return NULL; 3297839SN/A return m_cache[cacheSet][loc]; 3306782SN/A} 3316782SN/A 3326782SN/A// looks an address up in the cache 3337839SN/Aconst AbstractCacheEntry* 33411025Snilay@cs.wisc.eduCacheMemory::lookup(Addr address) const 3356782SN/A{ 33611025Snilay@cs.wisc.edu assert(address == makeLineAddress(address)); 33711061Snilay@cs.wisc.edu int64_t cacheSet = addressToCacheSet(address); 3387039SN/A int loc = findTagInSet(cacheSet, address); 33911321Ssteve.reinhardt@amd.com if (loc == -1) return NULL; 3407839SN/A return m_cache[cacheSet][loc]; 3416782SN/A} 3426782SN/A 3436782SN/A// Sets the most recently used bit for a cache block 3447039SN/Avoid 34511025Snilay@cs.wisc.eduCacheMemory::setMRU(Addr address) 3466782SN/A{ 34711061Snilay@cs.wisc.edu int64_t cacheSet = addressToCacheSet(address); 3488828SN/A int loc = findTagInSet(cacheSet, address); 3496782SN/A 35011321Ssteve.reinhardt@amd.com if (loc != -1) 3519171SN/A m_replacementPolicy_ptr->touch(cacheSet, loc, curTick()); 3526782SN/A} 3536782SN/A 3547039SN/Avoid 35511087Snilay@cs.wisc.eduCacheMemory::setMRU(const AbstractCacheEntry *e) 35611087Snilay@cs.wisc.edu{ 35711087Snilay@cs.wisc.edu uint32_t cacheSet = e->getSetIndex(); 35811087Snilay@cs.wisc.edu uint32_t loc = e->getWayIndex(); 35911087Snilay@cs.wisc.edu m_replacementPolicy_ptr->touch(cacheSet, loc, curTick()); 36011087Snilay@cs.wisc.edu} 36111087Snilay@cs.wisc.edu 36211087Snilay@cs.wisc.eduvoid 36311308Santhony.gutierrez@amd.comCacheMemory::setMRU(Addr address, int occupancy) 36411308Santhony.gutierrez@amd.com{ 36511308Santhony.gutierrez@amd.com int64_t cacheSet = addressToCacheSet(address); 36611308Santhony.gutierrez@amd.com int loc = findTagInSet(cacheSet, address); 36711308Santhony.gutierrez@amd.com 36811321Ssteve.reinhardt@amd.com if (loc != -1) { 36911308Santhony.gutierrez@amd.com if (m_replacementPolicy_ptr->useOccupancy()) { 37011308Santhony.gutierrez@amd.com (static_cast<WeightedLRUPolicy*>(m_replacementPolicy_ptr))-> 37111308Santhony.gutierrez@amd.com touch(cacheSet, loc, curTick(), occupancy); 37211308Santhony.gutierrez@amd.com } else { 37311308Santhony.gutierrez@amd.com m_replacementPolicy_ptr-> 37411308Santhony.gutierrez@amd.com touch(cacheSet, loc, curTick()); 37511308Santhony.gutierrez@amd.com } 37611308Santhony.gutierrez@amd.com } 37711308Santhony.gutierrez@amd.com} 37811308Santhony.gutierrez@amd.com 37911308Santhony.gutierrez@amd.comint 38011308Santhony.gutierrez@amd.comCacheMemory::getReplacementWeight(int64_t set, int64_t loc) 38111308Santhony.gutierrez@amd.com{ 38211308Santhony.gutierrez@amd.com assert(set < m_cache_num_sets); 38311308Santhony.gutierrez@amd.com assert(loc < m_cache_assoc); 38411308Santhony.gutierrez@amd.com int ret = 0; 38511321Ssteve.reinhardt@amd.com if (m_cache[set][loc] != NULL) { 38611308Santhony.gutierrez@amd.com ret = m_cache[set][loc]->getNumValidBlocks(); 38711308Santhony.gutierrez@amd.com assert(ret >= 0); 38811308Santhony.gutierrez@amd.com } 38911308Santhony.gutierrez@amd.com 39011308Santhony.gutierrez@amd.com return ret; 39111308Santhony.gutierrez@amd.com} 39211308Santhony.gutierrez@amd.com 39311308Santhony.gutierrez@amd.comvoid 3948683SN/ACacheMemory::recordCacheContents(int cntrl, CacheRecorder* tr) const 3956782SN/A{ 39611061Snilay@cs.wisc.edu uint64_t warmedUpBlocks = 0; 39711061Snilay@cs.wisc.edu uint64_t totalBlocks M5_VAR_USED = (uint64_t)m_cache_num_sets * 39811061Snilay@cs.wisc.edu (uint64_t)m_cache_assoc; 3998683SN/A 4007039SN/A for (int i = 0; i < m_cache_num_sets; i++) { 4017039SN/A for (int j = 0; j < m_cache_assoc; j++) { 4028683SN/A if (m_cache[i][j] != NULL) { 4038683SN/A AccessPermission perm = m_cache[i][j]->m_Permission; 4048683SN/A RubyRequestType request_type = RubyRequestType_NULL; 4058683SN/A if (perm == AccessPermission_Read_Only) { 4068683SN/A if (m_is_instruction_only_cache) { 4078683SN/A request_type = RubyRequestType_IFETCH; 4088683SN/A } else { 4098683SN/A request_type = RubyRequestType_LD; 4108683SN/A } 4118683SN/A } else if (perm == AccessPermission_Read_Write) { 4128683SN/A request_type = RubyRequestType_ST; 4137039SN/A } 4147039SN/A 4158683SN/A if (request_type != RubyRequestType_NULL) { 41611025Snilay@cs.wisc.edu tr->addRecord(cntrl, m_cache[i][j]->m_Address, 4178683SN/A 0, request_type, 4188683SN/A m_replacementPolicy_ptr->getLastAccess(i, j), 4198683SN/A m_cache[i][j]->getDataBlk()); 4208683SN/A warmedUpBlocks++; 4218683SN/A } 4227039SN/A } 4236782SN/A } 4246782SN/A } 4258683SN/A 4268937SN/A DPRINTF(RubyCacheTrace, "%s: %lli blocks of %lli total blocks" 4278683SN/A "recorded %.2f%% \n", name().c_str(), warmedUpBlocks, 42811061Snilay@cs.wisc.edu totalBlocks, (float(warmedUpBlocks) / float(totalBlocks)) * 100.0); 4296782SN/A} 4306782SN/A 4317039SN/Avoid 4327039SN/ACacheMemory::print(ostream& out) const 4336782SN/A{ 43410080SN/A out << "Cache dump: " << name() << endl; 4357039SN/A for (int i = 0; i < m_cache_num_sets; i++) { 4367039SN/A for (int j = 0; j < m_cache_assoc; j++) { 4377039SN/A if (m_cache[i][j] != NULL) { 4387039SN/A out << " Index: " << i 4397039SN/A << " way: " << j 4407039SN/A << " entry: " << *m_cache[i][j] << endl; 4417039SN/A } else { 4427039SN/A out << " Index: " << i 4437039SN/A << " way: " << j 4447039SN/A << " entry: NULL" << endl; 4457039SN/A } 4467039SN/A } 4476782SN/A } 4486782SN/A} 4496782SN/A 4507039SN/Avoid 4517039SN/ACacheMemory::printData(ostream& out) const 4526782SN/A{ 4537039SN/A out << "printData() not supported" << endl; 4546782SN/A} 4556782SN/A 4567039SN/Avoid 45711025Snilay@cs.wisc.eduCacheMemory::setLocked(Addr address, int context) 4587039SN/A{ 45911118Snilay@cs.wisc.edu DPRINTF(RubyCache, "Setting Lock for addr: %#x to %d\n", address, context); 46011025Snilay@cs.wisc.edu assert(address == makeLineAddress(address)); 46111061Snilay@cs.wisc.edu int64_t cacheSet = addressToCacheSet(address); 4627039SN/A int loc = findTagInSet(cacheSet, address); 4637039SN/A assert(loc != -1); 46411059Snilay@cs.wisc.edu m_cache[cacheSet][loc]->setLocked(context); 4656782SN/A} 4666782SN/A 4677039SN/Avoid 46811025Snilay@cs.wisc.eduCacheMemory::clearLocked(Addr address) 4696782SN/A{ 47011118Snilay@cs.wisc.edu DPRINTF(RubyCache, "Clear Lock for addr: %#x\n", address); 47111025Snilay@cs.wisc.edu assert(address == makeLineAddress(address)); 47211061Snilay@cs.wisc.edu int64_t cacheSet = addressToCacheSet(address); 4737039SN/A int loc = findTagInSet(cacheSet, address); 4747039SN/A assert(loc != -1); 47511059Snilay@cs.wisc.edu m_cache[cacheSet][loc]->clearLocked(); 4766782SN/A} 4776782SN/A 4786782SN/Abool 47911025Snilay@cs.wisc.eduCacheMemory::isLocked(Addr address, int context) 4806782SN/A{ 48111025Snilay@cs.wisc.edu assert(address == makeLineAddress(address)); 48211061Snilay@cs.wisc.edu int64_t cacheSet = addressToCacheSet(address); 4837039SN/A int loc = findTagInSet(cacheSet, address); 4847039SN/A assert(loc != -1); 48511118Snilay@cs.wisc.edu DPRINTF(RubyCache, "Testing Lock for addr: %#llx cur %d con %d\n", 4867839SN/A address, m_cache[cacheSet][loc]->m_locked, context); 48711059Snilay@cs.wisc.edu return m_cache[cacheSet][loc]->isLocked(context); 4886782SN/A} 4896782SN/A 4909104SN/Avoid 4919692SN/ACacheMemory::regStats() 4929692SN/A{ 49311523Sdavid.guillen@arm.com SimObject::regStats(); 49411523Sdavid.guillen@arm.com 4959692SN/A m_demand_hits 4969692SN/A .name(name() + ".demand_hits") 4979692SN/A .desc("Number of cache demand hits") 4989692SN/A ; 4999692SN/A 5009692SN/A m_demand_misses 5019692SN/A .name(name() + ".demand_misses") 5029692SN/A .desc("Number of cache demand misses") 5039692SN/A ; 5049692SN/A 5059692SN/A m_demand_accesses 5069692SN/A .name(name() + ".demand_accesses") 5079692SN/A .desc("Number of cache demand accesses") 5089692SN/A ; 5099692SN/A 5109692SN/A m_demand_accesses = m_demand_hits + m_demand_misses; 5119692SN/A 5129692SN/A m_sw_prefetches 5139692SN/A .name(name() + ".total_sw_prefetches") 5149692SN/A .desc("Number of software prefetches") 5159692SN/A .flags(Stats::nozero) 5169692SN/A ; 5179692SN/A 5189692SN/A m_hw_prefetches 5199692SN/A .name(name() + ".total_hw_prefetches") 5209692SN/A .desc("Number of hardware prefetches") 5219692SN/A .flags(Stats::nozero) 5229692SN/A ; 5239692SN/A 5249692SN/A m_prefetches 5259692SN/A .name(name() + ".total_prefetches") 5269692SN/A .desc("Number of prefetches") 5279692SN/A .flags(Stats::nozero) 5289692SN/A ; 5299692SN/A 5309692SN/A m_prefetches = m_sw_prefetches + m_hw_prefetches; 5319692SN/A 5329692SN/A m_accessModeType 5339692SN/A .init(RubyRequestType_NUM) 5349692SN/A .name(name() + ".access_mode") 5359692SN/A .flags(Stats::pdf | Stats::total) 5369692SN/A ; 5379692SN/A for (int i = 0; i < RubyAccessMode_NUM; i++) { 5389692SN/A m_accessModeType 5399692SN/A .subname(i, RubyAccessMode_to_string(RubyAccessMode(i))) 5409692SN/A .flags(Stats::nozero) 5419692SN/A ; 5429692SN/A } 5439692SN/A 5449692SN/A numDataArrayReads 5459692SN/A .name(name() + ".num_data_array_reads") 5469692SN/A .desc("number of data array reads") 5479692SN/A .flags(Stats::nozero) 5489692SN/A ; 5499692SN/A 5509692SN/A numDataArrayWrites 5519692SN/A .name(name() + ".num_data_array_writes") 5529692SN/A .desc("number of data array writes") 5539692SN/A .flags(Stats::nozero) 5549692SN/A ; 5559692SN/A 5569692SN/A numTagArrayReads 5579692SN/A .name(name() + ".num_tag_array_reads") 5589692SN/A .desc("number of tag array reads") 5599692SN/A .flags(Stats::nozero) 5609692SN/A ; 5619692SN/A 5629692SN/A numTagArrayWrites 5639692SN/A .name(name() + ".num_tag_array_writes") 5649692SN/A .desc("number of tag array writes") 5659692SN/A .flags(Stats::nozero) 5669692SN/A ; 5679692SN/A 5689692SN/A numTagArrayStalls 5699692SN/A .name(name() + ".num_tag_array_stalls") 5709692SN/A .desc("number of stalls caused by tag array") 5719692SN/A .flags(Stats::nozero) 5729692SN/A ; 5739692SN/A 5749692SN/A numDataArrayStalls 5759692SN/A .name(name() + ".num_data_array_stalls") 5769692SN/A .desc("number of stalls caused by data array") 5779692SN/A .flags(Stats::nozero) 5789692SN/A ; 5799692SN/A} 5809692SN/A 58110978Sdavid.hashe@amd.com// assumption: SLICC generated files will only call this function 58210978Sdavid.hashe@amd.com// once **all** resources are granted 5839692SN/Avoid 58411025Snilay@cs.wisc.eduCacheMemory::recordRequestType(CacheRequestType requestType, Addr addr) 5859692SN/A{ 5869104SN/A DPRINTF(RubyStats, "Recorded statistic: %s\n", 5879104SN/A CacheRequestType_to_string(requestType)); 5889104SN/A switch(requestType) { 5899104SN/A case CacheRequestType_DataArrayRead: 59010978Sdavid.hashe@amd.com if (m_resource_stalls) 59110978Sdavid.hashe@amd.com dataArray.reserve(addressToCacheSet(addr)); 5929104SN/A numDataArrayReads++; 5939104SN/A return; 5949104SN/A case CacheRequestType_DataArrayWrite: 59510978Sdavid.hashe@amd.com if (m_resource_stalls) 59610978Sdavid.hashe@amd.com dataArray.reserve(addressToCacheSet(addr)); 5979104SN/A numDataArrayWrites++; 5989104SN/A return; 5999104SN/A case CacheRequestType_TagArrayRead: 60010978Sdavid.hashe@amd.com if (m_resource_stalls) 60110978Sdavid.hashe@amd.com tagArray.reserve(addressToCacheSet(addr)); 6029104SN/A numTagArrayReads++; 6039104SN/A return; 6049104SN/A case CacheRequestType_TagArrayWrite: 60510978Sdavid.hashe@amd.com if (m_resource_stalls) 60610978Sdavid.hashe@amd.com tagArray.reserve(addressToCacheSet(addr)); 6079104SN/A numTagArrayWrites++; 6089104SN/A return; 6099104SN/A default: 6109104SN/A warn("CacheMemory access_type not found: %s", 6119104SN/A CacheRequestType_to_string(requestType)); 6129104SN/A } 6139104SN/A} 6149104SN/A 6159105SN/Abool 61611025Snilay@cs.wisc.eduCacheMemory::checkResourceAvailable(CacheResourceType res, Addr addr) 6179105SN/A{ 6189105SN/A if (!m_resource_stalls) { 6199105SN/A return true; 6209105SN/A } 6219105SN/A 6229105SN/A if (res == CacheResourceType_TagArray) { 6239105SN/A if (tagArray.tryAccess(addressToCacheSet(addr))) return true; 6249105SN/A else { 6259692SN/A DPRINTF(RubyResourceStalls, 62611118Snilay@cs.wisc.edu "Tag array stall on addr %#x in set %d\n", 6279692SN/A addr, addressToCacheSet(addr)); 6289105SN/A numTagArrayStalls++; 6299105SN/A return false; 6309105SN/A } 6319105SN/A } else if (res == CacheResourceType_DataArray) { 6329105SN/A if (dataArray.tryAccess(addressToCacheSet(addr))) return true; 6339105SN/A else { 6349692SN/A DPRINTF(RubyResourceStalls, 63511118Snilay@cs.wisc.edu "Data array stall on addr %#x in set %d\n", 6369692SN/A addr, addressToCacheSet(addr)); 6379105SN/A numDataArrayStalls++; 6389105SN/A return false; 6399105SN/A } 6409105SN/A } else { 64113449Sgabeblack@google.com panic("Unrecognized cache resource type."); 6429105SN/A } 6439105SN/A} 64410980Sdavid.hashe@amd.com 64510980Sdavid.hashe@amd.combool 64611061Snilay@cs.wisc.eduCacheMemory::isBlockInvalid(int64_t cache_set, int64_t loc) 64710980Sdavid.hashe@amd.com{ 64810980Sdavid.hashe@amd.com return (m_cache[cache_set][loc]->m_Permission == AccessPermission_Invalid); 64910980Sdavid.hashe@amd.com} 65010980Sdavid.hashe@amd.com 65110980Sdavid.hashe@amd.combool 65211061Snilay@cs.wisc.eduCacheMemory::isBlockNotBusy(int64_t cache_set, int64_t loc) 65310980Sdavid.hashe@amd.com{ 65410980Sdavid.hashe@amd.com return (m_cache[cache_set][loc]->m_Permission != AccessPermission_Busy); 65510980Sdavid.hashe@amd.com} 656