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