CacheMemory.cc revision 11086
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 307056SN/A#include "base/intmath.hh" 318232SN/A#include "debug/RubyCache.hh" 328937SN/A#include "debug/RubyCacheTrace.hh" 339105SN/A#include "debug/RubyResourceStalls.hh" 349104SN/A#include "debug/RubyStats.hh" 358683SN/A#include "mem/protocol/AccessPermission.hh" 3610301Snilay@cs.wisc.edu#include "mem/ruby/structures/CacheMemory.hh" 378683SN/A#include "mem/ruby/system/System.hh" 386782SN/A 397055SN/Ausing namespace std; 407055SN/A 417039SN/Aostream& 427039SN/Aoperator<<(ostream& out, const CacheMemory& obj) 436782SN/A{ 447039SN/A obj.print(out); 457039SN/A out << flush; 467039SN/A return out; 476782SN/A} 486782SN/A 496876SN/ACacheMemory * 506876SN/ARubyCacheParams::create() 516782SN/A{ 526876SN/A return new CacheMemory(this); 536782SN/A} 546782SN/A 556876SN/ACacheMemory::CacheMemory(const Params *p) 569105SN/A : SimObject(p), 5710919Sbrandon.potter@amd.com dataArray(p->dataArrayBanks, p->dataAccessLatency, 5810919Sbrandon.potter@amd.com p->start_index_bit, p->ruby_system), 5910919Sbrandon.potter@amd.com tagArray(p->tagArrayBanks, p->tagAccessLatency, 6010919Sbrandon.potter@amd.com p->start_index_bit, p->ruby_system) 616782SN/A{ 626882SN/A m_cache_size = p->size; 636876SN/A m_cache_assoc = p->assoc; 6410970Sdavid.hashe@amd.com m_replacementPolicy_ptr = p->replacement_policy; 6510980Sdavid.hashe@amd.com m_replacementPolicy_ptr->setCache(this); 667564SN/A m_start_index_bit = p->start_index_bit; 678653SN/A m_is_instruction_only_cache = p->is_icache; 689105SN/A m_resource_stalls = p->resourceStalls; 696876SN/A} 706876SN/A 717039SN/Avoid 727039SN/ACacheMemory::init() 736876SN/A{ 747039SN/A m_cache_num_sets = (m_cache_size / m_cache_assoc) / 757039SN/A RubySystem::getBlockSizeBytes(); 766882SN/A assert(m_cache_num_sets > 1); 777056SN/A m_cache_num_set_bits = floorLog2(m_cache_num_sets); 786882SN/A assert(m_cache_num_set_bits > 0); 797039SN/A 807454SN/A m_cache.resize(m_cache_num_sets); 817039SN/A for (int i = 0; i < m_cache_num_sets; i++) { 827454SN/A m_cache[i].resize(m_cache_assoc); 837039SN/A for (int j = 0; j < m_cache_assoc; j++) { 847039SN/A m_cache[i][j] = NULL; 857039SN/A } 866782SN/A } 876782SN/A} 886782SN/A 896782SN/ACacheMemory::~CacheMemory() 906782SN/A{ 917039SN/A if (m_replacementPolicy_ptr != NULL) 927039SN/A delete m_replacementPolicy_ptr; 937039SN/A for (int i = 0; i < m_cache_num_sets; i++) { 947039SN/A for (int j = 0; j < m_cache_assoc; j++) { 957039SN/A delete m_cache[i][j]; 967039SN/A } 976783SN/A } 986782SN/A} 996782SN/A 1006782SN/A// convert a Address to its location in the cache 10111061Snilay@cs.wisc.eduint64_t 10211025Snilay@cs.wisc.eduCacheMemory::addressToCacheSet(Addr address) const 1036782SN/A{ 10411025Snilay@cs.wisc.edu assert(address == makeLineAddress(address)); 10511025Snilay@cs.wisc.edu return bitSelect(address, m_start_index_bit, 10611025Snilay@cs.wisc.edu m_start_index_bit + m_cache_num_set_bits - 1); 1076782SN/A} 1086782SN/A 1096782SN/A// Given a cache index: returns the index of the tag in a set. 1106782SN/A// returns -1 if the tag is not found. 1117039SN/Aint 11211061Snilay@cs.wisc.eduCacheMemory::findTagInSet(int64_t cacheSet, Addr tag) const 1136782SN/A{ 11411025Snilay@cs.wisc.edu assert(tag == makeLineAddress(tag)); 1157039SN/A // search the set for the tags 11611025Snilay@cs.wisc.edu m5::hash_map<Addr, int>::const_iterator it = m_tag_index.find(tag); 1177039SN/A if (it != m_tag_index.end()) 1187039SN/A if (m_cache[cacheSet][it->second]->m_Permission != 1197039SN/A AccessPermission_NotPresent) 1207039SN/A return it->second; 1217039SN/A return -1; // Not found 1226782SN/A} 1236782SN/A 1246782SN/A// Given a cache index: returns the index of the tag in a set. 1256782SN/A// returns -1 if the tag is not found. 1267039SN/Aint 12711061Snilay@cs.wisc.eduCacheMemory::findTagInSetIgnorePermissions(int64_t cacheSet, 12811025Snilay@cs.wisc.edu Addr tag) const 1296782SN/A{ 13011025Snilay@cs.wisc.edu assert(tag == makeLineAddress(tag)); 1317039SN/A // search the set for the tags 13211025Snilay@cs.wisc.edu m5::hash_map<Addr, int>::const_iterator it = m_tag_index.find(tag); 1337039SN/A if (it != m_tag_index.end()) 1347039SN/A return it->second; 1357039SN/A return -1; // Not found 1366782SN/A} 1376782SN/A 13810973Sdavid.hashe@amd.com// Given an unique cache block identifier (idx): return the valid address 13910973Sdavid.hashe@amd.com// stored by the cache block. If the block is invalid/notpresent, the 14010973Sdavid.hashe@amd.com// function returns the 0 address 14111025Snilay@cs.wisc.eduAddr 14210973Sdavid.hashe@amd.comCacheMemory::getAddressAtIdx(int idx) const 14310973Sdavid.hashe@amd.com{ 14411025Snilay@cs.wisc.edu Addr tmp(0); 14510973Sdavid.hashe@amd.com 14610973Sdavid.hashe@amd.com int set = idx / m_cache_assoc; 14710973Sdavid.hashe@amd.com assert(set < m_cache_num_sets); 14810973Sdavid.hashe@amd.com 14910973Sdavid.hashe@amd.com int way = idx - set * m_cache_assoc; 15010973Sdavid.hashe@amd.com assert (way < m_cache_assoc); 15110973Sdavid.hashe@amd.com 15210973Sdavid.hashe@amd.com AbstractCacheEntry* entry = m_cache[set][way]; 15310973Sdavid.hashe@amd.com if (entry == NULL || 15410973Sdavid.hashe@amd.com entry->m_Permission == AccessPermission_Invalid || 15510973Sdavid.hashe@amd.com entry->m_Permission == AccessPermission_NotPresent) { 15610973Sdavid.hashe@amd.com return tmp; 15710973Sdavid.hashe@amd.com } 15810973Sdavid.hashe@amd.com return entry->m_Address; 15910973Sdavid.hashe@amd.com} 16010973Sdavid.hashe@amd.com 16111049Snilay@cs.wisc.edubool 16211049Snilay@cs.wisc.eduCacheMemory::tryCacheAccess(Addr address, RubyRequestType type, 16311049Snilay@cs.wisc.edu DataBlock*& data_ptr) 16411049Snilay@cs.wisc.edu{ 16511049Snilay@cs.wisc.edu assert(address == makeLineAddress(address)); 16611049Snilay@cs.wisc.edu DPRINTF(RubyCache, "address: %s\n", address); 16711061Snilay@cs.wisc.edu int64_t cacheSet = addressToCacheSet(address); 16811049Snilay@cs.wisc.edu int loc = findTagInSet(cacheSet, address); 16911049Snilay@cs.wisc.edu if (loc != -1) { 17011049Snilay@cs.wisc.edu // Do we even have a tag match? 17111049Snilay@cs.wisc.edu AbstractCacheEntry* entry = m_cache[cacheSet][loc]; 17211049Snilay@cs.wisc.edu m_replacementPolicy_ptr->touch(cacheSet, loc, curTick()); 17311049Snilay@cs.wisc.edu data_ptr = &(entry->getDataBlk()); 17411049Snilay@cs.wisc.edu 17511049Snilay@cs.wisc.edu if (entry->m_Permission == AccessPermission_Read_Write) { 17611049Snilay@cs.wisc.edu return true; 17711049Snilay@cs.wisc.edu } 17811049Snilay@cs.wisc.edu if ((entry->m_Permission == AccessPermission_Read_Only) && 17911049Snilay@cs.wisc.edu (type == RubyRequestType_LD || type == RubyRequestType_IFETCH)) { 18011049Snilay@cs.wisc.edu return true; 18111049Snilay@cs.wisc.edu } 18211049Snilay@cs.wisc.edu // The line must not be accessible 18311049Snilay@cs.wisc.edu } 18411049Snilay@cs.wisc.edu data_ptr = NULL; 18511049Snilay@cs.wisc.edu return false; 18611049Snilay@cs.wisc.edu} 18711049Snilay@cs.wisc.edu 18811049Snilay@cs.wisc.edubool 18911049Snilay@cs.wisc.eduCacheMemory::testCacheAccess(Addr address, RubyRequestType type, 19011049Snilay@cs.wisc.edu DataBlock*& data_ptr) 19111049Snilay@cs.wisc.edu{ 19211049Snilay@cs.wisc.edu assert(address == makeLineAddress(address)); 19311049Snilay@cs.wisc.edu DPRINTF(RubyCache, "address: %s\n", address); 19411061Snilay@cs.wisc.edu int64_t cacheSet = addressToCacheSet(address); 19511049Snilay@cs.wisc.edu int loc = findTagInSet(cacheSet, address); 19611049Snilay@cs.wisc.edu 19711049Snilay@cs.wisc.edu if (loc != -1) { 19811049Snilay@cs.wisc.edu // Do we even have a tag match? 19911049Snilay@cs.wisc.edu AbstractCacheEntry* entry = m_cache[cacheSet][loc]; 20011049Snilay@cs.wisc.edu m_replacementPolicy_ptr->touch(cacheSet, loc, curTick()); 20111049Snilay@cs.wisc.edu data_ptr = &(entry->getDataBlk()); 20211049Snilay@cs.wisc.edu 20311049Snilay@cs.wisc.edu return m_cache[cacheSet][loc]->m_Permission != 20411049Snilay@cs.wisc.edu AccessPermission_NotPresent; 20511049Snilay@cs.wisc.edu } 20611049Snilay@cs.wisc.edu 20711049Snilay@cs.wisc.edu data_ptr = NULL; 20811049Snilay@cs.wisc.edu return false; 20911049Snilay@cs.wisc.edu} 21011049Snilay@cs.wisc.edu 2116782SN/A// tests to see if an address is present in the cache 2127039SN/Abool 21311025Snilay@cs.wisc.eduCacheMemory::isTagPresent(Addr address) const 2146782SN/A{ 21511025Snilay@cs.wisc.edu assert(address == makeLineAddress(address)); 21611061Snilay@cs.wisc.edu int64_t cacheSet = addressToCacheSet(address); 2177039SN/A int loc = findTagInSet(cacheSet, address); 2186782SN/A 2197039SN/A if (loc == -1) { 2207039SN/A // We didn't find the tag 2217780SN/A DPRINTF(RubyCache, "No tag match for address: %s\n", address); 2227039SN/A return false; 2237039SN/A } 2247780SN/A DPRINTF(RubyCache, "address: %s found\n", address); 2257039SN/A return true; 2266782SN/A} 2276782SN/A 2286782SN/A// Returns true if there is: 2296782SN/A// a) a tag match on this address or there is 2306782SN/A// b) an unused line in the same cache "way" 2317039SN/Abool 23211025Snilay@cs.wisc.eduCacheMemory::cacheAvail(Addr address) const 2336782SN/A{ 23411025Snilay@cs.wisc.edu assert(address == makeLineAddress(address)); 2356782SN/A 23611061Snilay@cs.wisc.edu int64_t cacheSet = addressToCacheSet(address); 2376782SN/A 2387039SN/A for (int i = 0; i < m_cache_assoc; i++) { 2397039SN/A AbstractCacheEntry* entry = m_cache[cacheSet][i]; 2407039SN/A if (entry != NULL) { 2417039SN/A if (entry->m_Address == address || 2427039SN/A entry->m_Permission == AccessPermission_NotPresent) { 2437039SN/A // Already in the cache or we found an empty entry 2447039SN/A return true; 2457039SN/A } 2467039SN/A } else { 2477039SN/A return true; 2487039SN/A } 2496782SN/A } 2507039SN/A return false; 2516782SN/A} 2526782SN/A 2537839SN/AAbstractCacheEntry* 25411086Snilay@cs.wisc.eduCacheMemory::allocate(Addr address, AbstractCacheEntry *entry, bool touch) 2556782SN/A{ 25611025Snilay@cs.wisc.edu assert(address == makeLineAddress(address)); 2577039SN/A assert(!isTagPresent(address)); 2587039SN/A assert(cacheAvail(address)); 2597780SN/A DPRINTF(RubyCache, "address: %s\n", address); 2606782SN/A 2617039SN/A // Find the first open slot 26211061Snilay@cs.wisc.edu int64_t cacheSet = addressToCacheSet(address); 2637454SN/A std::vector<AbstractCacheEntry*> &set = m_cache[cacheSet]; 2647039SN/A for (int i = 0; i < m_cache_assoc; i++) { 2657039SN/A if (!set[i] || set[i]->m_Permission == AccessPermission_NotPresent) { 2667039SN/A set[i] = entry; // Init entry 2677039SN/A set[i]->m_Address = address; 2687039SN/A set[i]->m_Permission = AccessPermission_Invalid; 2697039SN/A DPRINTF(RubyCache, "Allocate clearing lock for addr: %x\n", 2707039SN/A address); 2717839SN/A set[i]->m_locked = -1; 2727039SN/A m_tag_index[address] = i; 27311086Snilay@cs.wisc.edu entry->setSetIndex(cacheSet); 27411086Snilay@cs.wisc.edu entry->setWayIndex(i); 2756782SN/A 27610974Sdavid.hashe@amd.com if (touch) { 27710974Sdavid.hashe@amd.com m_replacementPolicy_ptr->touch(cacheSet, i, curTick()); 27810974Sdavid.hashe@amd.com } 2796782SN/A 2807839SN/A return entry; 2817039SN/A } 2826782SN/A } 2837805SN/A panic("Allocate didn't find an available entry"); 2846782SN/A} 2856782SN/A 2867039SN/Avoid 28711025Snilay@cs.wisc.eduCacheMemory::deallocate(Addr address) 2886782SN/A{ 28911025Snilay@cs.wisc.edu assert(address == makeLineAddress(address)); 2907039SN/A assert(isTagPresent(address)); 2917780SN/A DPRINTF(RubyCache, "address: %s\n", address); 29211061Snilay@cs.wisc.edu int64_t cacheSet = addressToCacheSet(address); 2937039SN/A int loc = findTagInSet(cacheSet, address); 2947039SN/A if (loc != -1) { 2957039SN/A delete m_cache[cacheSet][loc]; 2967039SN/A m_cache[cacheSet][loc] = NULL; 2977039SN/A m_tag_index.erase(address); 2987039SN/A } 2996782SN/A} 3006782SN/A 3016782SN/A// Returns with the physical address of the conflicting cache line 30211025Snilay@cs.wisc.eduAddr 30311025Snilay@cs.wisc.eduCacheMemory::cacheProbe(Addr address) const 3046782SN/A{ 30511025Snilay@cs.wisc.edu assert(address == makeLineAddress(address)); 3067039SN/A assert(!cacheAvail(address)); 3076782SN/A 30811061Snilay@cs.wisc.edu int64_t cacheSet = addressToCacheSet(address); 3097039SN/A return m_cache[cacheSet][m_replacementPolicy_ptr->getVictim(cacheSet)]-> 3107039SN/A m_Address; 3116782SN/A} 3126782SN/A 3136782SN/A// looks an address up in the cache 3147839SN/AAbstractCacheEntry* 31511025Snilay@cs.wisc.eduCacheMemory::lookup(Addr address) 3166782SN/A{ 31711025Snilay@cs.wisc.edu assert(address == makeLineAddress(address)); 31811061Snilay@cs.wisc.edu int64_t cacheSet = addressToCacheSet(address); 3197039SN/A int loc = findTagInSet(cacheSet, address); 3207839SN/A if(loc == -1) return NULL; 3217839SN/A return m_cache[cacheSet][loc]; 3226782SN/A} 3236782SN/A 3246782SN/A// looks an address up in the cache 3257839SN/Aconst AbstractCacheEntry* 32611025Snilay@cs.wisc.eduCacheMemory::lookup(Addr address) const 3276782SN/A{ 32811025Snilay@cs.wisc.edu assert(address == makeLineAddress(address)); 32911061Snilay@cs.wisc.edu int64_t cacheSet = addressToCacheSet(address); 3307039SN/A int loc = findTagInSet(cacheSet, address); 3317839SN/A if(loc == -1) return NULL; 3327839SN/A return m_cache[cacheSet][loc]; 3336782SN/A} 3346782SN/A 3356782SN/A// Sets the most recently used bit for a cache block 3367039SN/Avoid 33711025Snilay@cs.wisc.eduCacheMemory::setMRU(Addr address) 3386782SN/A{ 33911061Snilay@cs.wisc.edu int64_t cacheSet = addressToCacheSet(address); 3408828SN/A int loc = findTagInSet(cacheSet, address); 3416782SN/A 3428828SN/A if(loc != -1) 3439171SN/A m_replacementPolicy_ptr->touch(cacheSet, loc, curTick()); 3446782SN/A} 3456782SN/A 3467039SN/Avoid 3478683SN/ACacheMemory::recordCacheContents(int cntrl, CacheRecorder* tr) const 3486782SN/A{ 34911061Snilay@cs.wisc.edu uint64_t warmedUpBlocks = 0; 35011061Snilay@cs.wisc.edu uint64_t totalBlocks M5_VAR_USED = (uint64_t)m_cache_num_sets * 35111061Snilay@cs.wisc.edu (uint64_t)m_cache_assoc; 3528683SN/A 3537039SN/A for (int i = 0; i < m_cache_num_sets; i++) { 3547039SN/A for (int j = 0; j < m_cache_assoc; j++) { 3558683SN/A if (m_cache[i][j] != NULL) { 3568683SN/A AccessPermission perm = m_cache[i][j]->m_Permission; 3578683SN/A RubyRequestType request_type = RubyRequestType_NULL; 3588683SN/A if (perm == AccessPermission_Read_Only) { 3598683SN/A if (m_is_instruction_only_cache) { 3608683SN/A request_type = RubyRequestType_IFETCH; 3618683SN/A } else { 3628683SN/A request_type = RubyRequestType_LD; 3638683SN/A } 3648683SN/A } else if (perm == AccessPermission_Read_Write) { 3658683SN/A request_type = RubyRequestType_ST; 3667039SN/A } 3677039SN/A 3688683SN/A if (request_type != RubyRequestType_NULL) { 36911025Snilay@cs.wisc.edu tr->addRecord(cntrl, m_cache[i][j]->m_Address, 3708683SN/A 0, request_type, 3718683SN/A m_replacementPolicy_ptr->getLastAccess(i, j), 3728683SN/A m_cache[i][j]->getDataBlk()); 3738683SN/A warmedUpBlocks++; 3748683SN/A } 3757039SN/A } 3766782SN/A } 3776782SN/A } 3788683SN/A 3798937SN/A DPRINTF(RubyCacheTrace, "%s: %lli blocks of %lli total blocks" 3808683SN/A "recorded %.2f%% \n", name().c_str(), warmedUpBlocks, 38111061Snilay@cs.wisc.edu totalBlocks, (float(warmedUpBlocks) / float(totalBlocks)) * 100.0); 3826782SN/A} 3836782SN/A 3847039SN/Avoid 3857039SN/ACacheMemory::print(ostream& out) const 3866782SN/A{ 38710080SN/A out << "Cache dump: " << name() << endl; 3887039SN/A for (int i = 0; i < m_cache_num_sets; i++) { 3897039SN/A for (int j = 0; j < m_cache_assoc; j++) { 3907039SN/A if (m_cache[i][j] != NULL) { 3917039SN/A out << " Index: " << i 3927039SN/A << " way: " << j 3937039SN/A << " entry: " << *m_cache[i][j] << endl; 3947039SN/A } else { 3957039SN/A out << " Index: " << i 3967039SN/A << " way: " << j 3977039SN/A << " entry: NULL" << endl; 3987039SN/A } 3997039SN/A } 4006782SN/A } 4016782SN/A} 4026782SN/A 4037039SN/Avoid 4047039SN/ACacheMemory::printData(ostream& out) const 4056782SN/A{ 4067039SN/A out << "printData() not supported" << endl; 4076782SN/A} 4086782SN/A 4097039SN/Avoid 41011025Snilay@cs.wisc.eduCacheMemory::setLocked(Addr address, int context) 4117039SN/A{ 4127039SN/A DPRINTF(RubyCache, "Setting Lock for addr: %x to %d\n", address, context); 41311025Snilay@cs.wisc.edu assert(address == makeLineAddress(address)); 41411061Snilay@cs.wisc.edu int64_t cacheSet = addressToCacheSet(address); 4157039SN/A int loc = findTagInSet(cacheSet, address); 4167039SN/A assert(loc != -1); 41711059Snilay@cs.wisc.edu m_cache[cacheSet][loc]->setLocked(context); 4186782SN/A} 4196782SN/A 4207039SN/Avoid 42111025Snilay@cs.wisc.eduCacheMemory::clearLocked(Addr address) 4226782SN/A{ 4237039SN/A DPRINTF(RubyCache, "Clear Lock for addr: %x\n", address); 42411025Snilay@cs.wisc.edu assert(address == makeLineAddress(address)); 42511061Snilay@cs.wisc.edu int64_t cacheSet = addressToCacheSet(address); 4267039SN/A int loc = findTagInSet(cacheSet, address); 4277039SN/A assert(loc != -1); 42811059Snilay@cs.wisc.edu m_cache[cacheSet][loc]->clearLocked(); 4296782SN/A} 4306782SN/A 4316782SN/Abool 43211025Snilay@cs.wisc.eduCacheMemory::isLocked(Addr address, int context) 4336782SN/A{ 43411025Snilay@cs.wisc.edu assert(address == makeLineAddress(address)); 43511061Snilay@cs.wisc.edu int64_t cacheSet = addressToCacheSet(address); 4367039SN/A int loc = findTagInSet(cacheSet, address); 4377039SN/A assert(loc != -1); 4387039SN/A DPRINTF(RubyCache, "Testing Lock for addr: %llx cur %d con %d\n", 4397839SN/A address, m_cache[cacheSet][loc]->m_locked, context); 44011059Snilay@cs.wisc.edu return m_cache[cacheSet][loc]->isLocked(context); 4416782SN/A} 4426782SN/A 4439104SN/Avoid 4449692SN/ACacheMemory::regStats() 4459692SN/A{ 4469692SN/A m_demand_hits 4479692SN/A .name(name() + ".demand_hits") 4489692SN/A .desc("Number of cache demand hits") 4499692SN/A ; 4509692SN/A 4519692SN/A m_demand_misses 4529692SN/A .name(name() + ".demand_misses") 4539692SN/A .desc("Number of cache demand misses") 4549692SN/A ; 4559692SN/A 4569692SN/A m_demand_accesses 4579692SN/A .name(name() + ".demand_accesses") 4589692SN/A .desc("Number of cache demand accesses") 4599692SN/A ; 4609692SN/A 4619692SN/A m_demand_accesses = m_demand_hits + m_demand_misses; 4629692SN/A 4639692SN/A m_sw_prefetches 4649692SN/A .name(name() + ".total_sw_prefetches") 4659692SN/A .desc("Number of software prefetches") 4669692SN/A .flags(Stats::nozero) 4679692SN/A ; 4689692SN/A 4699692SN/A m_hw_prefetches 4709692SN/A .name(name() + ".total_hw_prefetches") 4719692SN/A .desc("Number of hardware prefetches") 4729692SN/A .flags(Stats::nozero) 4739692SN/A ; 4749692SN/A 4759692SN/A m_prefetches 4769692SN/A .name(name() + ".total_prefetches") 4779692SN/A .desc("Number of prefetches") 4789692SN/A .flags(Stats::nozero) 4799692SN/A ; 4809692SN/A 4819692SN/A m_prefetches = m_sw_prefetches + m_hw_prefetches; 4829692SN/A 4839692SN/A m_accessModeType 4849692SN/A .init(RubyRequestType_NUM) 4859692SN/A .name(name() + ".access_mode") 4869692SN/A .flags(Stats::pdf | Stats::total) 4879692SN/A ; 4889692SN/A for (int i = 0; i < RubyAccessMode_NUM; i++) { 4899692SN/A m_accessModeType 4909692SN/A .subname(i, RubyAccessMode_to_string(RubyAccessMode(i))) 4919692SN/A .flags(Stats::nozero) 4929692SN/A ; 4939692SN/A } 4949692SN/A 4959692SN/A numDataArrayReads 4969692SN/A .name(name() + ".num_data_array_reads") 4979692SN/A .desc("number of data array reads") 4989692SN/A .flags(Stats::nozero) 4999692SN/A ; 5009692SN/A 5019692SN/A numDataArrayWrites 5029692SN/A .name(name() + ".num_data_array_writes") 5039692SN/A .desc("number of data array writes") 5049692SN/A .flags(Stats::nozero) 5059692SN/A ; 5069692SN/A 5079692SN/A numTagArrayReads 5089692SN/A .name(name() + ".num_tag_array_reads") 5099692SN/A .desc("number of tag array reads") 5109692SN/A .flags(Stats::nozero) 5119692SN/A ; 5129692SN/A 5139692SN/A numTagArrayWrites 5149692SN/A .name(name() + ".num_tag_array_writes") 5159692SN/A .desc("number of tag array writes") 5169692SN/A .flags(Stats::nozero) 5179692SN/A ; 5189692SN/A 5199692SN/A numTagArrayStalls 5209692SN/A .name(name() + ".num_tag_array_stalls") 5219692SN/A .desc("number of stalls caused by tag array") 5229692SN/A .flags(Stats::nozero) 5239692SN/A ; 5249692SN/A 5259692SN/A numDataArrayStalls 5269692SN/A .name(name() + ".num_data_array_stalls") 5279692SN/A .desc("number of stalls caused by data array") 5289692SN/A .flags(Stats::nozero) 5299692SN/A ; 5309692SN/A} 5319692SN/A 53210978Sdavid.hashe@amd.com// assumption: SLICC generated files will only call this function 53310978Sdavid.hashe@amd.com// once **all** resources are granted 5349692SN/Avoid 53511025Snilay@cs.wisc.eduCacheMemory::recordRequestType(CacheRequestType requestType, Addr addr) 5369692SN/A{ 5379104SN/A DPRINTF(RubyStats, "Recorded statistic: %s\n", 5389104SN/A CacheRequestType_to_string(requestType)); 5399104SN/A switch(requestType) { 5409104SN/A case CacheRequestType_DataArrayRead: 54110978Sdavid.hashe@amd.com if (m_resource_stalls) 54210978Sdavid.hashe@amd.com dataArray.reserve(addressToCacheSet(addr)); 5439104SN/A numDataArrayReads++; 5449104SN/A return; 5459104SN/A case CacheRequestType_DataArrayWrite: 54610978Sdavid.hashe@amd.com if (m_resource_stalls) 54710978Sdavid.hashe@amd.com dataArray.reserve(addressToCacheSet(addr)); 5489104SN/A numDataArrayWrites++; 5499104SN/A return; 5509104SN/A case CacheRequestType_TagArrayRead: 55110978Sdavid.hashe@amd.com if (m_resource_stalls) 55210978Sdavid.hashe@amd.com tagArray.reserve(addressToCacheSet(addr)); 5539104SN/A numTagArrayReads++; 5549104SN/A return; 5559104SN/A case CacheRequestType_TagArrayWrite: 55610978Sdavid.hashe@amd.com if (m_resource_stalls) 55710978Sdavid.hashe@amd.com tagArray.reserve(addressToCacheSet(addr)); 5589104SN/A numTagArrayWrites++; 5599104SN/A return; 5609104SN/A default: 5619104SN/A warn("CacheMemory access_type not found: %s", 5629104SN/A CacheRequestType_to_string(requestType)); 5639104SN/A } 5649104SN/A} 5659104SN/A 5669105SN/Abool 56711025Snilay@cs.wisc.eduCacheMemory::checkResourceAvailable(CacheResourceType res, Addr addr) 5689105SN/A{ 5699105SN/A if (!m_resource_stalls) { 5709105SN/A return true; 5719105SN/A } 5729105SN/A 5739105SN/A if (res == CacheResourceType_TagArray) { 5749105SN/A if (tagArray.tryAccess(addressToCacheSet(addr))) return true; 5759105SN/A else { 5769692SN/A DPRINTF(RubyResourceStalls, 5779692SN/A "Tag array stall on addr %s in set %d\n", 5789692SN/A addr, addressToCacheSet(addr)); 5799105SN/A numTagArrayStalls++; 5809105SN/A return false; 5819105SN/A } 5829105SN/A } else if (res == CacheResourceType_DataArray) { 5839105SN/A if (dataArray.tryAccess(addressToCacheSet(addr))) return true; 5849105SN/A else { 5859692SN/A DPRINTF(RubyResourceStalls, 5869692SN/A "Data array stall on addr %s in set %d\n", 5879692SN/A addr, addressToCacheSet(addr)); 5889105SN/A numDataArrayStalls++; 5899105SN/A return false; 5909105SN/A } 5919105SN/A } else { 5929105SN/A assert(false); 5939105SN/A return true; 5949105SN/A } 5959105SN/A} 59610980Sdavid.hashe@amd.com 59710980Sdavid.hashe@amd.combool 59811061Snilay@cs.wisc.eduCacheMemory::isBlockInvalid(int64_t cache_set, int64_t loc) 59910980Sdavid.hashe@amd.com{ 60010980Sdavid.hashe@amd.com return (m_cache[cache_set][loc]->m_Permission == AccessPermission_Invalid); 60110980Sdavid.hashe@amd.com} 60210980Sdavid.hashe@amd.com 60310980Sdavid.hashe@amd.combool 60411061Snilay@cs.wisc.eduCacheMemory::isBlockNotBusy(int64_t cache_set, int64_t loc) 60510980Sdavid.hashe@amd.com{ 60610980Sdavid.hashe@amd.com return (m_cache[cache_set][loc]->m_Permission != AccessPermission_Busy); 60710980Sdavid.hashe@amd.com} 608