CacheMemory.cc revision 8937
17584SAli.Saidi@arm.com/*
210718SAndreas.Sandberg@ARM.com * Copyright (c) 1999-2012 Mark D. Hill and David A. Wood
37584SAli.Saidi@arm.com * All rights reserved.
47584SAli.Saidi@arm.com *
57584SAli.Saidi@arm.com * Redistribution and use in source and binary forms, with or without
67584SAli.Saidi@arm.com * modification, are permitted provided that the following conditions are
77584SAli.Saidi@arm.com * met: redistributions of source code must retain the above copyright
87584SAli.Saidi@arm.com * notice, this list of conditions and the following disclaimer;
97584SAli.Saidi@arm.com * redistributions in binary form must reproduce the above copyright
107584SAli.Saidi@arm.com * notice, this list of conditions and the following disclaimer in the
117584SAli.Saidi@arm.com * documentation and/or other materials provided with the distribution;
127584SAli.Saidi@arm.com * neither the name of the copyright holders nor the names of its
137584SAli.Saidi@arm.com * contributors may be used to endorse or promote products derived from
147584SAli.Saidi@arm.com * this software without specific prior written permission.
157584SAli.Saidi@arm.com *
167584SAli.Saidi@arm.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
177584SAli.Saidi@arm.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
187584SAli.Saidi@arm.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
197584SAli.Saidi@arm.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
207584SAli.Saidi@arm.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
217584SAli.Saidi@arm.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
227584SAli.Saidi@arm.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
237584SAli.Saidi@arm.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
247584SAli.Saidi@arm.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
257584SAli.Saidi@arm.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
267584SAli.Saidi@arm.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
277584SAli.Saidi@arm.com */
287584SAli.Saidi@arm.com
297584SAli.Saidi@arm.com#include "base/intmath.hh"
307584SAli.Saidi@arm.com#include "debug/RubyCache.hh"
317584SAli.Saidi@arm.com#include "debug/RubyCacheTrace.hh"
327584SAli.Saidi@arm.com#include "mem/protocol/AccessPermission.hh"
337584SAli.Saidi@arm.com#include "mem/ruby/system/CacheMemory.hh"
347584SAli.Saidi@arm.com#include "mem/ruby/system/System.hh"
357584SAli.Saidi@arm.com
367584SAli.Saidi@arm.comusing namespace std;
377584SAli.Saidi@arm.com
387584SAli.Saidi@arm.comostream&
397584SAli.Saidi@arm.comoperator<<(ostream& out, const CacheMemory& obj)
407584SAli.Saidi@arm.com{
4110718SAndreas.Sandberg@ARM.com    obj.print(out);
427584SAli.Saidi@arm.com    out << flush;
437584SAli.Saidi@arm.com    return out;
4410718SAndreas.Sandberg@ARM.com}
4510718SAndreas.Sandberg@ARM.com
467584SAli.Saidi@arm.comCacheMemory *
478245Snate@binkert.orgRubyCacheParams::create()
488245Snate@binkert.org{
497587SAli.Saidi@arm.com    return new CacheMemory(this);
509525SAndreas.Sandberg@ARM.com}
517584SAli.Saidi@arm.com
527584SAli.Saidi@arm.comCacheMemory::CacheMemory(const Params *p)
5311793Sbrandon.potter@amd.com    : SimObject(p)
547584SAli.Saidi@arm.com{
557584SAli.Saidi@arm.com    m_cache_size = p->size;
5610718SAndreas.Sandberg@ARM.com    m_latency = p->latency;
5712772Snikos.nikoleris@arm.com    m_cache_assoc = p->assoc;
5812086Sspwilson2@wisc.edu    m_policy = p->replacement_policy;
5910718SAndreas.Sandberg@ARM.com    m_profiler_ptr = new CacheProfiler(name());
6010718SAndreas.Sandberg@ARM.com    m_start_index_bit = p->start_index_bit;
6110718SAndreas.Sandberg@ARM.com    m_is_instruction_only_cache = p->is_icache;
6210718SAndreas.Sandberg@ARM.com}
637584SAli.Saidi@arm.com
647584SAli.Saidi@arm.comvoid
657584SAli.Saidi@arm.comCacheMemory::init()
667584SAli.Saidi@arm.com{
677584SAli.Saidi@arm.com    m_cache_num_sets = (m_cache_size / m_cache_assoc) /
687584SAli.Saidi@arm.com        RubySystem::getBlockSizeBytes();
697584SAli.Saidi@arm.com    assert(m_cache_num_sets > 1);
707584SAli.Saidi@arm.com    m_cache_num_set_bits = floorLog2(m_cache_num_sets);
717584SAli.Saidi@arm.com    assert(m_cache_num_set_bits > 0);
727584SAli.Saidi@arm.com
737584SAli.Saidi@arm.com    if (m_policy == "PSEUDO_LRU")
747584SAli.Saidi@arm.com        m_replacementPolicy_ptr =
757584SAli.Saidi@arm.com            new PseudoLRUPolicy(m_cache_num_sets, m_cache_assoc);
767584SAli.Saidi@arm.com    else if (m_policy == "LRU")
777584SAli.Saidi@arm.com        m_replacementPolicy_ptr =
787584SAli.Saidi@arm.com            new LRUPolicy(m_cache_num_sets, m_cache_assoc);
797584SAli.Saidi@arm.com    else
807584SAli.Saidi@arm.com        assert(false);
817584SAli.Saidi@arm.com
827584SAli.Saidi@arm.com    m_cache.resize(m_cache_num_sets);
8312237Sandreas.sandberg@arm.com    for (int i = 0; i < m_cache_num_sets; i++) {
8412237Sandreas.sandberg@arm.com        m_cache[i].resize(m_cache_assoc);
8510718SAndreas.Sandberg@ARM.com        for (int j = 0; j < m_cache_assoc; j++) {
8610718SAndreas.Sandberg@ARM.com            m_cache[i][j] = NULL;
8710718SAndreas.Sandberg@ARM.com        }
8812237Sandreas.sandberg@arm.com    }
8911685Sbaz21@cam.ac.uk}
9011685Sbaz21@cam.ac.uk
9111685Sbaz21@cam.ac.ukCacheMemory::~CacheMemory()
9211685Sbaz21@cam.ac.uk{
9310718SAndreas.Sandberg@ARM.com    if (m_replacementPolicy_ptr != NULL)
947584SAli.Saidi@arm.com        delete m_replacementPolicy_ptr;
9513024Smadnaurice@googlemail.com    delete m_profiler_ptr;
9613024Smadnaurice@googlemail.com    for (int i = 0; i < m_cache_num_sets; i++) {
9713024Smadnaurice@googlemail.com        for (int j = 0; j < m_cache_assoc; j++) {
987584SAli.Saidi@arm.com            delete m_cache[i][j];
9910718SAndreas.Sandberg@ARM.com        }
10010718SAndreas.Sandberg@ARM.com    }
10111480Sbaz21@cam.ac.uk}
10212237Sandreas.sandberg@arm.com
10310718SAndreas.Sandberg@ARM.comvoid
10410718SAndreas.Sandberg@ARM.comCacheMemory::printConfig(ostream& out)
10510718SAndreas.Sandberg@ARM.com{
10610718SAndreas.Sandberg@ARM.com    int block_size = RubySystem::getBlockSizeBytes();
10710718SAndreas.Sandberg@ARM.com
10810718SAndreas.Sandberg@ARM.com    out << "Cache config: " << m_cache_name << endl;
1097584SAli.Saidi@arm.com    out << "  cache_associativity: " << m_cache_assoc << endl;
1107584SAli.Saidi@arm.com    out << "  num_cache_sets_bits: " << m_cache_num_set_bits << endl;
1117584SAli.Saidi@arm.com    const int cache_num_sets = 1 << m_cache_num_set_bits;
1127584SAli.Saidi@arm.com    out << "  num_cache_sets: " << cache_num_sets << endl;
1137584SAli.Saidi@arm.com    out << "  cache_set_size_bytes: " << cache_num_sets * block_size << endl;
1147584SAli.Saidi@arm.com    out << "  cache_set_size_Kbytes: "
1157584SAli.Saidi@arm.com        << double(cache_num_sets * block_size) / (1<<10) << endl;
1167584SAli.Saidi@arm.com    out << "  cache_set_size_Mbytes: "
1177584SAli.Saidi@arm.com        << double(cache_num_sets * block_size) / (1<<20) << endl;
1187584SAli.Saidi@arm.com    out << "  cache_size_bytes: "
1197584SAli.Saidi@arm.com        << cache_num_sets * block_size * m_cache_assoc << endl;
1207584SAli.Saidi@arm.com    out << "  cache_size_Kbytes: "
1217584SAli.Saidi@arm.com        << double(cache_num_sets * block_size * m_cache_assoc) / (1<<10)
1227584SAli.Saidi@arm.com        << endl;
1237584SAli.Saidi@arm.com    out << "  cache_size_Mbytes: "
1247584SAli.Saidi@arm.com        << double(cache_num_sets * block_size * m_cache_assoc) / (1<<20)
1257584SAli.Saidi@arm.com        << endl;
1267584SAli.Saidi@arm.com}
1277584SAli.Saidi@arm.com
1287584SAli.Saidi@arm.com// convert a Address to its location in the cache
1297584SAli.Saidi@arm.comIndex
1307584SAli.Saidi@arm.comCacheMemory::addressToCacheSet(const Address& address) const
1317584SAli.Saidi@arm.com{
1327584SAli.Saidi@arm.com    assert(address == line_address(address));
13310718SAndreas.Sandberg@ARM.com    return address.bitSelect(m_start_index_bit,
13410718SAndreas.Sandberg@ARM.com                             m_start_index_bit + m_cache_num_set_bits - 1);
1357584SAli.Saidi@arm.com}
1367584SAli.Saidi@arm.com
1379806Sstever@gmail.com// Given a cache index: returns the index of the tag in a set.
1387587SAli.Saidi@arm.com// returns -1 if the tag is not found.
1397587SAli.Saidi@arm.comint
1407584SAli.Saidi@arm.comCacheMemory::findTagInSet(Index cacheSet, const Address& tag) const
1417584SAli.Saidi@arm.com{
1427587SAli.Saidi@arm.com    assert(tag == line_address(tag));
1437584SAli.Saidi@arm.com    // search the set for the tags
1447584SAli.Saidi@arm.com    m5::hash_map<Address, int>::const_iterator it = m_tag_index.find(tag);
1457584SAli.Saidi@arm.com    if (it != m_tag_index.end())
1467584SAli.Saidi@arm.com        if (m_cache[cacheSet][it->second]->m_Permission !=
1477584SAli.Saidi@arm.com            AccessPermission_NotPresent)
1487584SAli.Saidi@arm.com            return it->second;
1497584SAli.Saidi@arm.com    return -1; // Not found
1507584SAli.Saidi@arm.com}
1517584SAli.Saidi@arm.com
1527584SAli.Saidi@arm.com// Given a cache index: returns the index of the tag in a set.
1537584SAli.Saidi@arm.com// returns -1 if the tag is not found.
1547584SAli.Saidi@arm.comint
1557584SAli.Saidi@arm.comCacheMemory::findTagInSetIgnorePermissions(Index cacheSet,
1567584SAli.Saidi@arm.com                                           const Address& tag) const
1577584SAli.Saidi@arm.com{
1587584SAli.Saidi@arm.com    assert(tag == line_address(tag));
1597584SAli.Saidi@arm.com    // search the set for the tags
1607584SAli.Saidi@arm.com    m5::hash_map<Address, int>::const_iterator it = m_tag_index.find(tag);
1617584SAli.Saidi@arm.com    if (it != m_tag_index.end())
1627584SAli.Saidi@arm.com        return it->second;
1637584SAli.Saidi@arm.com    return -1; // Not found
1647584SAli.Saidi@arm.com}
1657584SAli.Saidi@arm.com
1667584SAli.Saidi@arm.combool
1677584SAli.Saidi@arm.comCacheMemory::tryCacheAccess(const Address& address, RubyRequestType type,
1687584SAli.Saidi@arm.com                            DataBlock*& data_ptr)
1697584SAli.Saidi@arm.com{
1707584SAli.Saidi@arm.com    assert(address == line_address(address));
1717584SAli.Saidi@arm.com    DPRINTF(RubyCache, "address: %s\n", address);
1727584SAli.Saidi@arm.com    Index cacheSet = addressToCacheSet(address);
1737584SAli.Saidi@arm.com    int loc = findTagInSet(cacheSet, address);
1747584SAli.Saidi@arm.com    if (loc != -1) {
1757584SAli.Saidi@arm.com        // Do we even have a tag match?
1767584SAli.Saidi@arm.com        AbstractCacheEntry* entry = m_cache[cacheSet][loc];
1777584SAli.Saidi@arm.com        m_replacementPolicy_ptr->
1787584SAli.Saidi@arm.com            touch(cacheSet, loc, g_eventQueue_ptr->getTime());
1797584SAli.Saidi@arm.com        data_ptr = &(entry->getDataBlk());
1807584SAli.Saidi@arm.com
1817584SAli.Saidi@arm.com        if (entry->m_Permission == AccessPermission_Read_Write) {
1827584SAli.Saidi@arm.com            return true;
1837584SAli.Saidi@arm.com        }
1847584SAli.Saidi@arm.com        if ((entry->m_Permission == AccessPermission_Read_Only) &&
1857584SAli.Saidi@arm.com            (type == RubyRequestType_LD || type == RubyRequestType_IFETCH)) {
1867584SAli.Saidi@arm.com            return true;
1877584SAli.Saidi@arm.com        }
1887584SAli.Saidi@arm.com        // The line must not be accessible
1897584SAli.Saidi@arm.com    }
1907584SAli.Saidi@arm.com    data_ptr = NULL;
1917584SAli.Saidi@arm.com    return false;
1927584SAli.Saidi@arm.com}
1937584SAli.Saidi@arm.com
1947584SAli.Saidi@arm.combool
1957584SAli.Saidi@arm.comCacheMemory::testCacheAccess(const Address& address, RubyRequestType type,
1967584SAli.Saidi@arm.com                             DataBlock*& data_ptr)
1977584SAli.Saidi@arm.com{
1987584SAli.Saidi@arm.com    assert(address == line_address(address));
1997584SAli.Saidi@arm.com    DPRINTF(RubyCache, "address: %s\n", address);
2007584SAli.Saidi@arm.com    Index cacheSet = addressToCacheSet(address);
2017584SAli.Saidi@arm.com    int loc = findTagInSet(cacheSet, address);
2027584SAli.Saidi@arm.com
2037584SAli.Saidi@arm.com    if (loc != -1) {
20412237Sandreas.sandberg@arm.com        // Do we even have a tag match?
20510718SAndreas.Sandberg@ARM.com        AbstractCacheEntry* entry = m_cache[cacheSet][loc];
20610718SAndreas.Sandberg@ARM.com        m_replacementPolicy_ptr->
20710718SAndreas.Sandberg@ARM.com            touch(cacheSet, loc, g_eventQueue_ptr->getTime());
20810718SAndreas.Sandberg@ARM.com        data_ptr = &(entry->getDataBlk());
20910718SAndreas.Sandberg@ARM.com
2107584SAli.Saidi@arm.com        return m_cache[cacheSet][loc]->m_Permission !=
21113024Smadnaurice@googlemail.com            AccessPermission_NotPresent;
21213024Smadnaurice@googlemail.com    }
2137584SAli.Saidi@arm.com
2147584SAli.Saidi@arm.com    data_ptr = NULL;
2157584SAli.Saidi@arm.com    return false;
2167584SAli.Saidi@arm.com}
2177584SAli.Saidi@arm.com
2187584SAli.Saidi@arm.com// tests to see if an address is present in the cache
2197584SAli.Saidi@arm.combool
2207584SAli.Saidi@arm.comCacheMemory::isTagPresent(const Address& address) const
2217584SAli.Saidi@arm.com{
2227584SAli.Saidi@arm.com    assert(address == line_address(address));
2237584SAli.Saidi@arm.com    Index cacheSet = addressToCacheSet(address);
2247584SAli.Saidi@arm.com    int loc = findTagInSet(cacheSet, address);
2257584SAli.Saidi@arm.com
2267584SAli.Saidi@arm.com    if (loc == -1) {
2277584SAli.Saidi@arm.com        // We didn't find the tag
2287584SAli.Saidi@arm.com        DPRINTF(RubyCache, "No tag match for address: %s\n", address);
22910718SAndreas.Sandberg@ARM.com        return false;
23010718SAndreas.Sandberg@ARM.com    }
2317584SAli.Saidi@arm.com    DPRINTF(RubyCache, "address: %s found\n", address);
2327584SAli.Saidi@arm.com    return true;
2337584SAli.Saidi@arm.com}
2347584SAli.Saidi@arm.com
23510718SAndreas.Sandberg@ARM.com// Returns true if there is:
23612237Sandreas.sandberg@arm.com//   a) a tag match on this address or there is
23711685Sbaz21@cam.ac.uk//   b) an unused line in the same cache "way"
23811685Sbaz21@cam.ac.ukbool
23911685Sbaz21@cam.ac.ukCacheMemory::cacheAvail(const Address& address) const
24011685Sbaz21@cam.ac.uk{
2417584SAli.Saidi@arm.com    assert(address == line_address(address));
2427584SAli.Saidi@arm.com
2437584SAli.Saidi@arm.com    Index cacheSet = addressToCacheSet(address);
2447584SAli.Saidi@arm.com
2457584SAli.Saidi@arm.com    for (int i = 0; i < m_cache_assoc; i++) {
2467584SAli.Saidi@arm.com        AbstractCacheEntry* entry = m_cache[cacheSet][i];
2477584SAli.Saidi@arm.com        if (entry != NULL) {
2487584SAli.Saidi@arm.com            if (entry->m_Address == address ||
2497584SAli.Saidi@arm.com                entry->m_Permission == AccessPermission_NotPresent) {
2507584SAli.Saidi@arm.com                // Already in the cache or we found an empty entry
2517584SAli.Saidi@arm.com                return true;
2527584SAli.Saidi@arm.com            }
2537584SAli.Saidi@arm.com        } else {
2547584SAli.Saidi@arm.com            return true;
2557584SAli.Saidi@arm.com        }
25610718SAndreas.Sandberg@ARM.com    }
2577584SAli.Saidi@arm.com    return false;
2587584SAli.Saidi@arm.com}
2597584SAli.Saidi@arm.com
2607584SAli.Saidi@arm.comAbstractCacheEntry*
2617584SAli.Saidi@arm.comCacheMemory::allocate(const Address& address, AbstractCacheEntry* entry)
2627584SAli.Saidi@arm.com{
26310718SAndreas.Sandberg@ARM.com    assert(address == line_address(address));
2647584SAli.Saidi@arm.com    assert(!isTagPresent(address));
26510718SAndreas.Sandberg@ARM.com    assert(cacheAvail(address));
2667584SAli.Saidi@arm.com    DPRINTF(RubyCache, "address: %s\n", address);
2677584SAli.Saidi@arm.com
2687584SAli.Saidi@arm.com    // Find the first open slot
26910718SAndreas.Sandberg@ARM.com    Index cacheSet = addressToCacheSet(address);
2707584SAli.Saidi@arm.com    std::vector<AbstractCacheEntry*> &set = m_cache[cacheSet];
27110718SAndreas.Sandberg@ARM.com    for (int i = 0; i < m_cache_assoc; i++) {
27210718SAndreas.Sandberg@ARM.com        if (!set[i] || set[i]->m_Permission == AccessPermission_NotPresent) {
27310718SAndreas.Sandberg@ARM.com            set[i] = entry;  // Init entry
27410718SAndreas.Sandberg@ARM.com            set[i]->m_Address = address;
27510718SAndreas.Sandberg@ARM.com            set[i]->m_Permission = AccessPermission_Invalid;
27610718SAndreas.Sandberg@ARM.com            DPRINTF(RubyCache, "Allocate clearing lock for addr: %x\n",
27710718SAndreas.Sandberg@ARM.com                    address);
27810718SAndreas.Sandberg@ARM.com            set[i]->m_locked = -1;
27910718SAndreas.Sandberg@ARM.com            m_tag_index[address] = i;
28010718SAndreas.Sandberg@ARM.com
28110718SAndreas.Sandberg@ARM.com            m_replacementPolicy_ptr->
28210718SAndreas.Sandberg@ARM.com                touch(cacheSet, i, g_eventQueue_ptr->getTime());
28310718SAndreas.Sandberg@ARM.com
28410718SAndreas.Sandberg@ARM.com            return entry;
2857584SAli.Saidi@arm.com        }
2867584SAli.Saidi@arm.com    }
2877584SAli.Saidi@arm.com    panic("Allocate didn't find an available entry");
2887584SAli.Saidi@arm.com}
2897584SAli.Saidi@arm.com
29010905Sandreas.sandberg@arm.comvoid
2917584SAli.Saidi@arm.comCacheMemory::deallocate(const Address& address)
2927733SAli.Saidi@ARM.com{
2937733SAli.Saidi@ARM.com    assert(address == line_address(address));
2947733SAli.Saidi@ARM.com    assert(isTagPresent(address));
2957733SAli.Saidi@ARM.com    DPRINTF(RubyCache, "address: %s\n", address);
2967733SAli.Saidi@ARM.com    Index cacheSet = addressToCacheSet(address);
2977733SAli.Saidi@ARM.com    int loc = findTagInSet(cacheSet, address);
2987733SAli.Saidi@ARM.com    if (loc != -1) {
29910718SAndreas.Sandberg@ARM.com        delete m_cache[cacheSet][loc];
30010905Sandreas.sandberg@arm.com        m_cache[cacheSet][loc] = NULL;
30110905Sandreas.sandberg@arm.com        m_tag_index.erase(address);
3027584SAli.Saidi@arm.com    }
3037584SAli.Saidi@arm.com}
3047584SAli.Saidi@arm.com
30510905Sandreas.sandberg@arm.com// Returns with the physical address of the conflicting cache line
3067584SAli.Saidi@arm.comAddress
3077733SAli.Saidi@ARM.comCacheMemory::cacheProbe(const Address& address) const
3087733SAli.Saidi@ARM.com{
3097733SAli.Saidi@ARM.com    assert(address == line_address(address));
3107733SAli.Saidi@ARM.com    assert(!cacheAvail(address));
3117733SAli.Saidi@ARM.com
3127733SAli.Saidi@ARM.com    Index cacheSet = addressToCacheSet(address);
3137733SAli.Saidi@ARM.com    return m_cache[cacheSet][m_replacementPolicy_ptr->getVictim(cacheSet)]->
3147733SAli.Saidi@ARM.com        m_Address;
31510718SAndreas.Sandberg@ARM.com}
31610905Sandreas.sandberg@arm.com
31710905Sandreas.sandberg@arm.com// looks an address up in the cache
3187584SAli.Saidi@arm.comAbstractCacheEntry*
3197584SAli.Saidi@arm.comCacheMemory::lookup(const Address& address)
3207584SAli.Saidi@arm.com{
3217584SAli.Saidi@arm.com    assert(address == line_address(address));
3227584SAli.Saidi@arm.com    Index cacheSet = addressToCacheSet(address);
3237584SAli.Saidi@arm.com    int loc = findTagInSet(cacheSet, address);
3247584SAli.Saidi@arm.com    if(loc == -1) return NULL;
325    return m_cache[cacheSet][loc];
326}
327
328// looks an address up in the cache
329const AbstractCacheEntry*
330CacheMemory::lookup(const Address& address) const
331{
332    assert(address == line_address(address));
333    Index cacheSet = addressToCacheSet(address);
334    int loc = findTagInSet(cacheSet, address);
335    if(loc == -1) return NULL;
336    return m_cache[cacheSet][loc];
337}
338
339// Sets the most recently used bit for a cache block
340void
341CacheMemory::setMRU(const Address& address)
342{
343    Index cacheSet = addressToCacheSet(address);
344    int loc = findTagInSet(cacheSet, address);
345
346    if(loc != -1)
347        m_replacementPolicy_ptr->
348             touch(cacheSet, loc, g_eventQueue_ptr->getTime());
349}
350
351void
352CacheMemory::profileMiss(const RubyRequest& msg)
353{
354    m_profiler_ptr->addCacheStatSample(msg.getType(),
355                                       msg.getAccessMode(),
356                                       msg.getPrefetch());
357}
358
359void
360CacheMemory::profileGenericRequest(GenericRequestType requestType,
361                                   RubyAccessMode accessType,
362                                   PrefetchBit pfBit)
363{
364    m_profiler_ptr->addGenericStatSample(requestType,
365                                         accessType,
366                                         pfBit);
367}
368
369void
370CacheMemory::recordCacheContents(int cntrl, CacheRecorder* tr) const
371{
372    uint64 warmedUpBlocks = 0;
373    uint64 totalBlocks M5_VAR_USED = (uint64)m_cache_num_sets
374                                                  * (uint64)m_cache_assoc;
375
376    for (int i = 0; i < m_cache_num_sets; i++) {
377        for (int j = 0; j < m_cache_assoc; j++) {
378            if (m_cache[i][j] != NULL) {
379                AccessPermission perm = m_cache[i][j]->m_Permission;
380                RubyRequestType request_type = RubyRequestType_NULL;
381                if (perm == AccessPermission_Read_Only) {
382                    if (m_is_instruction_only_cache) {
383                        request_type = RubyRequestType_IFETCH;
384                    } else {
385                        request_type = RubyRequestType_LD;
386                    }
387                } else if (perm == AccessPermission_Read_Write) {
388                    request_type = RubyRequestType_ST;
389                }
390
391                if (request_type != RubyRequestType_NULL) {
392                    tr->addRecord(cntrl, m_cache[i][j]->m_Address.getAddress(),
393                                  0, request_type,
394                                  m_replacementPolicy_ptr->getLastAccess(i, j),
395                                  m_cache[i][j]->getDataBlk());
396                    warmedUpBlocks++;
397                }
398            }
399        }
400    }
401
402    DPRINTF(RubyCacheTrace, "%s: %lli blocks of %lli total blocks"
403            "recorded %.2f%% \n", name().c_str(), warmedUpBlocks,
404            (uint64)m_cache_num_sets * (uint64)m_cache_assoc,
405            (float(warmedUpBlocks)/float(totalBlocks))*100.0);
406}
407
408void
409CacheMemory::print(ostream& out) const
410{
411    out << "Cache dump: " << m_cache_name << endl;
412    for (int i = 0; i < m_cache_num_sets; i++) {
413        for (int j = 0; j < m_cache_assoc; j++) {
414            if (m_cache[i][j] != NULL) {
415                out << "  Index: " << i
416                    << " way: " << j
417                    << " entry: " << *m_cache[i][j] << endl;
418            } else {
419                out << "  Index: " << i
420                    << " way: " << j
421                    << " entry: NULL" << endl;
422            }
423        }
424    }
425}
426
427void
428CacheMemory::printData(ostream& out) const
429{
430    out << "printData() not supported" << endl;
431}
432
433void
434CacheMemory::clearStats() const
435{
436    m_profiler_ptr->clearStats();
437}
438
439void
440CacheMemory::printStats(ostream& out) const
441{
442    m_profiler_ptr->printStats(out);
443}
444
445void
446CacheMemory::setLocked(const Address& address, int context)
447{
448    DPRINTF(RubyCache, "Setting Lock for addr: %x to %d\n", address, context);
449    assert(address == line_address(address));
450    Index cacheSet = addressToCacheSet(address);
451    int loc = findTagInSet(cacheSet, address);
452    assert(loc != -1);
453    m_cache[cacheSet][loc]->m_locked = context;
454}
455
456void
457CacheMemory::clearLocked(const Address& address)
458{
459    DPRINTF(RubyCache, "Clear Lock for addr: %x\n", address);
460    assert(address == line_address(address));
461    Index cacheSet = addressToCacheSet(address);
462    int loc = findTagInSet(cacheSet, address);
463    assert(loc != -1);
464    m_cache[cacheSet][loc]->m_locked = -1;
465}
466
467bool
468CacheMemory::isLocked(const Address& address, int context)
469{
470    assert(address == line_address(address));
471    Index cacheSet = addressToCacheSet(address);
472    int loc = findTagInSet(cacheSet, address);
473    assert(loc != -1);
474    DPRINTF(RubyCache, "Testing Lock for addr: %llx cur %d con %d\n",
475            address, m_cache[cacheSet][loc]->m_locked, context);
476    return m_cache[cacheSet][loc]->m_locked == context;
477}
478
479