CacheMemory.cc revision 11049
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
10111049Snilay@cs.wisc.eduint64
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
11211049Snilay@cs.wisc.eduCacheMemory::findTagInSet(int64 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
12711049Snilay@cs.wisc.eduCacheMemory::findTagInSetIgnorePermissions(int64 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);
16711049Snilay@cs.wisc.edu    int64 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);
19411049Snilay@cs.wisc.edu    int64 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));
21611049Snilay@cs.wisc.edu    int64 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
23611049Snilay@cs.wisc.edu    int64 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*
25411049Snilay@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
26211049Snilay@cs.wisc.edu    int64 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;
2736782SN/A
27410974Sdavid.hashe@amd.com            if (touch) {
27510974Sdavid.hashe@amd.com                m_replacementPolicy_ptr->touch(cacheSet, i, curTick());
27610974Sdavid.hashe@amd.com            }
2776782SN/A
2787839SN/A            return entry;
2797039SN/A        }
2806782SN/A    }
2817805SN/A    panic("Allocate didn't find an available entry");
2826782SN/A}
2836782SN/A
2847039SN/Avoid
28511025Snilay@cs.wisc.eduCacheMemory::deallocate(Addr address)
2866782SN/A{
28711025Snilay@cs.wisc.edu    assert(address == makeLineAddress(address));
2887039SN/A    assert(isTagPresent(address));
2897780SN/A    DPRINTF(RubyCache, "address: %s\n", address);
29011049Snilay@cs.wisc.edu    int64 cacheSet = addressToCacheSet(address);
2917039SN/A    int loc = findTagInSet(cacheSet, address);
2927039SN/A    if (loc != -1) {
2937039SN/A        delete m_cache[cacheSet][loc];
2947039SN/A        m_cache[cacheSet][loc] = NULL;
2957039SN/A        m_tag_index.erase(address);
2967039SN/A    }
2976782SN/A}
2986782SN/A
2996782SN/A// Returns with the physical address of the conflicting cache line
30011025Snilay@cs.wisc.eduAddr
30111025Snilay@cs.wisc.eduCacheMemory::cacheProbe(Addr address) const
3026782SN/A{
30311025Snilay@cs.wisc.edu    assert(address == makeLineAddress(address));
3047039SN/A    assert(!cacheAvail(address));
3056782SN/A
30611049Snilay@cs.wisc.edu    int64 cacheSet = addressToCacheSet(address);
3077039SN/A    return m_cache[cacheSet][m_replacementPolicy_ptr->getVictim(cacheSet)]->
3087039SN/A        m_Address;
3096782SN/A}
3106782SN/A
3116782SN/A// looks an address up in the cache
3127839SN/AAbstractCacheEntry*
31311025Snilay@cs.wisc.eduCacheMemory::lookup(Addr address)
3146782SN/A{
31511025Snilay@cs.wisc.edu    assert(address == makeLineAddress(address));
31611049Snilay@cs.wisc.edu    int64 cacheSet = addressToCacheSet(address);
3177039SN/A    int loc = findTagInSet(cacheSet, address);
3187839SN/A    if(loc == -1) return NULL;
3197839SN/A    return m_cache[cacheSet][loc];
3206782SN/A}
3216782SN/A
3226782SN/A// looks an address up in the cache
3237839SN/Aconst AbstractCacheEntry*
32411025Snilay@cs.wisc.eduCacheMemory::lookup(Addr address) const
3256782SN/A{
32611025Snilay@cs.wisc.edu    assert(address == makeLineAddress(address));
32711049Snilay@cs.wisc.edu    int64 cacheSet = addressToCacheSet(address);
3287039SN/A    int loc = findTagInSet(cacheSet, address);
3297839SN/A    if(loc == -1) return NULL;
3307839SN/A    return m_cache[cacheSet][loc];
3316782SN/A}
3326782SN/A
3336782SN/A// Sets the most recently used bit for a cache block
3347039SN/Avoid
33511025Snilay@cs.wisc.eduCacheMemory::setMRU(Addr address)
3366782SN/A{
33711049Snilay@cs.wisc.edu    int64 cacheSet = addressToCacheSet(address);
3388828SN/A    int loc = findTagInSet(cacheSet, address);
3396782SN/A
3408828SN/A    if(loc != -1)
3419171SN/A        m_replacementPolicy_ptr->touch(cacheSet, loc, curTick());
3426782SN/A}
3436782SN/A
3447039SN/Avoid
3458683SN/ACacheMemory::recordCacheContents(int cntrl, CacheRecorder* tr) const
3466782SN/A{
34711049Snilay@cs.wisc.edu    uint64 warmedUpBlocks = 0;
34811049Snilay@cs.wisc.edu    uint64 totalBlocks M5_VAR_USED = (uint64)m_cache_num_sets
34911049Snilay@cs.wisc.edu                                                  * (uint64)m_cache_assoc;
3508683SN/A
3517039SN/A    for (int i = 0; i < m_cache_num_sets; i++) {
3527039SN/A        for (int j = 0; j < m_cache_assoc; j++) {
3538683SN/A            if (m_cache[i][j] != NULL) {
3548683SN/A                AccessPermission perm = m_cache[i][j]->m_Permission;
3558683SN/A                RubyRequestType request_type = RubyRequestType_NULL;
3568683SN/A                if (perm == AccessPermission_Read_Only) {
3578683SN/A                    if (m_is_instruction_only_cache) {
3588683SN/A                        request_type = RubyRequestType_IFETCH;
3598683SN/A                    } else {
3608683SN/A                        request_type = RubyRequestType_LD;
3618683SN/A                    }
3628683SN/A                } else if (perm == AccessPermission_Read_Write) {
3638683SN/A                    request_type = RubyRequestType_ST;
3647039SN/A                }
3657039SN/A
3668683SN/A                if (request_type != RubyRequestType_NULL) {
36711025Snilay@cs.wisc.edu                    tr->addRecord(cntrl, m_cache[i][j]->m_Address,
3688683SN/A                                  0, request_type,
3698683SN/A                                  m_replacementPolicy_ptr->getLastAccess(i, j),
3708683SN/A                                  m_cache[i][j]->getDataBlk());
3718683SN/A                    warmedUpBlocks++;
3728683SN/A                }
3737039SN/A            }
3746782SN/A        }
3756782SN/A    }
3768683SN/A
3778937SN/A    DPRINTF(RubyCacheTrace, "%s: %lli blocks of %lli total blocks"
3788683SN/A            "recorded %.2f%% \n", name().c_str(), warmedUpBlocks,
37911049Snilay@cs.wisc.edu            (uint64)m_cache_num_sets * (uint64)m_cache_assoc,
38011049Snilay@cs.wisc.edu            (float(warmedUpBlocks)/float(totalBlocks))*100.0);
3816782SN/A}
3826782SN/A
3837039SN/Avoid
3847039SN/ACacheMemory::print(ostream& out) const
3856782SN/A{
38610080SN/A    out << "Cache dump: " << name() << endl;
3877039SN/A    for (int i = 0; i < m_cache_num_sets; i++) {
3887039SN/A        for (int j = 0; j < m_cache_assoc; j++) {
3897039SN/A            if (m_cache[i][j] != NULL) {
3907039SN/A                out << "  Index: " << i
3917039SN/A                    << " way: " << j
3927039SN/A                    << " entry: " << *m_cache[i][j] << endl;
3937039SN/A            } else {
3947039SN/A                out << "  Index: " << i
3957039SN/A                    << " way: " << j
3967039SN/A                    << " entry: NULL" << endl;
3977039SN/A            }
3987039SN/A        }
3996782SN/A    }
4006782SN/A}
4016782SN/A
4027039SN/Avoid
4037039SN/ACacheMemory::printData(ostream& out) const
4046782SN/A{
4057039SN/A    out << "printData() not supported" << endl;
4066782SN/A}
4076782SN/A
4087039SN/Avoid
40911025Snilay@cs.wisc.eduCacheMemory::setLocked(Addr address, int context)
4107039SN/A{
4117039SN/A    DPRINTF(RubyCache, "Setting Lock for addr: %x to %d\n", address, context);
41211025Snilay@cs.wisc.edu    assert(address == makeLineAddress(address));
41311049Snilay@cs.wisc.edu    int64 cacheSet = addressToCacheSet(address);
4147039SN/A    int loc = findTagInSet(cacheSet, address);
4157039SN/A    assert(loc != -1);
41611049Snilay@cs.wisc.edu    m_cache[cacheSet][loc]->m_locked = context;
4176782SN/A}
4186782SN/A
4197039SN/Avoid
42011025Snilay@cs.wisc.eduCacheMemory::clearLocked(Addr address)
4216782SN/A{
4227039SN/A    DPRINTF(RubyCache, "Clear Lock for addr: %x\n", address);
42311025Snilay@cs.wisc.edu    assert(address == makeLineAddress(address));
42411049Snilay@cs.wisc.edu    int64 cacheSet = addressToCacheSet(address);
4257039SN/A    int loc = findTagInSet(cacheSet, address);
4267039SN/A    assert(loc != -1);
42711049Snilay@cs.wisc.edu    m_cache[cacheSet][loc]->m_locked = -1;
4286782SN/A}
4296782SN/A
4306782SN/Abool
43111025Snilay@cs.wisc.eduCacheMemory::isLocked(Addr address, int context)
4326782SN/A{
43311025Snilay@cs.wisc.edu    assert(address == makeLineAddress(address));
43411049Snilay@cs.wisc.edu    int64 cacheSet = addressToCacheSet(address);
4357039SN/A    int loc = findTagInSet(cacheSet, address);
4367039SN/A    assert(loc != -1);
4377039SN/A    DPRINTF(RubyCache, "Testing Lock for addr: %llx cur %d con %d\n",
4387839SN/A            address, m_cache[cacheSet][loc]->m_locked, context);
43911049Snilay@cs.wisc.edu    return m_cache[cacheSet][loc]->m_locked == context;
4406782SN/A}
4416782SN/A
4429104SN/Avoid
4439692SN/ACacheMemory::regStats()
4449692SN/A{
4459692SN/A    m_demand_hits
4469692SN/A        .name(name() + ".demand_hits")
4479692SN/A        .desc("Number of cache demand hits")
4489692SN/A        ;
4499692SN/A
4509692SN/A    m_demand_misses
4519692SN/A        .name(name() + ".demand_misses")
4529692SN/A        .desc("Number of cache demand misses")
4539692SN/A        ;
4549692SN/A
4559692SN/A    m_demand_accesses
4569692SN/A        .name(name() + ".demand_accesses")
4579692SN/A        .desc("Number of cache demand accesses")
4589692SN/A        ;
4599692SN/A
4609692SN/A    m_demand_accesses = m_demand_hits + m_demand_misses;
4619692SN/A
4629692SN/A    m_sw_prefetches
4639692SN/A        .name(name() + ".total_sw_prefetches")
4649692SN/A        .desc("Number of software prefetches")
4659692SN/A        .flags(Stats::nozero)
4669692SN/A        ;
4679692SN/A
4689692SN/A    m_hw_prefetches
4699692SN/A        .name(name() + ".total_hw_prefetches")
4709692SN/A        .desc("Number of hardware prefetches")
4719692SN/A        .flags(Stats::nozero)
4729692SN/A        ;
4739692SN/A
4749692SN/A    m_prefetches
4759692SN/A        .name(name() + ".total_prefetches")
4769692SN/A        .desc("Number of prefetches")
4779692SN/A        .flags(Stats::nozero)
4789692SN/A        ;
4799692SN/A
4809692SN/A    m_prefetches = m_sw_prefetches + m_hw_prefetches;
4819692SN/A
4829692SN/A    m_accessModeType
4839692SN/A        .init(RubyRequestType_NUM)
4849692SN/A        .name(name() + ".access_mode")
4859692SN/A        .flags(Stats::pdf | Stats::total)
4869692SN/A        ;
4879692SN/A    for (int i = 0; i < RubyAccessMode_NUM; i++) {
4889692SN/A        m_accessModeType
4899692SN/A            .subname(i, RubyAccessMode_to_string(RubyAccessMode(i)))
4909692SN/A            .flags(Stats::nozero)
4919692SN/A            ;
4929692SN/A    }
4939692SN/A
4949692SN/A    numDataArrayReads
4959692SN/A        .name(name() + ".num_data_array_reads")
4969692SN/A        .desc("number of data array reads")
4979692SN/A        .flags(Stats::nozero)
4989692SN/A        ;
4999692SN/A
5009692SN/A    numDataArrayWrites
5019692SN/A        .name(name() + ".num_data_array_writes")
5029692SN/A        .desc("number of data array writes")
5039692SN/A        .flags(Stats::nozero)
5049692SN/A        ;
5059692SN/A
5069692SN/A    numTagArrayReads
5079692SN/A        .name(name() + ".num_tag_array_reads")
5089692SN/A        .desc("number of tag array reads")
5099692SN/A        .flags(Stats::nozero)
5109692SN/A        ;
5119692SN/A
5129692SN/A    numTagArrayWrites
5139692SN/A        .name(name() + ".num_tag_array_writes")
5149692SN/A        .desc("number of tag array writes")
5159692SN/A        .flags(Stats::nozero)
5169692SN/A        ;
5179692SN/A
5189692SN/A    numTagArrayStalls
5199692SN/A        .name(name() + ".num_tag_array_stalls")
5209692SN/A        .desc("number of stalls caused by tag array")
5219692SN/A        .flags(Stats::nozero)
5229692SN/A        ;
5239692SN/A
5249692SN/A    numDataArrayStalls
5259692SN/A        .name(name() + ".num_data_array_stalls")
5269692SN/A        .desc("number of stalls caused by data array")
5279692SN/A        .flags(Stats::nozero)
5289692SN/A        ;
5299692SN/A}
5309692SN/A
53110978Sdavid.hashe@amd.com// assumption: SLICC generated files will only call this function
53210978Sdavid.hashe@amd.com// once **all** resources are granted
5339692SN/Avoid
53411025Snilay@cs.wisc.eduCacheMemory::recordRequestType(CacheRequestType requestType, Addr addr)
5359692SN/A{
5369104SN/A    DPRINTF(RubyStats, "Recorded statistic: %s\n",
5379104SN/A            CacheRequestType_to_string(requestType));
5389104SN/A    switch(requestType) {
5399104SN/A    case CacheRequestType_DataArrayRead:
54010978Sdavid.hashe@amd.com        if (m_resource_stalls)
54110978Sdavid.hashe@amd.com            dataArray.reserve(addressToCacheSet(addr));
5429104SN/A        numDataArrayReads++;
5439104SN/A        return;
5449104SN/A    case CacheRequestType_DataArrayWrite:
54510978Sdavid.hashe@amd.com        if (m_resource_stalls)
54610978Sdavid.hashe@amd.com            dataArray.reserve(addressToCacheSet(addr));
5479104SN/A        numDataArrayWrites++;
5489104SN/A        return;
5499104SN/A    case CacheRequestType_TagArrayRead:
55010978Sdavid.hashe@amd.com        if (m_resource_stalls)
55110978Sdavid.hashe@amd.com            tagArray.reserve(addressToCacheSet(addr));
5529104SN/A        numTagArrayReads++;
5539104SN/A        return;
5549104SN/A    case CacheRequestType_TagArrayWrite:
55510978Sdavid.hashe@amd.com        if (m_resource_stalls)
55610978Sdavid.hashe@amd.com            tagArray.reserve(addressToCacheSet(addr));
5579104SN/A        numTagArrayWrites++;
5589104SN/A        return;
5599104SN/A    default:
5609104SN/A        warn("CacheMemory access_type not found: %s",
5619104SN/A             CacheRequestType_to_string(requestType));
5629104SN/A    }
5639104SN/A}
5649104SN/A
5659105SN/Abool
56611025Snilay@cs.wisc.eduCacheMemory::checkResourceAvailable(CacheResourceType res, Addr addr)
5679105SN/A{
5689105SN/A    if (!m_resource_stalls) {
5699105SN/A        return true;
5709105SN/A    }
5719105SN/A
5729105SN/A    if (res == CacheResourceType_TagArray) {
5739105SN/A        if (tagArray.tryAccess(addressToCacheSet(addr))) return true;
5749105SN/A        else {
5759692SN/A            DPRINTF(RubyResourceStalls,
5769692SN/A                    "Tag array stall on addr %s in set %d\n",
5779692SN/A                    addr, addressToCacheSet(addr));
5789105SN/A            numTagArrayStalls++;
5799105SN/A            return false;
5809105SN/A        }
5819105SN/A    } else if (res == CacheResourceType_DataArray) {
5829105SN/A        if (dataArray.tryAccess(addressToCacheSet(addr))) return true;
5839105SN/A        else {
5849692SN/A            DPRINTF(RubyResourceStalls,
5859692SN/A                    "Data array stall on addr %s in set %d\n",
5869692SN/A                    addr, addressToCacheSet(addr));
5879105SN/A            numDataArrayStalls++;
5889105SN/A            return false;
5899105SN/A        }
5909105SN/A    } else {
5919105SN/A        assert(false);
5929105SN/A        return true;
5939105SN/A    }
5949105SN/A}
59510980Sdavid.hashe@amd.com
59610980Sdavid.hashe@amd.combool
59711049Snilay@cs.wisc.eduCacheMemory::isBlockInvalid(int64 cache_set, int64 loc)
59810980Sdavid.hashe@amd.com{
59910980Sdavid.hashe@amd.com  return (m_cache[cache_set][loc]->m_Permission == AccessPermission_Invalid);
60010980Sdavid.hashe@amd.com}
60110980Sdavid.hashe@amd.com
60210980Sdavid.hashe@amd.combool
60311049Snilay@cs.wisc.eduCacheMemory::isBlockNotBusy(int64 cache_set, int64 loc)
60410980Sdavid.hashe@amd.com{
60510980Sdavid.hashe@amd.com  return (m_cache[cache_set][loc]->m_Permission != AccessPermission_Busy);
60610980Sdavid.hashe@amd.com}
607