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