CacheMemory.cc revision 10314
16782SN/A/* 28683SN/A * Copyright (c) 1999-2012 Mark D. Hill and David A. Wood 36782SN/A * All rights reserved. 46782SN/A * 56782SN/A * Redistribution and use in source and binary forms, with or without 66782SN/A * modification, are permitted provided that the following conditions are 76782SN/A * met: redistributions of source code must retain the above copyright 86782SN/A * notice, this list of conditions and the following disclaimer; 96782SN/A * redistributions in binary form must reproduce the above copyright 106782SN/A * notice, this list of conditions and the following disclaimer in the 116782SN/A * documentation and/or other materials provided with the distribution; 126782SN/A * neither the name of the copyright holders nor the names of its 136782SN/A * contributors may be used to endorse or promote products derived from 146782SN/A * this software without specific prior written permission. 156782SN/A * 166782SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 176782SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 186782SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 196782SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 206782SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 216782SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 226782SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 236782SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 246782SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 256782SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 266782SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 276782SN/A */ 286782SN/A 297056SN/A#include "base/intmath.hh" 308232SN/A#include "debug/RubyCache.hh" 318937SN/A#include "debug/RubyCacheTrace.hh" 329105SN/A#include "debug/RubyResourceStalls.hh" 339104SN/A#include "debug/RubyStats.hh" 348683SN/A#include "mem/protocol/AccessPermission.hh" 3510301Snilay@cs.wisc.edu#include "mem/ruby/structures/CacheMemory.hh" 368683SN/A#include "mem/ruby/system/System.hh" 376782SN/A 387055SN/Ausing namespace std; 397055SN/A 407039SN/Aostream& 417039SN/Aoperator<<(ostream& out, const CacheMemory& obj) 426782SN/A{ 437039SN/A obj.print(out); 447039SN/A out << flush; 457039SN/A return out; 466782SN/A} 476782SN/A 486876SN/ACacheMemory * 496876SN/ARubyCacheParams::create() 506782SN/A{ 516876SN/A return new CacheMemory(this); 526782SN/A} 536782SN/A 546876SN/ACacheMemory::CacheMemory(const Params *p) 559105SN/A : SimObject(p), 569105SN/A dataArray(p->dataArrayBanks, p->dataAccessLatency, p->start_index_bit), 579105SN/A tagArray(p->tagArrayBanks, p->tagAccessLatency, p->start_index_bit) 586782SN/A{ 596882SN/A m_cache_size = p->size; 606876SN/A m_latency = p->latency; 616876SN/A m_cache_assoc = p->assoc; 626882SN/A m_policy = p->replacement_policy; 637564SN/A m_start_index_bit = p->start_index_bit; 648653SN/A m_is_instruction_only_cache = p->is_icache; 659105SN/A m_resource_stalls = p->resourceStalls; 666876SN/A} 676876SN/A 687039SN/Avoid 697039SN/ACacheMemory::init() 706876SN/A{ 717039SN/A m_cache_num_sets = (m_cache_size / m_cache_assoc) / 727039SN/A RubySystem::getBlockSizeBytes(); 736882SN/A assert(m_cache_num_sets > 1); 747056SN/A m_cache_num_set_bits = floorLog2(m_cache_num_sets); 756882SN/A assert(m_cache_num_set_bits > 0); 767039SN/A 777039SN/A if (m_policy == "PSEUDO_LRU") 787039SN/A m_replacementPolicy_ptr = 797039SN/A new PseudoLRUPolicy(m_cache_num_sets, m_cache_assoc); 806882SN/A else if (m_policy == "LRU") 817039SN/A m_replacementPolicy_ptr = 827039SN/A new LRUPolicy(m_cache_num_sets, m_cache_assoc); 836882SN/A else 847039SN/A assert(false); 856882SN/A 867454SN/A m_cache.resize(m_cache_num_sets); 877039SN/A for (int i = 0; i < m_cache_num_sets; i++) { 887454SN/A m_cache[i].resize(m_cache_assoc); 897039SN/A for (int j = 0; j < m_cache_assoc; j++) { 907039SN/A m_cache[i][j] = NULL; 917039SN/A } 926782SN/A } 936782SN/A} 946782SN/A 956782SN/ACacheMemory::~CacheMemory() 966782SN/A{ 977039SN/A if (m_replacementPolicy_ptr != NULL) 987039SN/A delete m_replacementPolicy_ptr; 997039SN/A for (int i = 0; i < m_cache_num_sets; i++) { 1007039SN/A for (int j = 0; j < m_cache_assoc; j++) { 1017039SN/A delete m_cache[i][j]; 1027039SN/A } 1036783SN/A } 1046782SN/A} 1056782SN/A 1066782SN/A// convert a Address to its location in the cache 10710314Snilay@cs.wisc.eduint64 1087039SN/ACacheMemory::addressToCacheSet(const Address& address) const 1096782SN/A{ 1107039SN/A assert(address == line_address(address)); 1117564SN/A return address.bitSelect(m_start_index_bit, 1127564SN/A m_start_index_bit + m_cache_num_set_bits - 1); 1136782SN/A} 1146782SN/A 1156782SN/A// Given a cache index: returns the index of the tag in a set. 1166782SN/A// returns -1 if the tag is not found. 1177039SN/Aint 11810314Snilay@cs.wisc.eduCacheMemory::findTagInSet(int64 cacheSet, const Address& tag) const 1196782SN/A{ 1207039SN/A assert(tag == line_address(tag)); 1217039SN/A // search the set for the tags 1227039SN/A m5::hash_map<Address, int>::const_iterator it = m_tag_index.find(tag); 1237039SN/A if (it != m_tag_index.end()) 1247039SN/A if (m_cache[cacheSet][it->second]->m_Permission != 1257039SN/A AccessPermission_NotPresent) 1267039SN/A return it->second; 1277039SN/A return -1; // Not found 1286782SN/A} 1296782SN/A 1306782SN/A// Given a cache index: returns the index of the tag in a set. 1316782SN/A// returns -1 if the tag is not found. 1327039SN/Aint 13310314Snilay@cs.wisc.eduCacheMemory::findTagInSetIgnorePermissions(int64 cacheSet, 1347039SN/A const Address& tag) const 1356782SN/A{ 1367039SN/A assert(tag == line_address(tag)); 1377039SN/A // search the set for the tags 1387039SN/A m5::hash_map<Address, int>::const_iterator it = m_tag_index.find(tag); 1397039SN/A if (it != m_tag_index.end()) 1407039SN/A return it->second; 1417039SN/A return -1; // Not found 1426782SN/A} 1436782SN/A 1447039SN/Abool 1458165SN/ACacheMemory::tryCacheAccess(const Address& address, RubyRequestType type, 1467039SN/A DataBlock*& data_ptr) 1476782SN/A{ 1487039SN/A assert(address == line_address(address)); 1497780SN/A DPRINTF(RubyCache, "address: %s\n", address); 15010314Snilay@cs.wisc.edu int64 cacheSet = addressToCacheSet(address); 1517039SN/A int loc = findTagInSet(cacheSet, address); 1527039SN/A if (loc != -1) { 1537039SN/A // Do we even have a tag match? 1547039SN/A AbstractCacheEntry* entry = m_cache[cacheSet][loc]; 1559171SN/A m_replacementPolicy_ptr->touch(cacheSet, loc, curTick()); 1567039SN/A data_ptr = &(entry->getDataBlk()); 1576782SN/A 1587039SN/A if (entry->m_Permission == AccessPermission_Read_Write) { 1597039SN/A return true; 1607039SN/A } 1617039SN/A if ((entry->m_Permission == AccessPermission_Read_Only) && 1628165SN/A (type == RubyRequestType_LD || type == RubyRequestType_IFETCH)) { 1637039SN/A return true; 1647039SN/A } 1657039SN/A // The line must not be accessible 1666782SN/A } 1677039SN/A data_ptr = NULL; 1687039SN/A return false; 1696782SN/A} 1706782SN/A 1717039SN/Abool 1728165SN/ACacheMemory::testCacheAccess(const Address& address, RubyRequestType type, 1737039SN/A DataBlock*& data_ptr) 1746782SN/A{ 1757039SN/A assert(address == line_address(address)); 1767780SN/A DPRINTF(RubyCache, "address: %s\n", address); 17710314Snilay@cs.wisc.edu int64 cacheSet = addressToCacheSet(address); 1787039SN/A int loc = findTagInSet(cacheSet, address); 1796782SN/A 1807039SN/A if (loc != -1) { 1817039SN/A // Do we even have a tag match? 1827039SN/A AbstractCacheEntry* entry = m_cache[cacheSet][loc]; 1839171SN/A m_replacementPolicy_ptr->touch(cacheSet, loc, curTick()); 1847039SN/A data_ptr = &(entry->getDataBlk()); 1857039SN/A 1867039SN/A return m_cache[cacheSet][loc]->m_Permission != 1877039SN/A AccessPermission_NotPresent; 1887039SN/A } 1897039SN/A 1907039SN/A data_ptr = NULL; 1917039SN/A return false; 1926782SN/A} 1936782SN/A 1946782SN/A// tests to see if an address is present in the cache 1957039SN/Abool 1967039SN/ACacheMemory::isTagPresent(const Address& address) const 1976782SN/A{ 1987039SN/A assert(address == line_address(address)); 19910314Snilay@cs.wisc.edu int64 cacheSet = addressToCacheSet(address); 2007039SN/A int loc = findTagInSet(cacheSet, address); 2016782SN/A 2027039SN/A if (loc == -1) { 2037039SN/A // We didn't find the tag 2047780SN/A DPRINTF(RubyCache, "No tag match for address: %s\n", address); 2057039SN/A return false; 2067039SN/A } 2077780SN/A DPRINTF(RubyCache, "address: %s found\n", address); 2087039SN/A return true; 2096782SN/A} 2106782SN/A 2116782SN/A// Returns true if there is: 2126782SN/A// a) a tag match on this address or there is 2136782SN/A// b) an unused line in the same cache "way" 2147039SN/Abool 2157039SN/ACacheMemory::cacheAvail(const Address& address) const 2166782SN/A{ 2177039SN/A assert(address == line_address(address)); 2186782SN/A 21910314Snilay@cs.wisc.edu int64 cacheSet = addressToCacheSet(address); 2206782SN/A 2217039SN/A for (int i = 0; i < m_cache_assoc; i++) { 2227039SN/A AbstractCacheEntry* entry = m_cache[cacheSet][i]; 2237039SN/A if (entry != NULL) { 2247039SN/A if (entry->m_Address == address || 2257039SN/A entry->m_Permission == AccessPermission_NotPresent) { 2267039SN/A // Already in the cache or we found an empty entry 2277039SN/A return true; 2287039SN/A } 2297039SN/A } else { 2307039SN/A return true; 2317039SN/A } 2326782SN/A } 2337039SN/A return false; 2346782SN/A} 2356782SN/A 2367839SN/AAbstractCacheEntry* 2377039SN/ACacheMemory::allocate(const Address& address, AbstractCacheEntry* entry) 2386782SN/A{ 2397039SN/A assert(address == line_address(address)); 2407039SN/A assert(!isTagPresent(address)); 2417039SN/A assert(cacheAvail(address)); 2427780SN/A DPRINTF(RubyCache, "address: %s\n", address); 2436782SN/A 2447039SN/A // Find the first open slot 24510314Snilay@cs.wisc.edu int64 cacheSet = addressToCacheSet(address); 2467454SN/A std::vector<AbstractCacheEntry*> &set = m_cache[cacheSet]; 2477039SN/A for (int i = 0; i < m_cache_assoc; i++) { 2487039SN/A if (!set[i] || set[i]->m_Permission == AccessPermission_NotPresent) { 2497039SN/A set[i] = entry; // Init entry 2507039SN/A set[i]->m_Address = address; 2517039SN/A set[i]->m_Permission = AccessPermission_Invalid; 2527039SN/A DPRINTF(RubyCache, "Allocate clearing lock for addr: %x\n", 2537039SN/A address); 2547839SN/A set[i]->m_locked = -1; 2557039SN/A m_tag_index[address] = i; 2566782SN/A 2579171SN/A m_replacementPolicy_ptr->touch(cacheSet, i, curTick()); 2586782SN/A 2597839SN/A return entry; 2607039SN/A } 2616782SN/A } 2627805SN/A panic("Allocate didn't find an available entry"); 2636782SN/A} 2646782SN/A 2657039SN/Avoid 2667039SN/ACacheMemory::deallocate(const Address& address) 2676782SN/A{ 2687039SN/A assert(address == line_address(address)); 2697039SN/A assert(isTagPresent(address)); 2707780SN/A DPRINTF(RubyCache, "address: %s\n", address); 27110314Snilay@cs.wisc.edu int64 cacheSet = addressToCacheSet(address); 2727039SN/A int loc = findTagInSet(cacheSet, address); 2737039SN/A if (loc != -1) { 2747039SN/A delete m_cache[cacheSet][loc]; 2757039SN/A m_cache[cacheSet][loc] = NULL; 2767039SN/A m_tag_index.erase(address); 2777039SN/A } 2786782SN/A} 2796782SN/A 2806782SN/A// Returns with the physical address of the conflicting cache line 2817039SN/AAddress 2827039SN/ACacheMemory::cacheProbe(const Address& address) const 2836782SN/A{ 2847039SN/A assert(address == line_address(address)); 2857039SN/A assert(!cacheAvail(address)); 2866782SN/A 28710314Snilay@cs.wisc.edu int64 cacheSet = addressToCacheSet(address); 2887039SN/A return m_cache[cacheSet][m_replacementPolicy_ptr->getVictim(cacheSet)]-> 2897039SN/A m_Address; 2906782SN/A} 2916782SN/A 2926782SN/A// looks an address up in the cache 2937839SN/AAbstractCacheEntry* 2947039SN/ACacheMemory::lookup(const Address& address) 2956782SN/A{ 2967039SN/A assert(address == line_address(address)); 29710314Snilay@cs.wisc.edu int64 cacheSet = addressToCacheSet(address); 2987039SN/A int loc = findTagInSet(cacheSet, address); 2997839SN/A if(loc == -1) return NULL; 3007839SN/A return m_cache[cacheSet][loc]; 3016782SN/A} 3026782SN/A 3036782SN/A// looks an address up in the cache 3047839SN/Aconst AbstractCacheEntry* 3057039SN/ACacheMemory::lookup(const Address& address) const 3066782SN/A{ 3077039SN/A assert(address == line_address(address)); 30810314Snilay@cs.wisc.edu int64 cacheSet = addressToCacheSet(address); 3097039SN/A int loc = findTagInSet(cacheSet, address); 3107839SN/A if(loc == -1) return NULL; 3117839SN/A return m_cache[cacheSet][loc]; 3126782SN/A} 3136782SN/A 3146782SN/A// Sets the most recently used bit for a cache block 3157039SN/Avoid 3167039SN/ACacheMemory::setMRU(const Address& address) 3176782SN/A{ 31810314Snilay@cs.wisc.edu int64 cacheSet = addressToCacheSet(address); 3198828SN/A int loc = findTagInSet(cacheSet, address); 3206782SN/A 3218828SN/A if(loc != -1) 3229171SN/A m_replacementPolicy_ptr->touch(cacheSet, loc, curTick()); 3236782SN/A} 3246782SN/A 3257039SN/Avoid 3268683SN/ACacheMemory::recordCacheContents(int cntrl, CacheRecorder* tr) const 3276782SN/A{ 3288683SN/A uint64 warmedUpBlocks = 0; 3298683SN/A uint64 totalBlocks M5_VAR_USED = (uint64)m_cache_num_sets 3308683SN/A * (uint64)m_cache_assoc; 3318683SN/A 3327039SN/A for (int i = 0; i < m_cache_num_sets; i++) { 3337039SN/A for (int j = 0; j < m_cache_assoc; j++) { 3348683SN/A if (m_cache[i][j] != NULL) { 3358683SN/A AccessPermission perm = m_cache[i][j]->m_Permission; 3368683SN/A RubyRequestType request_type = RubyRequestType_NULL; 3378683SN/A if (perm == AccessPermission_Read_Only) { 3388683SN/A if (m_is_instruction_only_cache) { 3398683SN/A request_type = RubyRequestType_IFETCH; 3408683SN/A } else { 3418683SN/A request_type = RubyRequestType_LD; 3428683SN/A } 3438683SN/A } else if (perm == AccessPermission_Read_Write) { 3448683SN/A request_type = RubyRequestType_ST; 3457039SN/A } 3467039SN/A 3478683SN/A if (request_type != RubyRequestType_NULL) { 3488683SN/A tr->addRecord(cntrl, m_cache[i][j]->m_Address.getAddress(), 3498683SN/A 0, request_type, 3508683SN/A m_replacementPolicy_ptr->getLastAccess(i, j), 3518683SN/A m_cache[i][j]->getDataBlk()); 3528683SN/A warmedUpBlocks++; 3538683SN/A } 3547039SN/A } 3556782SN/A } 3566782SN/A } 3578683SN/A 3588937SN/A DPRINTF(RubyCacheTrace, "%s: %lli blocks of %lli total blocks" 3598683SN/A "recorded %.2f%% \n", name().c_str(), warmedUpBlocks, 3608683SN/A (uint64)m_cache_num_sets * (uint64)m_cache_assoc, 3618683SN/A (float(warmedUpBlocks)/float(totalBlocks))*100.0); 3626782SN/A} 3636782SN/A 3647039SN/Avoid 3657039SN/ACacheMemory::print(ostream& out) const 3666782SN/A{ 36710080SN/A out << "Cache dump: " << name() << endl; 3687039SN/A for (int i = 0; i < m_cache_num_sets; i++) { 3697039SN/A for (int j = 0; j < m_cache_assoc; j++) { 3707039SN/A if (m_cache[i][j] != NULL) { 3717039SN/A out << " Index: " << i 3727039SN/A << " way: " << j 3737039SN/A << " entry: " << *m_cache[i][j] << endl; 3747039SN/A } else { 3757039SN/A out << " Index: " << i 3767039SN/A << " way: " << j 3777039SN/A << " entry: NULL" << endl; 3787039SN/A } 3797039SN/A } 3806782SN/A } 3816782SN/A} 3826782SN/A 3837039SN/Avoid 3847039SN/ACacheMemory::printData(ostream& out) const 3856782SN/A{ 3867039SN/A out << "printData() not supported" << endl; 3876782SN/A} 3886782SN/A 3897039SN/Avoid 3907039SN/ACacheMemory::setLocked(const Address& address, int context) 3917039SN/A{ 3927039SN/A DPRINTF(RubyCache, "Setting Lock for addr: %x to %d\n", address, context); 3937039SN/A assert(address == line_address(address)); 39410314Snilay@cs.wisc.edu int64 cacheSet = addressToCacheSet(address); 3957039SN/A int loc = findTagInSet(cacheSet, address); 3967039SN/A assert(loc != -1); 3977839SN/A m_cache[cacheSet][loc]->m_locked = context; 3986782SN/A} 3996782SN/A 4007039SN/Avoid 4017039SN/ACacheMemory::clearLocked(const Address& address) 4026782SN/A{ 4037039SN/A DPRINTF(RubyCache, "Clear Lock for addr: %x\n", address); 4047039SN/A assert(address == line_address(address)); 40510314Snilay@cs.wisc.edu int64 cacheSet = addressToCacheSet(address); 4067039SN/A int loc = findTagInSet(cacheSet, address); 4077039SN/A assert(loc != -1); 4087839SN/A m_cache[cacheSet][loc]->m_locked = -1; 4096782SN/A} 4106782SN/A 4116782SN/Abool 4126782SN/ACacheMemory::isLocked(const Address& address, int context) 4136782SN/A{ 4147039SN/A assert(address == line_address(address)); 41510314Snilay@cs.wisc.edu int64 cacheSet = addressToCacheSet(address); 4167039SN/A int loc = findTagInSet(cacheSet, address); 4177039SN/A assert(loc != -1); 4187039SN/A DPRINTF(RubyCache, "Testing Lock for addr: %llx cur %d con %d\n", 4197839SN/A address, m_cache[cacheSet][loc]->m_locked, context); 4207839SN/A return m_cache[cacheSet][loc]->m_locked == context; 4216782SN/A} 4226782SN/A 4239104SN/Avoid 4249692SN/ACacheMemory::regStats() 4259692SN/A{ 4269692SN/A m_demand_hits 4279692SN/A .name(name() + ".demand_hits") 4289692SN/A .desc("Number of cache demand hits") 4299692SN/A ; 4309692SN/A 4319692SN/A m_demand_misses 4329692SN/A .name(name() + ".demand_misses") 4339692SN/A .desc("Number of cache demand misses") 4349692SN/A ; 4359692SN/A 4369692SN/A m_demand_accesses 4379692SN/A .name(name() + ".demand_accesses") 4389692SN/A .desc("Number of cache demand accesses") 4399692SN/A ; 4409692SN/A 4419692SN/A m_demand_accesses = m_demand_hits + m_demand_misses; 4429692SN/A 4439692SN/A m_sw_prefetches 4449692SN/A .name(name() + ".total_sw_prefetches") 4459692SN/A .desc("Number of software prefetches") 4469692SN/A .flags(Stats::nozero) 4479692SN/A ; 4489692SN/A 4499692SN/A m_hw_prefetches 4509692SN/A .name(name() + ".total_hw_prefetches") 4519692SN/A .desc("Number of hardware prefetches") 4529692SN/A .flags(Stats::nozero) 4539692SN/A ; 4549692SN/A 4559692SN/A m_prefetches 4569692SN/A .name(name() + ".total_prefetches") 4579692SN/A .desc("Number of prefetches") 4589692SN/A .flags(Stats::nozero) 4599692SN/A ; 4609692SN/A 4619692SN/A m_prefetches = m_sw_prefetches + m_hw_prefetches; 4629692SN/A 4639692SN/A m_accessModeType 4649692SN/A .init(RubyRequestType_NUM) 4659692SN/A .name(name() + ".access_mode") 4669692SN/A .flags(Stats::pdf | Stats::total) 4679692SN/A ; 4689692SN/A for (int i = 0; i < RubyAccessMode_NUM; i++) { 4699692SN/A m_accessModeType 4709692SN/A .subname(i, RubyAccessMode_to_string(RubyAccessMode(i))) 4719692SN/A .flags(Stats::nozero) 4729692SN/A ; 4739692SN/A } 4749692SN/A 4759692SN/A numDataArrayReads 4769692SN/A .name(name() + ".num_data_array_reads") 4779692SN/A .desc("number of data array reads") 4789692SN/A .flags(Stats::nozero) 4799692SN/A ; 4809692SN/A 4819692SN/A numDataArrayWrites 4829692SN/A .name(name() + ".num_data_array_writes") 4839692SN/A .desc("number of data array writes") 4849692SN/A .flags(Stats::nozero) 4859692SN/A ; 4869692SN/A 4879692SN/A numTagArrayReads 4889692SN/A .name(name() + ".num_tag_array_reads") 4899692SN/A .desc("number of tag array reads") 4909692SN/A .flags(Stats::nozero) 4919692SN/A ; 4929692SN/A 4939692SN/A numTagArrayWrites 4949692SN/A .name(name() + ".num_tag_array_writes") 4959692SN/A .desc("number of tag array writes") 4969692SN/A .flags(Stats::nozero) 4979692SN/A ; 4989692SN/A 4999692SN/A numTagArrayStalls 5009692SN/A .name(name() + ".num_tag_array_stalls") 5019692SN/A .desc("number of stalls caused by tag array") 5029692SN/A .flags(Stats::nozero) 5039692SN/A ; 5049692SN/A 5059692SN/A numDataArrayStalls 5069692SN/A .name(name() + ".num_data_array_stalls") 5079692SN/A .desc("number of stalls caused by data array") 5089692SN/A .flags(Stats::nozero) 5099692SN/A ; 5109692SN/A} 5119692SN/A 5129692SN/Avoid 5139692SN/ACacheMemory::recordRequestType(CacheRequestType requestType) 5149692SN/A{ 5159104SN/A DPRINTF(RubyStats, "Recorded statistic: %s\n", 5169104SN/A CacheRequestType_to_string(requestType)); 5179104SN/A switch(requestType) { 5189104SN/A case CacheRequestType_DataArrayRead: 5199104SN/A numDataArrayReads++; 5209104SN/A return; 5219104SN/A case CacheRequestType_DataArrayWrite: 5229104SN/A numDataArrayWrites++; 5239104SN/A return; 5249104SN/A case CacheRequestType_TagArrayRead: 5259104SN/A numTagArrayReads++; 5269104SN/A return; 5279104SN/A case CacheRequestType_TagArrayWrite: 5289104SN/A numTagArrayWrites++; 5299104SN/A return; 5309104SN/A default: 5319104SN/A warn("CacheMemory access_type not found: %s", 5329104SN/A CacheRequestType_to_string(requestType)); 5339104SN/A } 5349104SN/A} 5359104SN/A 5369105SN/Abool 5379105SN/ACacheMemory::checkResourceAvailable(CacheResourceType res, Address addr) 5389105SN/A{ 5399105SN/A if (!m_resource_stalls) { 5409105SN/A return true; 5419105SN/A } 5429105SN/A 5439105SN/A if (res == CacheResourceType_TagArray) { 5449105SN/A if (tagArray.tryAccess(addressToCacheSet(addr))) return true; 5459105SN/A else { 5469692SN/A DPRINTF(RubyResourceStalls, 5479692SN/A "Tag array stall on addr %s in set %d\n", 5489692SN/A addr, addressToCacheSet(addr)); 5499105SN/A numTagArrayStalls++; 5509105SN/A return false; 5519105SN/A } 5529105SN/A } else if (res == CacheResourceType_DataArray) { 5539105SN/A if (dataArray.tryAccess(addressToCacheSet(addr))) return true; 5549105SN/A else { 5559692SN/A DPRINTF(RubyResourceStalls, 5569692SN/A "Data array stall on addr %s in set %d\n", 5579692SN/A addr, addressToCacheSet(addr)); 5589105SN/A numDataArrayStalls++; 5599105SN/A return false; 5609105SN/A } 5619105SN/A } else { 5629105SN/A assert(false); 5639105SN/A return true; 5649105SN/A } 5659105SN/A} 566