CacheMemory.cc revision 11308:7d8836fd043d
112531Sandreas.sandberg@arm.com/*
212531Sandreas.sandberg@arm.com * Copyright (c) 1999-2012 Mark D. Hill and David A. Wood
312531Sandreas.sandberg@arm.com * Copyright (c) 2013 Advanced Micro Devices, Inc.
412531Sandreas.sandberg@arm.com * All rights reserved.
512531Sandreas.sandberg@arm.com *
612531Sandreas.sandberg@arm.com * Redistribution and use in source and binary forms, with or without
712531Sandreas.sandberg@arm.com * modification, are permitted provided that the following conditions are
812531Sandreas.sandberg@arm.com * met: redistributions of source code must retain the above copyright
912531Sandreas.sandberg@arm.com * notice, this list of conditions and the following disclaimer;
1012531Sandreas.sandberg@arm.com * redistributions in binary form must reproduce the above copyright
1112531Sandreas.sandberg@arm.com * notice, this list of conditions and the following disclaimer in the
1212531Sandreas.sandberg@arm.com * documentation and/or other materials provided with the distribution;
1312531Sandreas.sandberg@arm.com * neither the name of the copyright holders nor the names of its
1412531Sandreas.sandberg@arm.com * contributors may be used to endorse or promote products derived from
1512531Sandreas.sandberg@arm.com * this software without specific prior written permission.
1612531Sandreas.sandberg@arm.com *
1712531Sandreas.sandberg@arm.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
1812531Sandreas.sandberg@arm.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
1912531Sandreas.sandberg@arm.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
2012531Sandreas.sandberg@arm.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
2112531Sandreas.sandberg@arm.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
2212531Sandreas.sandberg@arm.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
2312531Sandreas.sandberg@arm.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2412531Sandreas.sandberg@arm.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2512531Sandreas.sandberg@arm.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2612531Sandreas.sandberg@arm.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2712531Sandreas.sandberg@arm.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2812531Sandreas.sandberg@arm.com */
2912531Sandreas.sandberg@arm.com
3012531Sandreas.sandberg@arm.com#include "base/intmath.hh"
3112531Sandreas.sandberg@arm.com#include "debug/RubyCache.hh"
3212531Sandreas.sandberg@arm.com#include "debug/RubyCacheTrace.hh"
3312531Sandreas.sandberg@arm.com#include "debug/RubyResourceStalls.hh"
3412531Sandreas.sandberg@arm.com#include "debug/RubyStats.hh"
3512531Sandreas.sandberg@arm.com#include "mem/protocol/AccessPermission.hh"
3612531Sandreas.sandberg@arm.com#include "mem/ruby/structures/CacheMemory.hh"
3712531Sandreas.sandberg@arm.com#include "mem/ruby/system/RubySystem.hh"
3812531Sandreas.sandberg@arm.com#include "mem/ruby/system/WeightedLRUPolicy.hh"
3912531Sandreas.sandberg@arm.com
4012531Sandreas.sandberg@arm.comusing namespace std;
4112531Sandreas.sandberg@arm.com
4212531Sandreas.sandberg@arm.comostream&
4312531Sandreas.sandberg@arm.comoperator<<(ostream& out, const CacheMemory& obj)
4412531Sandreas.sandberg@arm.com{
4512531Sandreas.sandberg@arm.com    obj.print(out);
4612531Sandreas.sandberg@arm.com    out << flush;
4712531Sandreas.sandberg@arm.com    return out;
4812531Sandreas.sandberg@arm.com}
4912531Sandreas.sandberg@arm.com
5012531Sandreas.sandberg@arm.comCacheMemory *
5112531Sandreas.sandberg@arm.comRubyCacheParams::create()
5212531Sandreas.sandberg@arm.com{
5312531Sandreas.sandberg@arm.com    return new CacheMemory(this);
5412531Sandreas.sandberg@arm.com}
5512531Sandreas.sandberg@arm.com
5612531Sandreas.sandberg@arm.comCacheMemory::CacheMemory(const Params *p)
5712531Sandreas.sandberg@arm.com    : SimObject(p),
5812531Sandreas.sandberg@arm.com    dataArray(p->dataArrayBanks, p->dataAccessLatency,
5912531Sandreas.sandberg@arm.com              p->start_index_bit, p->ruby_system),
6012531Sandreas.sandberg@arm.com    tagArray(p->tagArrayBanks, p->tagAccessLatency,
6112531Sandreas.sandberg@arm.com             p->start_index_bit, p->ruby_system)
6212531Sandreas.sandberg@arm.com{
6312531Sandreas.sandberg@arm.com    m_cache_size = p->size;
6412531Sandreas.sandberg@arm.com    m_cache_assoc = p->assoc;
6512531Sandreas.sandberg@arm.com    m_replacementPolicy_ptr = p->replacement_policy;
6612531Sandreas.sandberg@arm.com    m_replacementPolicy_ptr->setCache(this);
6712531Sandreas.sandberg@arm.com    m_start_index_bit = p->start_index_bit;
6812531Sandreas.sandberg@arm.com    m_is_instruction_only_cache = p->is_icache;
6912531Sandreas.sandberg@arm.com    m_resource_stalls = p->resourceStalls;
7012531Sandreas.sandberg@arm.com    m_block_size = p->block_size;  // may be 0 at this point. Updated in init()
7112531Sandreas.sandberg@arm.com}
7212531Sandreas.sandberg@arm.com
7312531Sandreas.sandberg@arm.comvoid
7412531Sandreas.sandberg@arm.comCacheMemory::init()
7512531Sandreas.sandberg@arm.com{
7612531Sandreas.sandberg@arm.com    if (m_block_size == 0) {
7712531Sandreas.sandberg@arm.com        m_block_size = RubySystem::getBlockSizeBytes();
7812531Sandreas.sandberg@arm.com    }
7912699Sandreas.sandberg@arm.com    m_cache_num_sets = (m_cache_size / m_cache_assoc) / m_block_size;
8012531Sandreas.sandberg@arm.com    assert(m_cache_num_sets > 1);
8112531Sandreas.sandberg@arm.com    m_cache_num_set_bits = floorLog2(m_cache_num_sets);
8212531Sandreas.sandberg@arm.com    assert(m_cache_num_set_bits > 0);
8312531Sandreas.sandberg@arm.com
8412531Sandreas.sandberg@arm.com    m_cache.resize(m_cache_num_sets,
8512531Sandreas.sandberg@arm.com                    std::vector<AbstractCacheEntry*>(m_cache_assoc, nullptr));
8612531Sandreas.sandberg@arm.com}
8712531Sandreas.sandberg@arm.com
8812531Sandreas.sandberg@arm.comCacheMemory::~CacheMemory()
8912531Sandreas.sandberg@arm.com{
9012531Sandreas.sandberg@arm.com    if (m_replacementPolicy_ptr)
9112531Sandreas.sandberg@arm.com        delete m_replacementPolicy_ptr;
9212531Sandreas.sandberg@arm.com    for (int i = 0; i < m_cache_num_sets; i++) {
9312531Sandreas.sandberg@arm.com        for (int j = 0; j < m_cache_assoc; j++) {
9412531Sandreas.sandberg@arm.com            delete m_cache[i][j];
9512531Sandreas.sandberg@arm.com        }
9612531Sandreas.sandberg@arm.com    }
9712531Sandreas.sandberg@arm.com}
9812531Sandreas.sandberg@arm.com
9912531Sandreas.sandberg@arm.com// convert a Address to its location in the cache
10012531Sandreas.sandberg@arm.comint64_t
10112531Sandreas.sandberg@arm.comCacheMemory::addressToCacheSet(Addr address) const
10212531Sandreas.sandberg@arm.com{
10312531Sandreas.sandberg@arm.com    assert(address == makeLineAddress(address));
10412531Sandreas.sandberg@arm.com    return bitSelect(address, m_start_index_bit,
10512531Sandreas.sandberg@arm.com                     m_start_index_bit + m_cache_num_set_bits - 1);
10612531Sandreas.sandberg@arm.com}
10712531Sandreas.sandberg@arm.com
10812531Sandreas.sandberg@arm.com// Given a cache index: returns the index of the tag in a set.
10912531Sandreas.sandberg@arm.com// returns -1 if the tag is not found.
11012531Sandreas.sandberg@arm.comint
11112531Sandreas.sandberg@arm.comCacheMemory::findTagInSet(int64_t cacheSet, Addr tag) const
11212531Sandreas.sandberg@arm.com{
11312531Sandreas.sandberg@arm.com    assert(tag == makeLineAddress(tag));
11412531Sandreas.sandberg@arm.com    // search the set for the tags
11512531Sandreas.sandberg@arm.com    auto it = m_tag_index.find(tag);
11612531Sandreas.sandberg@arm.com    if (it != m_tag_index.end())
11712531Sandreas.sandberg@arm.com        if (m_cache[cacheSet][it->second]->m_Permission !=
11812531Sandreas.sandberg@arm.com            AccessPermission_NotPresent)
11912531Sandreas.sandberg@arm.com            return it->second;
12012531Sandreas.sandberg@arm.com    return -1; // Not found
12112531Sandreas.sandberg@arm.com}
12212531Sandreas.sandberg@arm.com
12312531Sandreas.sandberg@arm.com// Given a cache index: returns the index of the tag in a set.
12412698Sandreas.sandberg@arm.com// returns -1 if the tag is not found.
12512698Sandreas.sandberg@arm.comint
12612698Sandreas.sandberg@arm.comCacheMemory::findTagInSetIgnorePermissions(int64_t cacheSet,
12712698Sandreas.sandberg@arm.com                                           Addr tag) const
12812698Sandreas.sandberg@arm.com{
12912698Sandreas.sandberg@arm.com    assert(tag == makeLineAddress(tag));
13012698Sandreas.sandberg@arm.com    // search the set for the tags
13112698Sandreas.sandberg@arm.com    auto it = m_tag_index.find(tag);
13212698Sandreas.sandberg@arm.com    if (it != m_tag_index.end())
13312531Sandreas.sandberg@arm.com        return it->second;
13412531Sandreas.sandberg@arm.com    return -1; // Not found
13512531Sandreas.sandberg@arm.com}
13612531Sandreas.sandberg@arm.com
13712531Sandreas.sandberg@arm.com// Given an unique cache block identifier (idx): return the valid address
13812531Sandreas.sandberg@arm.com// stored by the cache block.  If the block is invalid/notpresent, the
13912531Sandreas.sandberg@arm.com// function returns the 0 address
14012698Sandreas.sandberg@arm.comAddr
14112698Sandreas.sandberg@arm.comCacheMemory::getAddressAtIdx(int idx) const
14212698Sandreas.sandberg@arm.com{
14312698Sandreas.sandberg@arm.com    Addr tmp(0);
14412698Sandreas.sandberg@arm.com
14512531Sandreas.sandberg@arm.com    int set = idx / m_cache_assoc;
14612531Sandreas.sandberg@arm.com    assert(set < m_cache_num_sets);
14712531Sandreas.sandberg@arm.com
14812531Sandreas.sandberg@arm.com    int way = idx - set * m_cache_assoc;
14912531Sandreas.sandberg@arm.com    assert (way < m_cache_assoc);
15012531Sandreas.sandberg@arm.com
15112531Sandreas.sandberg@arm.com    AbstractCacheEntry* entry = m_cache[set][way];
15212531Sandreas.sandberg@arm.com    if (entry == NULL ||
15312531Sandreas.sandberg@arm.com        entry->m_Permission == AccessPermission_Invalid ||
15412531Sandreas.sandberg@arm.com        entry->m_Permission == AccessPermission_NotPresent) {
15512531Sandreas.sandberg@arm.com        return tmp;
15612531Sandreas.sandberg@arm.com    }
15712531Sandreas.sandberg@arm.com    return entry->m_Address;
15812531Sandreas.sandberg@arm.com}
15912531Sandreas.sandberg@arm.com
16012531Sandreas.sandberg@arm.combool
16112531Sandreas.sandberg@arm.comCacheMemory::tryCacheAccess(Addr address, RubyRequestType type,
16212531Sandreas.sandberg@arm.com                            DataBlock*& data_ptr)
16312531Sandreas.sandberg@arm.com{
16412531Sandreas.sandberg@arm.com    assert(address == makeLineAddress(address));
16512531Sandreas.sandberg@arm.com    DPRINTF(RubyCache, "address: %#x\n", address);
16612531Sandreas.sandberg@arm.com    int64_t cacheSet = addressToCacheSet(address);
16712531Sandreas.sandberg@arm.com    int loc = findTagInSet(cacheSet, address);
16812531Sandreas.sandberg@arm.com    if (loc != -1) {
16912531Sandreas.sandberg@arm.com        // Do we even have a tag match?
17012531Sandreas.sandberg@arm.com        AbstractCacheEntry* entry = m_cache[cacheSet][loc];
17112531Sandreas.sandberg@arm.com        m_replacementPolicy_ptr->touch(cacheSet, loc, curTick());
17212531Sandreas.sandberg@arm.com        data_ptr = &(entry->getDataBlk());
17312533Sandreas.sandberg@arm.com
17412531Sandreas.sandberg@arm.com        if (entry->m_Permission == AccessPermission_Read_Write) {
17512531Sandreas.sandberg@arm.com            return true;
17612531Sandreas.sandberg@arm.com        }
17712531Sandreas.sandberg@arm.com        if ((entry->m_Permission == AccessPermission_Read_Only) &&
17812531Sandreas.sandberg@arm.com            (type == RubyRequestType_LD || type == RubyRequestType_IFETCH)) {
17912531Sandreas.sandberg@arm.com            return true;
18012531Sandreas.sandberg@arm.com        }
18112531Sandreas.sandberg@arm.com        // The line must not be accessible
18212531Sandreas.sandberg@arm.com    }
18312531Sandreas.sandberg@arm.com    data_ptr = NULL;
18412531Sandreas.sandberg@arm.com    return false;
18512531Sandreas.sandberg@arm.com}
18612531Sandreas.sandberg@arm.com
18712531Sandreas.sandberg@arm.combool
18812531Sandreas.sandberg@arm.comCacheMemory::testCacheAccess(Addr address, RubyRequestType type,
18912531Sandreas.sandberg@arm.com                             DataBlock*& data_ptr)
19012531Sandreas.sandberg@arm.com{
19112531Sandreas.sandberg@arm.com    assert(address == makeLineAddress(address));
19212531Sandreas.sandberg@arm.com    DPRINTF(RubyCache, "address: %#x\n", address);
19312531Sandreas.sandberg@arm.com    int64_t cacheSet = addressToCacheSet(address);
19412531Sandreas.sandberg@arm.com    int loc = findTagInSet(cacheSet, address);
19512531Sandreas.sandberg@arm.com
19612531Sandreas.sandberg@arm.com    if (loc != -1) {
19712531Sandreas.sandberg@arm.com        // Do we even have a tag match?
19812531Sandreas.sandberg@arm.com        AbstractCacheEntry* entry = m_cache[cacheSet][loc];
19912531Sandreas.sandberg@arm.com        m_replacementPolicy_ptr->touch(cacheSet, loc, curTick());
20012531Sandreas.sandberg@arm.com        data_ptr = &(entry->getDataBlk());
20112531Sandreas.sandberg@arm.com
20212531Sandreas.sandberg@arm.com        return m_cache[cacheSet][loc]->m_Permission !=
20312531Sandreas.sandberg@arm.com            AccessPermission_NotPresent;
20412531Sandreas.sandberg@arm.com    }
20512531Sandreas.sandberg@arm.com
20612531Sandreas.sandberg@arm.com    data_ptr = NULL;
20712531Sandreas.sandberg@arm.com    return false;
20812533Sandreas.sandberg@arm.com}
20912531Sandreas.sandberg@arm.com
21012531Sandreas.sandberg@arm.com// tests to see if an address is present in the cache
21112531Sandreas.sandberg@arm.combool
21212531Sandreas.sandberg@arm.comCacheMemory::isTagPresent(Addr address) const
21312531Sandreas.sandberg@arm.com{
21412531Sandreas.sandberg@arm.com    assert(address == makeLineAddress(address));
21512531Sandreas.sandberg@arm.com    int64_t cacheSet = addressToCacheSet(address);
21612531Sandreas.sandberg@arm.com    int loc = findTagInSet(cacheSet, address);
21712531Sandreas.sandberg@arm.com
21812531Sandreas.sandberg@arm.com    if (loc == -1) {
21912531Sandreas.sandberg@arm.com        // We didn't find the tag
22012531Sandreas.sandberg@arm.com        DPRINTF(RubyCache, "No tag match for address: %#x\n", address);
22112531Sandreas.sandberg@arm.com        return false;
22212531Sandreas.sandberg@arm.com    }
22312531Sandreas.sandberg@arm.com    DPRINTF(RubyCache, "address: %#x found\n", address);
22412531Sandreas.sandberg@arm.com    return true;
22512531Sandreas.sandberg@arm.com}
22612531Sandreas.sandberg@arm.com
22712531Sandreas.sandberg@arm.com// Returns true if there is:
22812531Sandreas.sandberg@arm.com//   a) a tag match on this address or there is
22912531Sandreas.sandberg@arm.com//   b) an unused line in the same cache "way"
23012531Sandreas.sandberg@arm.combool
23112531Sandreas.sandberg@arm.comCacheMemory::cacheAvail(Addr address) const
23212531Sandreas.sandberg@arm.com{
23312531Sandreas.sandberg@arm.com    assert(address == makeLineAddress(address));
23412531Sandreas.sandberg@arm.com
23512531Sandreas.sandberg@arm.com    int64_t cacheSet = addressToCacheSet(address);
23612531Sandreas.sandberg@arm.com
23712531Sandreas.sandberg@arm.com    for (int i = 0; i < m_cache_assoc; i++) {
23812531Sandreas.sandberg@arm.com        AbstractCacheEntry* entry = m_cache[cacheSet][i];
23912531Sandreas.sandberg@arm.com        if (entry != NULL) {
24012531Sandreas.sandberg@arm.com            if (entry->m_Address == address ||
24112531Sandreas.sandberg@arm.com                entry->m_Permission == AccessPermission_NotPresent) {
24212531Sandreas.sandberg@arm.com                // Already in the cache or we found an empty entry
24312531Sandreas.sandberg@arm.com                return true;
24412531Sandreas.sandberg@arm.com            }
24512531Sandreas.sandberg@arm.com        } else {
24612531Sandreas.sandberg@arm.com            return true;
24712531Sandreas.sandberg@arm.com        }
24812531Sandreas.sandberg@arm.com    }
24912531Sandreas.sandberg@arm.com    return false;
25012531Sandreas.sandberg@arm.com}
25112531Sandreas.sandberg@arm.com
25212533Sandreas.sandberg@arm.comAbstractCacheEntry*
25312533Sandreas.sandberg@arm.comCacheMemory::allocate(Addr address, AbstractCacheEntry *entry, bool touch)
25412533Sandreas.sandberg@arm.com{
25512533Sandreas.sandberg@arm.com    assert(address == makeLineAddress(address));
25612533Sandreas.sandberg@arm.com    assert(!isTagPresent(address));
25712533Sandreas.sandberg@arm.com    assert(cacheAvail(address));
25812533Sandreas.sandberg@arm.com    DPRINTF(RubyCache, "address: %#x\n", address);
25912533Sandreas.sandberg@arm.com
26012533Sandreas.sandberg@arm.com    // Find the first open slot
26112533Sandreas.sandberg@arm.com    int64_t cacheSet = addressToCacheSet(address);
26212533Sandreas.sandberg@arm.com    std::vector<AbstractCacheEntry*> &set = m_cache[cacheSet];
26312533Sandreas.sandberg@arm.com    for (int i = 0; i < m_cache_assoc; i++) {
26412533Sandreas.sandberg@arm.com        if (!set[i] || set[i]->m_Permission == AccessPermission_NotPresent) {
26512533Sandreas.sandberg@arm.com            if (set[i] && (set[i] != entry)) {
26612533Sandreas.sandberg@arm.com                warn_once("This protocol contains a cache entry handling bug: "
26712533Sandreas.sandberg@arm.com                    "Entries in the cache should never be NotPresent! If\n"
26812533Sandreas.sandberg@arm.com                    "this entry (%#x) is not tracked elsewhere, it will memory "
26912531Sandreas.sandberg@arm.com                    "leak here. Fix your protocol to eliminate these!",
27012531Sandreas.sandberg@arm.com                    address);
27112531Sandreas.sandberg@arm.com            }
27212531Sandreas.sandberg@arm.com            set[i] = entry;  // Init entry
27312531Sandreas.sandberg@arm.com            set[i]->m_Address = address;
27412531Sandreas.sandberg@arm.com            set[i]->m_Permission = AccessPermission_Invalid;
27512533Sandreas.sandberg@arm.com            DPRINTF(RubyCache, "Allocate clearing lock for addr: %x\n",
27612531Sandreas.sandberg@arm.com                    address);
27712531Sandreas.sandberg@arm.com            set[i]->m_locked = -1;
27812531Sandreas.sandberg@arm.com            m_tag_index[address] = i;
27912531Sandreas.sandberg@arm.com            entry->setSetIndex(cacheSet);
28012531Sandreas.sandberg@arm.com            entry->setWayIndex(i);
28112531Sandreas.sandberg@arm.com
28212531Sandreas.sandberg@arm.com            if (touch) {
28312531Sandreas.sandberg@arm.com                m_replacementPolicy_ptr->touch(cacheSet, i, curTick());
28412531Sandreas.sandberg@arm.com            }
28512531Sandreas.sandberg@arm.com
28612531Sandreas.sandberg@arm.com            return entry;
28712531Sandreas.sandberg@arm.com        }
28812531Sandreas.sandberg@arm.com    }
28912531Sandreas.sandberg@arm.com    panic("Allocate didn't find an available entry");
29012531Sandreas.sandberg@arm.com}
29112531Sandreas.sandberg@arm.com
29212531Sandreas.sandberg@arm.comvoid
29312531Sandreas.sandberg@arm.comCacheMemory::deallocate(Addr address)
29412531Sandreas.sandberg@arm.com{
29512531Sandreas.sandberg@arm.com    assert(address == makeLineAddress(address));
29612531Sandreas.sandberg@arm.com    assert(isTagPresent(address));
29712531Sandreas.sandberg@arm.com    DPRINTF(RubyCache, "address: %#x\n", address);
29812531Sandreas.sandberg@arm.com    int64_t cacheSet = addressToCacheSet(address);
29912531Sandreas.sandberg@arm.com    int loc = findTagInSet(cacheSet, address);
30012531Sandreas.sandberg@arm.com    if (loc != -1) {
30112531Sandreas.sandberg@arm.com        delete m_cache[cacheSet][loc];
30212531Sandreas.sandberg@arm.com        m_cache[cacheSet][loc] = NULL;
30312531Sandreas.sandberg@arm.com        m_tag_index.erase(address);
30412531Sandreas.sandberg@arm.com    }
30512531Sandreas.sandberg@arm.com}
30612531Sandreas.sandberg@arm.com
30712531Sandreas.sandberg@arm.com// Returns with the physical address of the conflicting cache line
30812531Sandreas.sandberg@arm.comAddr
30912531Sandreas.sandberg@arm.comCacheMemory::cacheProbe(Addr address) const
31012531Sandreas.sandberg@arm.com{
31112531Sandreas.sandberg@arm.com    assert(address == makeLineAddress(address));
31212531Sandreas.sandberg@arm.com    assert(!cacheAvail(address));
31312531Sandreas.sandberg@arm.com
31412531Sandreas.sandberg@arm.com    int64_t cacheSet = addressToCacheSet(address);
31512531Sandreas.sandberg@arm.com    return m_cache[cacheSet][m_replacementPolicy_ptr->getVictim(cacheSet)]->
31612531Sandreas.sandberg@arm.com        m_Address;
31712531Sandreas.sandberg@arm.com}
31812531Sandreas.sandberg@arm.com
31912531Sandreas.sandberg@arm.com// looks an address up in the cache
32012531Sandreas.sandberg@arm.comAbstractCacheEntry*
32112531Sandreas.sandberg@arm.comCacheMemory::lookup(Addr address)
32212531Sandreas.sandberg@arm.com{
32312531Sandreas.sandberg@arm.com    assert(address == makeLineAddress(address));
32412531Sandreas.sandberg@arm.com    int64_t cacheSet = addressToCacheSet(address);
32512531Sandreas.sandberg@arm.com    int loc = findTagInSet(cacheSet, address);
32612531Sandreas.sandberg@arm.com    if(loc == -1) return NULL;
32712531Sandreas.sandberg@arm.com    return m_cache[cacheSet][loc];
32812531Sandreas.sandberg@arm.com}
32912531Sandreas.sandberg@arm.com
33012531Sandreas.sandberg@arm.com// looks an address up in the cache
33112531Sandreas.sandberg@arm.comconst AbstractCacheEntry*
33212531Sandreas.sandberg@arm.comCacheMemory::lookup(Addr address) const
33312531Sandreas.sandberg@arm.com{
33412531Sandreas.sandberg@arm.com    assert(address == makeLineAddress(address));
33512533Sandreas.sandberg@arm.com    int64_t cacheSet = addressToCacheSet(address);
33612531Sandreas.sandberg@arm.com    int loc = findTagInSet(cacheSet, address);
33712531Sandreas.sandberg@arm.com    if(loc == -1) return NULL;
33812531Sandreas.sandberg@arm.com    return m_cache[cacheSet][loc];
33912531Sandreas.sandberg@arm.com}
34012531Sandreas.sandberg@arm.com
34112531Sandreas.sandberg@arm.com// Sets the most recently used bit for a cache block
34212531Sandreas.sandberg@arm.comvoid
34312531Sandreas.sandberg@arm.comCacheMemory::setMRU(Addr address)
34412531Sandreas.sandberg@arm.com{
34512531Sandreas.sandberg@arm.com    int64_t cacheSet = addressToCacheSet(address);
34612531Sandreas.sandberg@arm.com    int loc = findTagInSet(cacheSet, address);
34712531Sandreas.sandberg@arm.com
34812533Sandreas.sandberg@arm.com    if(loc != -1)
34912531Sandreas.sandberg@arm.com        m_replacementPolicy_ptr->touch(cacheSet, loc, curTick());
35012531Sandreas.sandberg@arm.com}
35112531Sandreas.sandberg@arm.com
35212531Sandreas.sandberg@arm.comvoid
35312531Sandreas.sandberg@arm.comCacheMemory::setMRU(const AbstractCacheEntry *e)
35412531Sandreas.sandberg@arm.com{
35512531Sandreas.sandberg@arm.com    uint32_t cacheSet = e->getSetIndex();
35612531Sandreas.sandberg@arm.com    uint32_t loc = e->getWayIndex();
35712531Sandreas.sandberg@arm.com    m_replacementPolicy_ptr->touch(cacheSet, loc, curTick());
35812531Sandreas.sandberg@arm.com}
35912531Sandreas.sandberg@arm.com
36012531Sandreas.sandberg@arm.comvoid
36112531Sandreas.sandberg@arm.comCacheMemory::setMRU(Addr address, int occupancy)
36212531Sandreas.sandberg@arm.com{
36312531Sandreas.sandberg@arm.com    int64_t cacheSet = addressToCacheSet(address);
36412531Sandreas.sandberg@arm.com    int loc = findTagInSet(cacheSet, address);
36512531Sandreas.sandberg@arm.com
36612531Sandreas.sandberg@arm.com    if(loc != -1) {
36712531Sandreas.sandberg@arm.com        if (m_replacementPolicy_ptr->useOccupancy()) {
36812533Sandreas.sandberg@arm.com            (static_cast<WeightedLRUPolicy*>(m_replacementPolicy_ptr))->
36912531Sandreas.sandberg@arm.com                touch(cacheSet, loc, curTick(), occupancy);
37012531Sandreas.sandberg@arm.com        } else {
37112531Sandreas.sandberg@arm.com            m_replacementPolicy_ptr->
37212531Sandreas.sandberg@arm.com                touch(cacheSet, loc, curTick());
37312531Sandreas.sandberg@arm.com        }
37412531Sandreas.sandberg@arm.com    }
37512531Sandreas.sandberg@arm.com}
37612531Sandreas.sandberg@arm.com
37712531Sandreas.sandberg@arm.comint
37812531Sandreas.sandberg@arm.comCacheMemory::getReplacementWeight(int64_t set, int64_t loc)
37912531Sandreas.sandberg@arm.com{
38012531Sandreas.sandberg@arm.com    assert(set < m_cache_num_sets);
38112531Sandreas.sandberg@arm.com    assert(loc < m_cache_assoc);
38212531Sandreas.sandberg@arm.com    int ret = 0;
38312531Sandreas.sandberg@arm.com    if(m_cache[set][loc] != NULL) {
38412531Sandreas.sandberg@arm.com        ret = m_cache[set][loc]->getNumValidBlocks();
38512531Sandreas.sandberg@arm.com        assert(ret >= 0);
38612531Sandreas.sandberg@arm.com    }
38712531Sandreas.sandberg@arm.com
38812531Sandreas.sandberg@arm.com    return ret;
38912531Sandreas.sandberg@arm.com}
39012531Sandreas.sandberg@arm.com
39112531Sandreas.sandberg@arm.comvoid
39212531Sandreas.sandberg@arm.comCacheMemory::recordCacheContents(int cntrl, CacheRecorder* tr) const
39312531Sandreas.sandberg@arm.com{
39412531Sandreas.sandberg@arm.com    uint64_t warmedUpBlocks = 0;
39512533Sandreas.sandberg@arm.com    uint64_t totalBlocks M5_VAR_USED = (uint64_t)m_cache_num_sets *
39612531Sandreas.sandberg@arm.com                                       (uint64_t)m_cache_assoc;
39712531Sandreas.sandberg@arm.com
39812531Sandreas.sandberg@arm.com    for (int i = 0; i < m_cache_num_sets; i++) {
39912531Sandreas.sandberg@arm.com        for (int j = 0; j < m_cache_assoc; j++) {
40012531Sandreas.sandberg@arm.com            if (m_cache[i][j] != NULL) {
40112531Sandreas.sandberg@arm.com                AccessPermission perm = m_cache[i][j]->m_Permission;
40212531Sandreas.sandberg@arm.com                RubyRequestType request_type = RubyRequestType_NULL;
40312531Sandreas.sandberg@arm.com                if (perm == AccessPermission_Read_Only) {
40412531Sandreas.sandberg@arm.com                    if (m_is_instruction_only_cache) {
40512531Sandreas.sandberg@arm.com                        request_type = RubyRequestType_IFETCH;
40612531Sandreas.sandberg@arm.com                    } else {
40712531Sandreas.sandberg@arm.com                        request_type = RubyRequestType_LD;
40812531Sandreas.sandberg@arm.com                    }
40912531Sandreas.sandberg@arm.com                } else if (perm == AccessPermission_Read_Write) {
41012531Sandreas.sandberg@arm.com                    request_type = RubyRequestType_ST;
41112531Sandreas.sandberg@arm.com                }
41212531Sandreas.sandberg@arm.com
41312531Sandreas.sandberg@arm.com                if (request_type != RubyRequestType_NULL) {
41412531Sandreas.sandberg@arm.com                    tr->addRecord(cntrl, m_cache[i][j]->m_Address,
41512531Sandreas.sandberg@arm.com                                  0, request_type,
41612531Sandreas.sandberg@arm.com                                  m_replacementPolicy_ptr->getLastAccess(i, j),
41712531Sandreas.sandberg@arm.com                                  m_cache[i][j]->getDataBlk());
41812531Sandreas.sandberg@arm.com                    warmedUpBlocks++;
41912531Sandreas.sandberg@arm.com                }
42012531Sandreas.sandberg@arm.com            }
42112531Sandreas.sandberg@arm.com        }
42212531Sandreas.sandberg@arm.com    }
42312531Sandreas.sandberg@arm.com
42412531Sandreas.sandberg@arm.com    DPRINTF(RubyCacheTrace, "%s: %lli blocks of %lli total blocks"
42512531Sandreas.sandberg@arm.com            "recorded %.2f%% \n", name().c_str(), warmedUpBlocks,
42612531Sandreas.sandberg@arm.com            totalBlocks, (float(warmedUpBlocks) / float(totalBlocks)) * 100.0);
42712531Sandreas.sandberg@arm.com}
42812531Sandreas.sandberg@arm.com
42912531Sandreas.sandberg@arm.comvoid
43012531Sandreas.sandberg@arm.comCacheMemory::print(ostream& out) const
43112531Sandreas.sandberg@arm.com{
43212531Sandreas.sandberg@arm.com    out << "Cache dump: " << name() << endl;
43312531Sandreas.sandberg@arm.com    for (int i = 0; i < m_cache_num_sets; i++) {
43412531Sandreas.sandberg@arm.com        for (int j = 0; j < m_cache_assoc; j++) {
43512531Sandreas.sandberg@arm.com            if (m_cache[i][j] != NULL) {
43612531Sandreas.sandberg@arm.com                out << "  Index: " << i
43712531Sandreas.sandberg@arm.com                    << " way: " << j
43812531Sandreas.sandberg@arm.com                    << " entry: " << *m_cache[i][j] << endl;
43912531Sandreas.sandberg@arm.com            } else {
44012531Sandreas.sandberg@arm.com                out << "  Index: " << i
44112531Sandreas.sandberg@arm.com                    << " way: " << j
44212531Sandreas.sandberg@arm.com                    << " entry: NULL" << endl;
44312531Sandreas.sandberg@arm.com            }
44412531Sandreas.sandberg@arm.com        }
44512531Sandreas.sandberg@arm.com    }
44612531Sandreas.sandberg@arm.com}
44712531Sandreas.sandberg@arm.com
44812531Sandreas.sandberg@arm.comvoid
44912531Sandreas.sandberg@arm.comCacheMemory::printData(ostream& out) const
45012531Sandreas.sandberg@arm.com{
45112531Sandreas.sandberg@arm.com    out << "printData() not supported" << endl;
45212531Sandreas.sandberg@arm.com}
45312531Sandreas.sandberg@arm.com
45412531Sandreas.sandberg@arm.comvoid
45512531Sandreas.sandberg@arm.comCacheMemory::setLocked(Addr address, int context)
45612531Sandreas.sandberg@arm.com{
45712531Sandreas.sandberg@arm.com    DPRINTF(RubyCache, "Setting Lock for addr: %#x to %d\n", address, context);
45812531Sandreas.sandberg@arm.com    assert(address == makeLineAddress(address));
45912531Sandreas.sandberg@arm.com    int64_t cacheSet = addressToCacheSet(address);
46012531Sandreas.sandberg@arm.com    int loc = findTagInSet(cacheSet, address);
46112531Sandreas.sandberg@arm.com    assert(loc != -1);
46212531Sandreas.sandberg@arm.com    m_cache[cacheSet][loc]->setLocked(context);
46312531Sandreas.sandberg@arm.com}
46412531Sandreas.sandberg@arm.com
46512531Sandreas.sandberg@arm.comvoid
46612531Sandreas.sandberg@arm.comCacheMemory::clearLocked(Addr address)
46712531Sandreas.sandberg@arm.com{
46812531Sandreas.sandberg@arm.com    DPRINTF(RubyCache, "Clear Lock for addr: %#x\n", address);
46912531Sandreas.sandberg@arm.com    assert(address == makeLineAddress(address));
47012531Sandreas.sandberg@arm.com    int64_t cacheSet = addressToCacheSet(address);
47112531Sandreas.sandberg@arm.com    int loc = findTagInSet(cacheSet, address);
47212531Sandreas.sandberg@arm.com    assert(loc != -1);
47312531Sandreas.sandberg@arm.com    m_cache[cacheSet][loc]->clearLocked();
47412531Sandreas.sandberg@arm.com}
47512531Sandreas.sandberg@arm.com
47612531Sandreas.sandberg@arm.combool
47712531Sandreas.sandberg@arm.comCacheMemory::isLocked(Addr address, int context)
47812531Sandreas.sandberg@arm.com{
47912531Sandreas.sandberg@arm.com    assert(address == makeLineAddress(address));
48012531Sandreas.sandberg@arm.com    int64_t cacheSet = addressToCacheSet(address);
48112531Sandreas.sandberg@arm.com    int loc = findTagInSet(cacheSet, address);
48212533Sandreas.sandberg@arm.com    assert(loc != -1);
48312531Sandreas.sandberg@arm.com    DPRINTF(RubyCache, "Testing Lock for addr: %#llx cur %d con %d\n",
48412531Sandreas.sandberg@arm.com            address, m_cache[cacheSet][loc]->m_locked, context);
48512531Sandreas.sandberg@arm.com    return m_cache[cacheSet][loc]->isLocked(context);
48612531Sandreas.sandberg@arm.com}
48712531Sandreas.sandberg@arm.com
48812531Sandreas.sandberg@arm.comvoid
48912531Sandreas.sandberg@arm.comCacheMemory::regStats()
49012531Sandreas.sandberg@arm.com{
49112531Sandreas.sandberg@arm.com    m_demand_hits
49212531Sandreas.sandberg@arm.com        .name(name() + ".demand_hits")
49312531Sandreas.sandberg@arm.com        .desc("Number of cache demand hits")
49412531Sandreas.sandberg@arm.com        ;
49512531Sandreas.sandberg@arm.com
49612531Sandreas.sandberg@arm.com    m_demand_misses
49712531Sandreas.sandberg@arm.com        .name(name() + ".demand_misses")
49812531Sandreas.sandberg@arm.com        .desc("Number of cache demand misses")
49912531Sandreas.sandberg@arm.com        ;
50012531Sandreas.sandberg@arm.com
50112531Sandreas.sandberg@arm.com    m_demand_accesses
50212531Sandreas.sandberg@arm.com        .name(name() + ".demand_accesses")
50312531Sandreas.sandberg@arm.com        .desc("Number of cache demand accesses")
50412531Sandreas.sandberg@arm.com        ;
50512531Sandreas.sandberg@arm.com
50612531Sandreas.sandberg@arm.com    m_demand_accesses = m_demand_hits + m_demand_misses;
50712531Sandreas.sandberg@arm.com
50812531Sandreas.sandberg@arm.com    m_sw_prefetches
50912531Sandreas.sandberg@arm.com        .name(name() + ".total_sw_prefetches")
51012531Sandreas.sandberg@arm.com        .desc("Number of software prefetches")
51112531Sandreas.sandberg@arm.com        .flags(Stats::nozero)
51212531Sandreas.sandberg@arm.com        ;
51312531Sandreas.sandberg@arm.com
51412531Sandreas.sandberg@arm.com    m_hw_prefetches
51512531Sandreas.sandberg@arm.com        .name(name() + ".total_hw_prefetches")
51612531Sandreas.sandberg@arm.com        .desc("Number of hardware prefetches")
51712531Sandreas.sandberg@arm.com        .flags(Stats::nozero)
51812531Sandreas.sandberg@arm.com        ;
51912531Sandreas.sandberg@arm.com
52012531Sandreas.sandberg@arm.com    m_prefetches
52112531Sandreas.sandberg@arm.com        .name(name() + ".total_prefetches")
52212531Sandreas.sandberg@arm.com        .desc("Number of prefetches")
52312531Sandreas.sandberg@arm.com        .flags(Stats::nozero)
52412531Sandreas.sandberg@arm.com        ;
52512531Sandreas.sandberg@arm.com
52612531Sandreas.sandberg@arm.com    m_prefetches = m_sw_prefetches + m_hw_prefetches;
52712531Sandreas.sandberg@arm.com
52812531Sandreas.sandberg@arm.com    m_accessModeType
52912531Sandreas.sandberg@arm.com        .init(RubyRequestType_NUM)
53012531Sandreas.sandberg@arm.com        .name(name() + ".access_mode")
53112531Sandreas.sandberg@arm.com        .flags(Stats::pdf | Stats::total)
53212531Sandreas.sandberg@arm.com        ;
53312531Sandreas.sandberg@arm.com    for (int i = 0; i < RubyAccessMode_NUM; i++) {
53412531Sandreas.sandberg@arm.com        m_accessModeType
53512531Sandreas.sandberg@arm.com            .subname(i, RubyAccessMode_to_string(RubyAccessMode(i)))
53612531Sandreas.sandberg@arm.com            .flags(Stats::nozero)
53712531Sandreas.sandberg@arm.com            ;
53812531Sandreas.sandberg@arm.com    }
53912531Sandreas.sandberg@arm.com
54012531Sandreas.sandberg@arm.com    numDataArrayReads
54112531Sandreas.sandberg@arm.com        .name(name() + ".num_data_array_reads")
54212531Sandreas.sandberg@arm.com        .desc("number of data array reads")
54312531Sandreas.sandberg@arm.com        .flags(Stats::nozero)
54412531Sandreas.sandberg@arm.com        ;
54512531Sandreas.sandberg@arm.com
54612531Sandreas.sandberg@arm.com    numDataArrayWrites
54712531Sandreas.sandberg@arm.com        .name(name() + ".num_data_array_writes")
54812531Sandreas.sandberg@arm.com        .desc("number of data array writes")
54912531Sandreas.sandberg@arm.com        .flags(Stats::nozero)
55012531Sandreas.sandberg@arm.com        ;
55112531Sandreas.sandberg@arm.com
55212533Sandreas.sandberg@arm.com    numTagArrayReads
55312531Sandreas.sandberg@arm.com        .name(name() + ".num_tag_array_reads")
55412531Sandreas.sandberg@arm.com        .desc("number of tag array reads")
55512531Sandreas.sandberg@arm.com        .flags(Stats::nozero)
55612531Sandreas.sandberg@arm.com        ;
55712531Sandreas.sandberg@arm.com
55812531Sandreas.sandberg@arm.com    numTagArrayWrites
55912531Sandreas.sandberg@arm.com        .name(name() + ".num_tag_array_writes")
56012531Sandreas.sandberg@arm.com        .desc("number of tag array writes")
56112531Sandreas.sandberg@arm.com        .flags(Stats::nozero)
56212531Sandreas.sandberg@arm.com        ;
56312531Sandreas.sandberg@arm.com
56412531Sandreas.sandberg@arm.com    numTagArrayStalls
56512531Sandreas.sandberg@arm.com        .name(name() + ".num_tag_array_stalls")
56612531Sandreas.sandberg@arm.com        .desc("number of stalls caused by tag array")
56712531Sandreas.sandberg@arm.com        .flags(Stats::nozero)
56812531Sandreas.sandberg@arm.com        ;
56912531Sandreas.sandberg@arm.com
57012531Sandreas.sandberg@arm.com    numDataArrayStalls
57112531Sandreas.sandberg@arm.com        .name(name() + ".num_data_array_stalls")
57212531Sandreas.sandberg@arm.com        .desc("number of stalls caused by data array")
57312531Sandreas.sandberg@arm.com        .flags(Stats::nozero)
57412531Sandreas.sandberg@arm.com        ;
57512531Sandreas.sandberg@arm.com}
57612531Sandreas.sandberg@arm.com
57712531Sandreas.sandberg@arm.com// assumption: SLICC generated files will only call this function
57812531Sandreas.sandberg@arm.com// once **all** resources are granted
57912531Sandreas.sandberg@arm.comvoid
58012531Sandreas.sandberg@arm.comCacheMemory::recordRequestType(CacheRequestType requestType, Addr addr)
58112531Sandreas.sandberg@arm.com{
58212531Sandreas.sandberg@arm.com    DPRINTF(RubyStats, "Recorded statistic: %s\n",
58312531Sandreas.sandberg@arm.com            CacheRequestType_to_string(requestType));
58412531Sandreas.sandberg@arm.com    switch(requestType) {
58512531Sandreas.sandberg@arm.com    case CacheRequestType_DataArrayRead:
58612531Sandreas.sandberg@arm.com        if (m_resource_stalls)
58712531Sandreas.sandberg@arm.com            dataArray.reserve(addressToCacheSet(addr));
58812531Sandreas.sandberg@arm.com        numDataArrayReads++;
58912531Sandreas.sandberg@arm.com        return;
59012531Sandreas.sandberg@arm.com    case CacheRequestType_DataArrayWrite:
59112531Sandreas.sandberg@arm.com        if (m_resource_stalls)
59212531Sandreas.sandberg@arm.com            dataArray.reserve(addressToCacheSet(addr));
59312531Sandreas.sandberg@arm.com        numDataArrayWrites++;
59412531Sandreas.sandberg@arm.com        return;
59512531Sandreas.sandberg@arm.com    case CacheRequestType_TagArrayRead:
59612531Sandreas.sandberg@arm.com        if (m_resource_stalls)
59712531Sandreas.sandberg@arm.com            tagArray.reserve(addressToCacheSet(addr));
59812531Sandreas.sandberg@arm.com        numTagArrayReads++;
59912531Sandreas.sandberg@arm.com        return;
60012531Sandreas.sandberg@arm.com    case CacheRequestType_TagArrayWrite:
60112531Sandreas.sandberg@arm.com        if (m_resource_stalls)
60212531Sandreas.sandberg@arm.com            tagArray.reserve(addressToCacheSet(addr));
60312531Sandreas.sandberg@arm.com        numTagArrayWrites++;
60412531Sandreas.sandberg@arm.com        return;
60512531Sandreas.sandberg@arm.com    default:
60612531Sandreas.sandberg@arm.com        warn("CacheMemory access_type not found: %s",
60712531Sandreas.sandberg@arm.com             CacheRequestType_to_string(requestType));
60812531Sandreas.sandberg@arm.com    }
60912533Sandreas.sandberg@arm.com}
61012531Sandreas.sandberg@arm.com
61112531Sandreas.sandberg@arm.combool
61212531Sandreas.sandberg@arm.comCacheMemory::checkResourceAvailable(CacheResourceType res, Addr addr)
61312531Sandreas.sandberg@arm.com{
61412531Sandreas.sandberg@arm.com    if (!m_resource_stalls) {
61512531Sandreas.sandberg@arm.com        return true;
61612531Sandreas.sandberg@arm.com    }
61712531Sandreas.sandberg@arm.com
61812531Sandreas.sandberg@arm.com    if (res == CacheResourceType_TagArray) {
61912531Sandreas.sandberg@arm.com        if (tagArray.tryAccess(addressToCacheSet(addr))) return true;
62012531Sandreas.sandberg@arm.com        else {
62112531Sandreas.sandberg@arm.com            DPRINTF(RubyResourceStalls,
62212531Sandreas.sandberg@arm.com                    "Tag array stall on addr %#x in set %d\n",
62312531Sandreas.sandberg@arm.com                    addr, addressToCacheSet(addr));
62412531Sandreas.sandberg@arm.com            numTagArrayStalls++;
62512531Sandreas.sandberg@arm.com            return false;
62612531Sandreas.sandberg@arm.com        }
62712531Sandreas.sandberg@arm.com    } else if (res == CacheResourceType_DataArray) {
62812531Sandreas.sandberg@arm.com        if (dataArray.tryAccess(addressToCacheSet(addr))) return true;
62912531Sandreas.sandberg@arm.com        else {
63012531Sandreas.sandberg@arm.com            DPRINTF(RubyResourceStalls,
63112531Sandreas.sandberg@arm.com                    "Data array stall on addr %#x in set %d\n",
63212531Sandreas.sandberg@arm.com                    addr, addressToCacheSet(addr));
63312531Sandreas.sandberg@arm.com            numDataArrayStalls++;
63412531Sandreas.sandberg@arm.com            return false;
63512531Sandreas.sandberg@arm.com        }
63612531Sandreas.sandberg@arm.com    } else {
63712531Sandreas.sandberg@arm.com        assert(false);
63812531Sandreas.sandberg@arm.com        return true;
63912531Sandreas.sandberg@arm.com    }
64012531Sandreas.sandberg@arm.com}
64112531Sandreas.sandberg@arm.com
64212531Sandreas.sandberg@arm.combool
64312531Sandreas.sandberg@arm.comCacheMemory::isBlockInvalid(int64_t cache_set, int64_t loc)
64412531Sandreas.sandberg@arm.com{
64512531Sandreas.sandberg@arm.com  return (m_cache[cache_set][loc]->m_Permission == AccessPermission_Invalid);
64612531Sandreas.sandberg@arm.com}
64712531Sandreas.sandberg@arm.com
64812531Sandreas.sandberg@arm.combool
64912531Sandreas.sandberg@arm.comCacheMemory::isBlockNotBusy(int64_t cache_set, int64_t loc)
65012531Sandreas.sandberg@arm.com{
65112531Sandreas.sandberg@arm.com  return (m_cache[cache_set][loc]->m_Permission != AccessPermission_Busy);
65212531Sandreas.sandberg@arm.com}
65312531Sandreas.sandberg@arm.com