CacheMemory.cc revision 10974
16145Snate@binkert.org/* 26145Snate@binkert.org * Copyright (c) 1999-2012 Mark D. Hill and David A. Wood 36145Snate@binkert.org * Copyright (c) 2013 Advanced Micro Devices, Inc. 46145Snate@binkert.org * All rights reserved. 56145Snate@binkert.org * 66145Snate@binkert.org * Redistribution and use in source and binary forms, with or without 76145Snate@binkert.org * modification, are permitted provided that the following conditions are 86145Snate@binkert.org * met: redistributions of source code must retain the above copyright 96145Snate@binkert.org * notice, this list of conditions and the following disclaimer; 106145Snate@binkert.org * redistributions in binary form must reproduce the above copyright 116145Snate@binkert.org * notice, this list of conditions and the following disclaimer in the 126145Snate@binkert.org * documentation and/or other materials provided with the distribution; 136145Snate@binkert.org * neither the name of the copyright holders nor the names of its 146145Snate@binkert.org * contributors may be used to endorse or promote products derived from 156145Snate@binkert.org * this software without specific prior written permission. 166145Snate@binkert.org * 176145Snate@binkert.org * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 186145Snate@binkert.org * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 196145Snate@binkert.org * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 206145Snate@binkert.org * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 216145Snate@binkert.org * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 226145Snate@binkert.org * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 236145Snate@binkert.org * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 246145Snate@binkert.org * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 256145Snate@binkert.org * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 266145Snate@binkert.org * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 276145Snate@binkert.org * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 286145Snate@binkert.org */ 298229Snate@binkert.org 307056Snate@binkert.org#include "base/intmath.hh" 318615Snilay@cs.wisc.edu#include "debug/RubyCache.hh" 328615Snilay@cs.wisc.edu#include "debug/RubyCacheTrace.hh" 338615Snilay@cs.wisc.edu#include "debug/RubyResourceStalls.hh" 348615Snilay@cs.wisc.edu#include "debug/RubyStats.hh" 357632SBrad.Beckmann@amd.com#include "mem/protocol/AccessPermission.hh" 368232Snate@binkert.org#include "mem/ruby/structures/CacheMemory.hh" 378232Snate@binkert.org#include "mem/ruby/system/System.hh" 388615Snilay@cs.wisc.edu 399104Shestness@cs.utexas.eduusing namespace std; 408615Snilay@cs.wisc.edu 418615Snilay@cs.wisc.eduostream& 427039Snate@binkert.orgoperator<<(ostream& out, const CacheMemory& obj) 437039Snate@binkert.org{ 447039Snate@binkert.org obj.print(out); 458229Snate@binkert.org out << flush; 466154Snate@binkert.org return out; 476154Snate@binkert.org} 487550SBrad.Beckmann@amd.com 496876Ssteve.reinhardt@amd.comCacheMemory * 507055Snate@binkert.orgRubyCacheParams::create() 517055Snate@binkert.org{ 526876Ssteve.reinhardt@amd.com return new CacheMemory(this); 536876Ssteve.reinhardt@amd.com} 546285Snate@binkert.org 556876Ssteve.reinhardt@amd.comCacheMemory::CacheMemory(const Params *p) 566285Snate@binkert.org : SimObject(p), 577039Snate@binkert.org dataArray(p->dataArrayBanks, p->dataAccessLatency, 586876Ssteve.reinhardt@amd.com p->start_index_bit, p->ruby_system), 596886SBrad.Beckmann@amd.com tagArray(p->tagArrayBanks, p->tagAccessLatency, 606876Ssteve.reinhardt@amd.com p->start_index_bit, p->ruby_system) 616876Ssteve.reinhardt@amd.com{ 626876Ssteve.reinhardt@amd.com m_cache_size = p->size; 636876Ssteve.reinhardt@amd.com m_latency = p->latency; 646876Ssteve.reinhardt@amd.com m_cache_assoc = p->assoc; 657039Snate@binkert.org m_replacementPolicy_ptr = p->replacement_policy; 666876Ssteve.reinhardt@amd.com m_start_index_bit = p->start_index_bit; 676285Snate@binkert.org m_is_instruction_only_cache = p->is_icache; 686876Ssteve.reinhardt@amd.com m_resource_stalls = p->resourceStalls; 696876Ssteve.reinhardt@amd.com} 706876Ssteve.reinhardt@amd.com 716876Ssteve.reinhardt@amd.comvoid 726899SBrad.Beckmann@amd.comCacheMemory::init() 736876Ssteve.reinhardt@amd.com{ 746876Ssteve.reinhardt@amd.com m_cache_num_sets = (m_cache_size / m_cache_assoc) / 756876Ssteve.reinhardt@amd.com RubySystem::getBlockSizeBytes(); 766876Ssteve.reinhardt@amd.com assert(m_cache_num_sets > 1); 778171Stushar@csail.mit.edu m_cache_num_set_bits = floorLog2(m_cache_num_sets); 788171Stushar@csail.mit.edu assert(m_cache_num_set_bits > 0); 796145Snate@binkert.org 806145Snate@binkert.org m_cache.resize(m_cache_num_sets); 817039Snate@binkert.org for (int i = 0; i < m_cache_num_sets; i++) { 827039Snate@binkert.org m_cache[i].resize(m_cache_assoc); 836145Snate@binkert.org for (int j = 0; j < m_cache_assoc; j++) { 846145Snate@binkert.org m_cache[i][j] = NULL; 857039Snate@binkert.org } 867039Snate@binkert.org } 877039Snate@binkert.org} 887039Snate@binkert.org 899171Snilay@cs.wisc.eduCacheMemory::~CacheMemory() 906145Snate@binkert.org{ 917039Snate@binkert.org if (m_replacementPolicy_ptr != NULL) 927039Snate@binkert.org delete m_replacementPolicy_ptr; 936285Snate@binkert.org for (int i = 0; i < m_cache_num_sets; i++) { 947455Snate@binkert.org for (int j = 0; j < m_cache_assoc; j++) { 957455Snate@binkert.org delete m_cache[i][j]; 967455Snate@binkert.org } 977455Snate@binkert.org } 987455Snate@binkert.org} 997455Snate@binkert.org 1007455Snate@binkert.org// convert a Address to its location in the cache 1017805Snilay@cs.wisc.eduint64 1027921SBrad.Beckmann@amd.comCacheMemory::addressToCacheSet(const Address& address) const 1037805Snilay@cs.wisc.edu{ 1048615Snilay@cs.wisc.edu assert(address == line_address(address)); 1057805Snilay@cs.wisc.edu return address.bitSelect(m_start_index_bit, 1067805Snilay@cs.wisc.edu m_start_index_bit + m_cache_num_set_bits - 1); 1076145Snate@binkert.org} 1086145Snate@binkert.org 1097455Snate@binkert.org// Given a cache index: returns the index of the tag in a set. 1107455Snate@binkert.org// returns -1 if the tag is not found. 1117455Snate@binkert.orgint 1127455Snate@binkert.orgCacheMemory::findTagInSet(int64 cacheSet, const Address& tag) const 1137455Snate@binkert.org{ 1147455Snate@binkert.org assert(tag == line_address(tag)); 1157455Snate@binkert.org // search the set for the tags 1167805Snilay@cs.wisc.edu m5::hash_map<Address, int>::const_iterator it = m_tag_index.find(tag); 1177921SBrad.Beckmann@amd.com if (it != m_tag_index.end()) 1187805Snilay@cs.wisc.edu if (m_cache[cacheSet][it->second]->m_Permission != 1198615Snilay@cs.wisc.edu AccessPermission_NotPresent) 1207805Snilay@cs.wisc.edu return it->second; 1217805Snilay@cs.wisc.edu return -1; // Not found 1226145Snate@binkert.org} 1236285Snate@binkert.org 1247039Snate@binkert.org// Given a cache index: returns the index of the tag in a set. 1257039Snate@binkert.org// returns -1 if the tag is not found. 1266145Snate@binkert.orgint 1277039Snate@binkert.orgCacheMemory::findTagInSetIgnorePermissions(int64 cacheSet, 1287039Snate@binkert.org const Address& tag) const 1297039Snate@binkert.org{ 1307039Snate@binkert.org assert(tag == line_address(tag)); 1317039Snate@binkert.org // search the set for the tags 1329171Snilay@cs.wisc.edu m5::hash_map<Address, int>::const_iterator it = m_tag_index.find(tag); 1337823Ssteve.reinhardt@amd.com if (it != m_tag_index.end()) 1347039Snate@binkert.org return it->second; 1356145Snate@binkert.org return -1; // Not found 1366145Snate@binkert.org} 1377039Snate@binkert.org 1387039Snate@binkert.org// Given an unique cache block identifier (idx): return the valid address 1397039Snate@binkert.org// stored by the cache block. If the block is invalid/notpresent, the 1407039Snate@binkert.org// function returns the 0 address 1417039Snate@binkert.orgAddress 1427039Snate@binkert.orgCacheMemory::getAddressAtIdx(int idx) const 1437039Snate@binkert.org{ 1447039Snate@binkert.org Address tmp(0); 1457039Snate@binkert.org 1467039Snate@binkert.org int set = idx / m_cache_assoc; 1477039Snate@binkert.org assert(set < m_cache_num_sets); 1487039Snate@binkert.org 1496859Sdrh5@cs.wisc.edu int way = idx - set * m_cache_assoc; 1506859Sdrh5@cs.wisc.edu assert (way < m_cache_assoc); 1517039Snate@binkert.org 1527039Snate@binkert.org AbstractCacheEntry* entry = m_cache[set][way]; 1537039Snate@binkert.org if (entry == NULL || 1547039Snate@binkert.org entry->m_Permission == AccessPermission_Invalid || 1557039Snate@binkert.org entry->m_Permission == AccessPermission_NotPresent) { 1567039Snate@binkert.org return tmp; 1579171Snilay@cs.wisc.edu } 1587039Snate@binkert.org return entry->m_Address; 1597039Snate@binkert.org} 1606145Snate@binkert.org 1617455Snate@binkert.orgbool 1627455Snate@binkert.orgCacheMemory::tryCacheAccess(const Address& address, RubyRequestType type, 1636145Snate@binkert.org DataBlock*& data_ptr) 1647039Snate@binkert.org{ 1657455Snate@binkert.org assert(address == line_address(address)); 1667455Snate@binkert.org DPRINTF(RubyCache, "address: %s\n", address); 1677455Snate@binkert.org int64 cacheSet = addressToCacheSet(address); 1687455Snate@binkert.org int loc = findTagInSet(cacheSet, address); 1697039Snate@binkert.org if (loc != -1) { 1707039Snate@binkert.org // Do we even have a tag match? 1717039Snate@binkert.org AbstractCacheEntry* entry = m_cache[cacheSet][loc]; 1727039Snate@binkert.org m_replacementPolicy_ptr->touch(cacheSet, loc, curTick()); 1736145Snate@binkert.org data_ptr = &(entry->getDataBlk()); 1747039Snate@binkert.org 1756145Snate@binkert.org if (entry->m_Permission == AccessPermission_Read_Write) { 1767455Snate@binkert.org return true; 1777455Snate@binkert.org } 1786285Snate@binkert.org if ((entry->m_Permission == AccessPermission_Read_Only) && 1797039Snate@binkert.org (type == RubyRequestType_LD || type == RubyRequestType_IFETCH)) { 1807455Snate@binkert.org return true; 1817455Snate@binkert.org } 1827455Snate@binkert.org // The line must not be accessible 1837455Snate@binkert.org } 1847039Snate@binkert.org data_ptr = NULL; 1857039Snate@binkert.org return false; 1867039Snate@binkert.org} 1877039Snate@binkert.org 1887039Snate@binkert.orgbool 1897039Snate@binkert.orgCacheMemory::testCacheAccess(const Address& address, RubyRequestType type, 1907039Snate@binkert.org DataBlock*& data_ptr) 1917039Snate@binkert.org{ 1927039Snate@binkert.org assert(address == line_address(address)); 1937039Snate@binkert.org DPRINTF(RubyCache, "address: %s\n", address); 1947039Snate@binkert.org int64 cacheSet = addressToCacheSet(address); 1957039Snate@binkert.org int loc = findTagInSet(cacheSet, address); 1967039Snate@binkert.org 1977039Snate@binkert.org if (loc != -1) { 1987039Snate@binkert.org // Do we even have a tag match? 1997039Snate@binkert.org AbstractCacheEntry* entry = m_cache[cacheSet][loc]; 2006145Snate@binkert.org m_replacementPolicy_ptr->touch(cacheSet, loc, curTick()); 2016145Snate@binkert.org data_ptr = &(entry->getDataBlk()); 2026145Snate@binkert.org 2036145Snate@binkert.org return m_cache[cacheSet][loc]->m_Permission != 2048615Snilay@cs.wisc.edu AccessPermission_NotPresent; 2058615Snilay@cs.wisc.edu } 2067039Snate@binkert.org 2078641Snate@binkert.org data_ptr = NULL; 2088641Snate@binkert.org return false; 2096145Snate@binkert.org} 2107039Snate@binkert.org 2117039Snate@binkert.org// tests to see if an address is present in the cache 2129011Snilay@cs.wisc.edubool 2139171Snilay@cs.wisc.eduCacheMemory::isTagPresent(const Address& address) const 2149011Snilay@cs.wisc.edu{ 2157039Snate@binkert.org assert(address == line_address(address)); 2166145Snate@binkert.org int64 cacheSet = addressToCacheSet(address); 2178615Snilay@cs.wisc.edu int loc = findTagInSet(cacheSet, address); 2187039Snate@binkert.org 2198615Snilay@cs.wisc.edu if (loc == -1) { 2208615Snilay@cs.wisc.edu // We didn't find the tag 2218615Snilay@cs.wisc.edu DPRINTF(RubyCache, "No tag match for address: %s\n", address); 2228615Snilay@cs.wisc.edu return false; 2238615Snilay@cs.wisc.edu } 2248615Snilay@cs.wisc.edu DPRINTF(RubyCache, "address: %s found\n", address); 2258615Snilay@cs.wisc.edu return true; 2268615Snilay@cs.wisc.edu} 2278615Snilay@cs.wisc.edu 2288615Snilay@cs.wisc.edu// Returns true if there is: 2298615Snilay@cs.wisc.edu// a) a tag match on this address or there is 2308615Snilay@cs.wisc.edu// b) an unused line in the same cache "way" 2318615Snilay@cs.wisc.edubool 2328615Snilay@cs.wisc.eduCacheMemory::cacheAvail(const Address& address) const 2338615Snilay@cs.wisc.edu{ 2348615Snilay@cs.wisc.edu assert(address == line_address(address)); 2357455Snate@binkert.org 2367455Snate@binkert.org int64 cacheSet = addressToCacheSet(address); 2378615Snilay@cs.wisc.edu 2388615Snilay@cs.wisc.edu for (int i = 0; i < m_cache_assoc; i++) { 2398615Snilay@cs.wisc.edu AbstractCacheEntry* entry = m_cache[cacheSet][i]; 2409171Snilay@cs.wisc.edu if (entry != NULL) { 2418615Snilay@cs.wisc.edu if (entry->m_Address == address || 2428615Snilay@cs.wisc.edu entry->m_Permission == AccessPermission_NotPresent) { 2438615Snilay@cs.wisc.edu // Already in the cache or we found an empty entry 2448615Snilay@cs.wisc.edu return true; 2458615Snilay@cs.wisc.edu } 2468615Snilay@cs.wisc.edu } else { 2478615Snilay@cs.wisc.edu return true; 2488615Snilay@cs.wisc.edu } 2498615Snilay@cs.wisc.edu } 2508615Snilay@cs.wisc.edu return false; 2518615Snilay@cs.wisc.edu} 2528615Snilay@cs.wisc.edu 2538615Snilay@cs.wisc.eduAbstractCacheEntry* 2547039Snate@binkert.orgCacheMemory::allocate(const Address& address, AbstractCacheEntry* entry, bool touch) 2557455Snate@binkert.org{ 2567455Snate@binkert.org assert(address == line_address(address)); 2577039Snate@binkert.org assert(!isTagPresent(address)); 2588615Snilay@cs.wisc.edu assert(cacheAvail(address)); 2598615Snilay@cs.wisc.edu DPRINTF(RubyCache, "address: %s\n", address); 2608615Snilay@cs.wisc.edu 2619171Snilay@cs.wisc.edu // Find the first open slot 2628615Snilay@cs.wisc.edu int64 cacheSet = addressToCacheSet(address); 2638615Snilay@cs.wisc.edu std::vector<AbstractCacheEntry*> &set = m_cache[cacheSet]; 2648615Snilay@cs.wisc.edu for (int i = 0; i < m_cache_assoc; i++) { 2658615Snilay@cs.wisc.edu if (!set[i] || set[i]->m_Permission == AccessPermission_NotPresent) { 2668615Snilay@cs.wisc.edu set[i] = entry; // Init entry 2677039Snate@binkert.org set[i]->m_Address = address; 2686145Snate@binkert.org set[i]->m_Permission = AccessPermission_Invalid; 2696145Snate@binkert.org DPRINTF(RubyCache, "Allocate clearing lock for addr: %x\n", 2707039Snate@binkert.org address); 2718641Snate@binkert.org set[i]->m_locked = -1; 2728641Snate@binkert.org m_tag_index[address] = i; 2736145Snate@binkert.org 2748615Snilay@cs.wisc.edu if (touch) { 2756145Snate@binkert.org m_replacementPolicy_ptr->touch(cacheSet, i, curTick()); 2766145Snate@binkert.org } 2777039Snate@binkert.org 2787455Snate@binkert.org return entry; 2797455Snate@binkert.org } 2807455Snate@binkert.org } 2817455Snate@binkert.org panic("Allocate didn't find an available entry"); 2827455Snate@binkert.org} 2837455Snate@binkert.org 2847455Snate@binkert.orgvoid 2857455Snate@binkert.orgCacheMemory::deallocate(const Address& address) 2867039Snate@binkert.org{ 2877039Snate@binkert.org assert(address == line_address(address)); 2887039Snate@binkert.org assert(isTagPresent(address)); 2897039Snate@binkert.org DPRINTF(RubyCache, "address: %s\n", address); 2906145Snate@binkert.org int64 cacheSet = addressToCacheSet(address); 2918615Snilay@cs.wisc.edu int loc = findTagInSet(cacheSet, address); 2927039Snate@binkert.org if (loc != -1) { 2938615Snilay@cs.wisc.edu delete m_cache[cacheSet][loc]; 2948615Snilay@cs.wisc.edu m_cache[cacheSet][loc] = NULL; 2958615Snilay@cs.wisc.edu m_tag_index.erase(address); 2968615Snilay@cs.wisc.edu } 2978615Snilay@cs.wisc.edu} 2988615Snilay@cs.wisc.edu 2998615Snilay@cs.wisc.edu// Returns with the physical address of the conflicting cache line 3007455Snate@binkert.orgAddress 3017039Snate@binkert.orgCacheMemory::cacheProbe(const Address& address) const 3027455Snate@binkert.org{ 3037039Snate@binkert.org assert(address == line_address(address)); 3046285Snate@binkert.org assert(!cacheAvail(address)); 3057455Snate@binkert.org 3066145Snate@binkert.org int64 cacheSet = addressToCacheSet(address); 3076145Snate@binkert.org return m_cache[cacheSet][m_replacementPolicy_ptr->getVictim(cacheSet)]-> 3087560SBrad.Beckmann@amd.com m_Address; 3097560SBrad.Beckmann@amd.com} 3107550SBrad.Beckmann@amd.com 3117560SBrad.Beckmann@amd.com// looks an address up in the cache 3127560SBrad.Beckmann@amd.comAbstractCacheEntry* 3137560SBrad.Beckmann@amd.comCacheMemory::lookup(const Address& address) 3147560SBrad.Beckmann@amd.com{ 3157560SBrad.Beckmann@amd.com assert(address == line_address(address)); 3167560SBrad.Beckmann@amd.com int64 cacheSet = addressToCacheSet(address); 3178615Snilay@cs.wisc.edu int loc = findTagInSet(cacheSet, address); 3187550SBrad.Beckmann@amd.com if(loc == -1) return NULL; 3197550SBrad.Beckmann@amd.com return m_cache[cacheSet][loc]; 3207550SBrad.Beckmann@amd.com} 3217550SBrad.Beckmann@amd.com 3227550SBrad.Beckmann@amd.com// looks an address up in the cache 3238615Snilay@cs.wisc.educonst AbstractCacheEntry* 3247560SBrad.Beckmann@amd.comCacheMemory::lookup(const Address& address) const 3257550SBrad.Beckmann@amd.com{ 3267550SBrad.Beckmann@amd.com assert(address == line_address(address)); 3277550SBrad.Beckmann@amd.com int64 cacheSet = addressToCacheSet(address); 3287550SBrad.Beckmann@amd.com int loc = findTagInSet(cacheSet, address); 3297550SBrad.Beckmann@amd.com if(loc == -1) return NULL; 3308615Snilay@cs.wisc.edu return m_cache[cacheSet][loc]; 3317550SBrad.Beckmann@amd.com} 3327560SBrad.Beckmann@amd.com 3337560SBrad.Beckmann@amd.com// Sets the most recently used bit for a cache block 3347560SBrad.Beckmann@amd.comvoid 3357550SBrad.Beckmann@amd.comCacheMemory::setMRU(const Address& address) 3368615Snilay@cs.wisc.edu{ 3377550SBrad.Beckmann@amd.com int64 cacheSet = addressToCacheSet(address); 3387550SBrad.Beckmann@amd.com int loc = findTagInSet(cacheSet, address); 3397550SBrad.Beckmann@amd.com 3407550SBrad.Beckmann@amd.com if(loc != -1) 3417550SBrad.Beckmann@amd.com m_replacementPolicy_ptr->touch(cacheSet, loc, curTick()); 3428615Snilay@cs.wisc.edu} 3438615Snilay@cs.wisc.edu 3447550SBrad.Beckmann@amd.comvoid 3457550SBrad.Beckmann@amd.comCacheMemory::recordCacheContents(int cntrl, CacheRecorder* tr) const 3467550SBrad.Beckmann@amd.com{ 3477550SBrad.Beckmann@amd.com uint64 warmedUpBlocks = 0; 3487550SBrad.Beckmann@amd.com uint64 totalBlocks M5_VAR_USED = (uint64)m_cache_num_sets 3497560SBrad.Beckmann@amd.com * (uint64)m_cache_assoc; 3507550SBrad.Beckmann@amd.com 3517550SBrad.Beckmann@amd.com for (int i = 0; i < m_cache_num_sets; i++) { 3527550SBrad.Beckmann@amd.com for (int j = 0; j < m_cache_assoc; j++) { 3537039Snate@binkert.org if (m_cache[i][j] != NULL) { 3547039Snate@binkert.org AccessPermission perm = m_cache[i][j]->m_Permission; 3557546SBrad.Beckmann@amd.com RubyRequestType request_type = RubyRequestType_NULL; 3567546SBrad.Beckmann@amd.com if (perm == AccessPermission_Read_Only) { 3577546SBrad.Beckmann@amd.com if (m_is_instruction_only_cache) { 3587546SBrad.Beckmann@amd.com request_type = RubyRequestType_IFETCH; 3597546SBrad.Beckmann@amd.com } else { 3607546SBrad.Beckmann@amd.com request_type = RubyRequestType_LD; 3617546SBrad.Beckmann@amd.com } 3627546SBrad.Beckmann@amd.com } else if (perm == AccessPermission_Read_Write) { 3637565SBrad.Beckmann@amd.com request_type = RubyRequestType_ST; 3647565SBrad.Beckmann@amd.com } 3657565SBrad.Beckmann@amd.com 3667565SBrad.Beckmann@amd.com if (request_type != RubyRequestType_NULL) { 3677565SBrad.Beckmann@amd.com tr->addRecord(cntrl, m_cache[i][j]->m_Address.getAddress(), 3687565SBrad.Beckmann@amd.com 0, request_type, 3697565SBrad.Beckmann@amd.com m_replacementPolicy_ptr->getLastAccess(i, j), 3707565SBrad.Beckmann@amd.com m_cache[i][j]->getDataBlk()); 3717565SBrad.Beckmann@amd.com warmedUpBlocks++; 3727565SBrad.Beckmann@amd.com } 3737565SBrad.Beckmann@amd.com } 3747039Snate@binkert.org } 3757455Snate@binkert.org } 3766145Snate@binkert.org 3777455Snate@binkert.org DPRINTF(RubyCacheTrace, "%s: %lli blocks of %lli total blocks" 3787455Snate@binkert.org "recorded %.2f%% \n", name().c_str(), warmedUpBlocks, 3797455Snate@binkert.org (uint64)m_cache_num_sets * (uint64)m_cache_assoc, 3806145Snate@binkert.org (float(warmedUpBlocks)/float(totalBlocks))*100.0); 3817455Snate@binkert.org} 3827455Snate@binkert.org 3836846Spdudnik@cs.wisc.eduvoid 3848615Snilay@cs.wisc.eduCacheMemory::print(ostream& out) const 3858615Snilay@cs.wisc.edu{ 3868615Snilay@cs.wisc.edu out << "Cache dump: " << name() << endl; 3878615Snilay@cs.wisc.edu for (int i = 0; i < m_cache_num_sets; i++) { 3888615Snilay@cs.wisc.edu for (int j = 0; j < m_cache_assoc; j++) { 3898615Snilay@cs.wisc.edu if (m_cache[i][j] != NULL) { 3908615Snilay@cs.wisc.edu out << " Index: " << i 3918615Snilay@cs.wisc.edu << " way: " << j 3928615Snilay@cs.wisc.edu << " entry: " << *m_cache[i][j] << endl; 3938184Ssomayeh@cs.wisc.edu } else { 3946145Snate@binkert.org out << " Index: " << i 3957550SBrad.Beckmann@amd.com << " way: " << j 3967550SBrad.Beckmann@amd.com << " entry: NULL" << endl; 3977550SBrad.Beckmann@amd.com } 3987550SBrad.Beckmann@amd.com } 3998171Stushar@csail.mit.edu } 4008171Stushar@csail.mit.edu} 4018171Stushar@csail.mit.edu 4028171Stushar@csail.mit.eduvoid 4038171Stushar@csail.mit.eduCacheMemory::printData(ostream& out) const 4047550SBrad.Beckmann@amd.com{ 4058615Snilay@cs.wisc.edu out << "printData() not supported" << endl; 4067039Snate@binkert.org} 4078615Snilay@cs.wisc.edu 4087039Snate@binkert.orgvoid 4097039Snate@binkert.orgCacheMemory::setLocked(const Address& address, int context) 4106863Sdrh5@cs.wisc.edu{ 4117565SBrad.Beckmann@amd.com DPRINTF(RubyCache, "Setting Lock for addr: %x to %d\n", address, context); 4127565SBrad.Beckmann@amd.com assert(address == line_address(address)); 4136145Snate@binkert.org int64 cacheSet = addressToCacheSet(address); 4146145Snate@binkert.org int loc = findTagInSet(cacheSet, address); 4157039Snate@binkert.org assert(loc != -1); 4167039Snate@binkert.org m_cache[cacheSet][loc]->m_locked = context; 4177039Snate@binkert.org} 4187546SBrad.Beckmann@amd.com 4197546SBrad.Beckmann@amd.comvoid 4207546SBrad.Beckmann@amd.comCacheMemory::clearLocked(const Address& address) 4217546SBrad.Beckmann@amd.com{ 4227546SBrad.Beckmann@amd.com DPRINTF(RubyCache, "Clear Lock for addr: %x\n", address); 4237546SBrad.Beckmann@amd.com assert(address == line_address(address)); 4247546SBrad.Beckmann@amd.com int64 cacheSet = addressToCacheSet(address); 4257546SBrad.Beckmann@amd.com int loc = findTagInSet(cacheSet, address); 4267565SBrad.Beckmann@amd.com assert(loc != -1); 4277565SBrad.Beckmann@amd.com m_cache[cacheSet][loc]->m_locked = -1; 4287565SBrad.Beckmann@amd.com} 4297565SBrad.Beckmann@amd.com 4307565SBrad.Beckmann@amd.combool 4317565SBrad.Beckmann@amd.comCacheMemory::isLocked(const Address& address, int context) 4327565SBrad.Beckmann@amd.com{ 4337565SBrad.Beckmann@amd.com assert(address == line_address(address)); 4347565SBrad.Beckmann@amd.com int64 cacheSet = addressToCacheSet(address); 4357565SBrad.Beckmann@amd.com int loc = findTagInSet(cacheSet, address); 4367565SBrad.Beckmann@amd.com assert(loc != -1); 4377039Snate@binkert.org DPRINTF(RubyCache, "Testing Lock for addr: %llx cur %d con %d\n", 4387455Snate@binkert.org address, m_cache[cacheSet][loc]->m_locked, context); 4396145Snate@binkert.org return m_cache[cacheSet][loc]->m_locked == context; 4407455Snate@binkert.org} 4417455Snate@binkert.org 4427455Snate@binkert.orgvoid 4437455Snate@binkert.orgCacheMemory::regStats() 4447455Snate@binkert.org{ 4457455Snate@binkert.org m_demand_hits 4466145Snate@binkert.org .name(name() + ".demand_hits") 4478615Snilay@cs.wisc.edu .desc("Number of cache demand hits") 4488615Snilay@cs.wisc.edu ; 4496285Snate@binkert.org 4507565SBrad.Beckmann@amd.com m_demand_misses 4517565SBrad.Beckmann@amd.com .name(name() + ".demand_misses") 4526145Snate@binkert.org .desc("Number of cache demand misses") 4536145Snate@binkert.org ; 4547039Snate@binkert.org 4557546SBrad.Beckmann@amd.com m_demand_accesses 4567546SBrad.Beckmann@amd.com .name(name() + ".demand_accesses") 4577560SBrad.Beckmann@amd.com .desc("Number of cache demand accesses") 4587565SBrad.Beckmann@amd.com ; 4597565SBrad.Beckmann@amd.com 4607565SBrad.Beckmann@amd.com m_demand_accesses = m_demand_hits + m_demand_misses; 4617565SBrad.Beckmann@amd.com 4627039Snate@binkert.org m_sw_prefetches 4638615Snilay@cs.wisc.edu .name(name() + ".total_sw_prefetches") 4648615Snilay@cs.wisc.edu .desc("Number of software prefetches") 4658615Snilay@cs.wisc.edu .flags(Stats::nozero) 4667039Snate@binkert.org ; 4678615Snilay@cs.wisc.edu 4687039Snate@binkert.org m_hw_prefetches 4696145Snate@binkert.org .name(name() + ".total_hw_prefetches") 4707039Snate@binkert.org .desc("Number of hardware prefetches") 4717039Snate@binkert.org .flags(Stats::nozero) 4728828Snilay@cs.wisc.edu ; 4737039Snate@binkert.org 4748828Snilay@cs.wisc.edu m_prefetches 4757039Snate@binkert.org .name(name() + ".total_prefetches") 4766145Snate@binkert.org .desc("Number of prefetches") 4779171Snilay@cs.wisc.edu .flags(Stats::nozero) 4789171Snilay@cs.wisc.edu ; 4796145Snate@binkert.org 4807039Snate@binkert.org m_prefetches = m_sw_prefetches + m_hw_prefetches; 4817039Snate@binkert.org 4827546SBrad.Beckmann@amd.com m_accessModeType 4836285Snate@binkert.org .init(RubyRequestType_NUM) 4847565SBrad.Beckmann@amd.com .name(name() + ".access_mode") 4857565SBrad.Beckmann@amd.com .flags(Stats::pdf | Stats::total) 4867565SBrad.Beckmann@amd.com ; 4877565SBrad.Beckmann@amd.com for (int i = 0; i < RubyAccessMode_NUM; i++) { 4887565SBrad.Beckmann@amd.com m_accessModeType 4899171Snilay@cs.wisc.edu .subname(i, RubyAccessMode_to_string(RubyAccessMode(i))) 4907565SBrad.Beckmann@amd.com .flags(Stats::nozero) 4917565SBrad.Beckmann@amd.com ; 4927565SBrad.Beckmann@amd.com } 4937565SBrad.Beckmann@amd.com 4947565SBrad.Beckmann@amd.com numDataArrayReads 4957565SBrad.Beckmann@amd.com .name(name() + ".num_data_array_reads") 4967565SBrad.Beckmann@amd.com .desc("number of data array reads") 4979171Snilay@cs.wisc.edu .flags(Stats::nozero) 4987565SBrad.Beckmann@amd.com ; 4997565SBrad.Beckmann@amd.com 5008266Sksewell@umich.edu numDataArrayWrites 5018266Sksewell@umich.edu .name(name() + ".num_data_array_writes") 5028266Sksewell@umich.edu .desc("number of data array writes") 5038615Snilay@cs.wisc.edu .flags(Stats::nozero) 5046285Snate@binkert.org ; 5056285Snate@binkert.org 5067039Snate@binkert.org numTagArrayReads 5078688Snilay@cs.wisc.edu .name(name() + ".num_tag_array_reads") 5088688Snilay@cs.wisc.edu .desc("number of tag array reads") 5098688Snilay@cs.wisc.edu .flags(Stats::nozero) 5108688Snilay@cs.wisc.edu ; 5118688Snilay@cs.wisc.edu 5127039Snate@binkert.org numTagArrayWrites 5137039Snate@binkert.org .name(name() + ".num_tag_array_writes") 5147039Snate@binkert.org .desc("number of tag array writes") 5157908Shestness@cs.utexas.edu .flags(Stats::nozero) 5167907Shestness@cs.utexas.edu ; 5178615Snilay@cs.wisc.edu 5188615Snilay@cs.wisc.edu numTagArrayStalls 5198615Snilay@cs.wisc.edu .name(name() + ".num_tag_array_stalls") 5207039Snate@binkert.org .desc("number of stalls caused by tag array") 5218615Snilay@cs.wisc.edu .flags(Stats::nozero) 5228615Snilay@cs.wisc.edu ; 5237039Snate@binkert.org 5246285Snate@binkert.org numDataArrayStalls 5257039Snate@binkert.org .name(name() + ".num_data_array_stalls") 5267039Snate@binkert.org .desc("number of stalls caused by data array") 5277039Snate@binkert.org .flags(Stats::nozero) 5287039Snate@binkert.org ; 5297023SBrad.Beckmann@amd.com} 5307039Snate@binkert.org 5317039Snate@binkert.orgvoid 5327039Snate@binkert.orgCacheMemory::recordRequestType(CacheRequestType requestType) 5337039Snate@binkert.org{ 5347039Snate@binkert.org DPRINTF(RubyStats, "Recorded statistic: %s\n", 5357039Snate@binkert.org CacheRequestType_to_string(requestType)); 5367039Snate@binkert.org switch(requestType) { 5378615Snilay@cs.wisc.edu case CacheRequestType_DataArrayRead: 5387039Snate@binkert.org numDataArrayReads++; 5397039Snate@binkert.org return; 5407039Snate@binkert.org case CacheRequestType_DataArrayWrite: 5417039Snate@binkert.org numDataArrayWrites++; 5427023SBrad.Beckmann@amd.com return; 5437039Snate@binkert.org case CacheRequestType_TagArrayRead: 5448688Snilay@cs.wisc.edu numTagArrayReads++; 5458688Snilay@cs.wisc.edu return; 5468688Snilay@cs.wisc.edu case CacheRequestType_TagArrayWrite: 5478688Snilay@cs.wisc.edu numTagArrayWrites++; 5488688Snilay@cs.wisc.edu return; 5498688Snilay@cs.wisc.edu default: 5508688Snilay@cs.wisc.edu warn("CacheMemory access_type not found: %s", 5518688Snilay@cs.wisc.edu CacheRequestType_to_string(requestType)); 5528688Snilay@cs.wisc.edu } 5538688Snilay@cs.wisc.edu} 5546285Snate@binkert.org 5556285Snate@binkert.orgbool 5567039Snate@binkert.orgCacheMemory::checkResourceAvailable(CacheResourceType res, Address addr) 5577039Snate@binkert.org{ 5587039Snate@binkert.org if (!m_resource_stalls) { 5597455Snate@binkert.org return true; 5606145Snate@binkert.org } 5616145Snate@binkert.org 5627039Snate@binkert.org if (res == CacheResourceType_TagArray) { 5638615Snilay@cs.wisc.edu if (tagArray.tryAccess(addressToCacheSet(addr))) return true; 5647039Snate@binkert.org else { 5658615Snilay@cs.wisc.edu DPRINTF(RubyResourceStalls, 5668615Snilay@cs.wisc.edu "Tag array stall on addr %s in set %d\n", 5678615Snilay@cs.wisc.edu addr, addressToCacheSet(addr)); 5688615Snilay@cs.wisc.edu numTagArrayStalls++; 5698615Snilay@cs.wisc.edu return false; 5708615Snilay@cs.wisc.edu } 5718615Snilay@cs.wisc.edu } else if (res == CacheResourceType_DataArray) { 5728615Snilay@cs.wisc.edu if (dataArray.tryAccess(addressToCacheSet(addr))) return true; 5738615Snilay@cs.wisc.edu else { 5748615Snilay@cs.wisc.edu DPRINTF(RubyResourceStalls, 5758615Snilay@cs.wisc.edu "Data array stall on addr %s in set %d\n", 5768615Snilay@cs.wisc.edu addr, addressToCacheSet(addr)); 5778615Snilay@cs.wisc.edu numDataArrayStalls++; 5788615Snilay@cs.wisc.edu return false; 5798615Snilay@cs.wisc.edu } 5808615Snilay@cs.wisc.edu } else { 5818615Snilay@cs.wisc.edu assert(false); 5828615Snilay@cs.wisc.edu return true; 5838615Snilay@cs.wisc.edu } 5848615Snilay@cs.wisc.edu} 5858615Snilay@cs.wisc.edu