CacheMemory.hh revision 6374
112950Sgabeblack@google.com/* 212950Sgabeblack@google.com * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood 312950Sgabeblack@google.com * All rights reserved. 412950Sgabeblack@google.com * 512950Sgabeblack@google.com * Redistribution and use in source and binary forms, with or without 612950Sgabeblack@google.com * modification, are permitted provided that the following conditions are 712950Sgabeblack@google.com * met: redistributions of source code must retain the above copyright 812950Sgabeblack@google.com * notice, this list of conditions and the following disclaimer; 912950Sgabeblack@google.com * redistributions in binary form must reproduce the above copyright 1012950Sgabeblack@google.com * notice, this list of conditions and the following disclaimer in the 1112950Sgabeblack@google.com * documentation and/or other materials provided with the distribution; 1212950Sgabeblack@google.com * neither the name of the copyright holders nor the names of its 1312950Sgabeblack@google.com * contributors may be used to endorse or promote products derived from 1412950Sgabeblack@google.com * this software without specific prior written permission. 1512950Sgabeblack@google.com * 1612950Sgabeblack@google.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 1712950Sgabeblack@google.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 1812950Sgabeblack@google.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 1912950Sgabeblack@google.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 2012950Sgabeblack@google.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 2112950Sgabeblack@google.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 2212950Sgabeblack@google.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2312950Sgabeblack@google.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2412950Sgabeblack@google.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2512950Sgabeblack@google.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 2612950Sgabeblack@google.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2712950Sgabeblack@google.com */ 2812950Sgabeblack@google.com 2912950Sgabeblack@google.com/* 3012950Sgabeblack@google.com * CacheMemory.hh 3112950Sgabeblack@google.com * 3212988Sgabeblack@google.com * Description: 3312988Sgabeblack@google.com * 3412950Sgabeblack@google.com * $Id: CacheMemory.hh,v 3.7 2004/06/18 20:15:15 beckmann Exp $ 3512950Sgabeblack@google.com * 3612953Sgabeblack@google.com */ 3712950Sgabeblack@google.com 3812950Sgabeblack@google.com#ifndef CACHEMEMORY_H 3912950Sgabeblack@google.com#define CACHEMEMORY_H 4012950Sgabeblack@google.com 4112950Sgabeblack@google.com#include "mem/ruby/common/Global.hh" 4212950Sgabeblack@google.com#include "mem/protocol/AccessPermission.hh" 4312950Sgabeblack@google.com#include "mem/ruby/common/Address.hh" 4412950Sgabeblack@google.com#include "mem/ruby/recorder/CacheRecorder.hh" 4512950Sgabeblack@google.com#include "mem/protocol/CacheRequestType.hh" 4612950Sgabeblack@google.com#include "mem/gems_common/Vector.hh" 4712950Sgabeblack@google.com#include "mem/ruby/common/DataBlock.hh" 4812950Sgabeblack@google.com#include "mem/protocol/MachineType.hh" 4912950Sgabeblack@google.com#include "mem/ruby/slicc_interface/RubySlicc_ComponentMapping.hh" 5012950Sgabeblack@google.com#include "mem/ruby/system/PseudoLRUPolicy.hh" 5112950Sgabeblack@google.com#include "mem/ruby/system/LRUPolicy.hh" 5212950Sgabeblack@google.com#include "mem/ruby/slicc_interface/AbstractCacheEntry.hh" 5312950Sgabeblack@google.com#include "mem/ruby/system/System.hh" 5412950Sgabeblack@google.com#include "mem/ruby/slicc_interface/AbstractController.hh" 5512950Sgabeblack@google.com#include "mem/ruby/profiler/CacheProfiler.hh" 5612950Sgabeblack@google.com#include "mem/protocol/CacheMsg.hh" 5712950Sgabeblack@google.com#include <vector> 5812950Sgabeblack@google.com 5912950Sgabeblack@google.comclass CacheMemory { 6012950Sgabeblack@google.compublic: 6112950Sgabeblack@google.com 6212950Sgabeblack@google.com // Constructors 6312950Sgabeblack@google.com CacheMemory(const string & name); 6412950Sgabeblack@google.com void init(const vector<string> & argv); 6512950Sgabeblack@google.com 6612950Sgabeblack@google.com // Destructor 6712950Sgabeblack@google.com ~CacheMemory(); 6812950Sgabeblack@google.com 6912950Sgabeblack@google.com // factory 7012950Sgabeblack@google.com // static CacheMemory* createCache(int level, int num, char split_type, AbstractCacheEntry* (*entry_factory)()); 7112950Sgabeblack@google.com // static CacheMemory* getCache(int cache_id); 7212955Sgabeblack@google.com 7312950Sgabeblack@google.com // Public Methods 7412955Sgabeblack@google.com void printConfig(ostream& out); 7513085Sgabeblack@google.com 7612950Sgabeblack@google.com // perform a cache access and see if we hit or not. Return true on a hit. 7712950Sgabeblack@google.com bool tryCacheAccess(const Address& address, CacheRequestType type, DataBlock*& data_ptr); 7812950Sgabeblack@google.com 7912950Sgabeblack@google.com // similar to above, but doesn't require full access check 8012950Sgabeblack@google.com bool testCacheAccess(const Address& address, CacheRequestType type, DataBlock*& data_ptr); 8113045Sgabeblack@google.com 8213045Sgabeblack@google.com // tests to see if an address is present in the cache 8312950Sgabeblack@google.com bool isTagPresent(const Address& address) const; 8412950Sgabeblack@google.com 8512950Sgabeblack@google.com // Returns true if there is: 8612950Sgabeblack@google.com // a) a tag match on this address or there is 8712950Sgabeblack@google.com // b) an unused line in the same cache "way" 8812950Sgabeblack@google.com bool cacheAvail(const Address& address) const; 8912950Sgabeblack@google.com 9012950Sgabeblack@google.com // find an unused entry and sets the tag appropriate for the address 9112950Sgabeblack@google.com void allocate(const Address& address, AbstractCacheEntry* new_entry); 9213045Sgabeblack@google.com 9312955Sgabeblack@google.com // Explicitly free up this address 9412953Sgabeblack@google.com void deallocate(const Address& address); 9512953Sgabeblack@google.com 9612953Sgabeblack@google.com // Returns with the physical address of the conflicting cache line 9713126Sgabeblack@google.com Address cacheProbe(const Address& address) const; 9813126Sgabeblack@google.com 9913126Sgabeblack@google.com // looks an address up in the cache 10012950Sgabeblack@google.com AbstractCacheEntry& lookup(const Address& address); 10112950Sgabeblack@google.com const AbstractCacheEntry& lookup(const Address& address) const; 10212955Sgabeblack@google.com 10312950Sgabeblack@google.com // Get/Set permission of cache block 10412950Sgabeblack@google.com AccessPermission getPermission(const Address& address) const; 10512955Sgabeblack@google.com void changePermission(const Address& address, AccessPermission new_perm); 10612950Sgabeblack@google.com 10712950Sgabeblack@google.com int getLatency() const { return m_latency; } 10812950Sgabeblack@google.com 10912950Sgabeblack@google.com // Hook for checkpointing the contents of the cache 11012950Sgabeblack@google.com void recordCacheContents(CacheRecorder& tr) const; 11112952Sgabeblack@google.com void setAsInstructionCache(bool is_icache) { m_is_instruction_only_cache = is_icache; } 11212950Sgabeblack@google.com 11312950Sgabeblack@google.com // Set this address to most recently used 11412950Sgabeblack@google.com void setMRU(const Address& address); 11512955Sgabeblack@google.com 11612955Sgabeblack@google.com void profileMiss(const CacheMsg & msg); 11712950Sgabeblack@google.com 11812950Sgabeblack@google.com void getMemoryValue(const Address& addr, char* value, 11912950Sgabeblack@google.com unsigned int size_in_bytes ); 12012950Sgabeblack@google.com void setMemoryValue(const Address& addr, char* value, 12112950Sgabeblack@google.com unsigned int size_in_bytes ); 12212950Sgabeblack@google.com 12312950Sgabeblack@google.com void setLocked (const Address& addr, int context); 12412950Sgabeblack@google.com void clearLocked (const Address& addr); 12512950Sgabeblack@google.com bool isLocked (const Address& addr, int context); 12612950Sgabeblack@google.com // Print cache contents 12712984Sgabeblack@google.com void print(ostream& out) const; 12812984Sgabeblack@google.com void printData(ostream& out) const; 12912984Sgabeblack@google.com 13012984Sgabeblack@google.com void printStats(ostream& out) const; 13112984Sgabeblack@google.com 13212984Sgabeblack@google.comprivate: 13312950Sgabeblack@google.com // Private Methods 13412950Sgabeblack@google.com 13512950Sgabeblack@google.com // convert a Address to its location in the cache 13612950Sgabeblack@google.com Index addressToCacheSet(const Address& address) const; 13712950Sgabeblack@google.com 13812950Sgabeblack@google.com // Given a cache tag: returns the index of the tag in a set. 13912950Sgabeblack@google.com // returns -1 if the tag is not found. 14012950Sgabeblack@google.com int findTagInSet(Index line, const Address& tag) const; 14112950Sgabeblack@google.com int findTagInSetIgnorePermissions(Index cacheSet, const Address& tag) const; 14212950Sgabeblack@google.com 14312950Sgabeblack@google.com // Private copy constructor and assignment operator 14412950Sgabeblack@google.com CacheMemory(const CacheMemory& obj); 14512950Sgabeblack@google.com CacheMemory& operator=(const CacheMemory& obj); 14612950Sgabeblack@google.com 14712950Sgabeblack@google.comprivate: 14812950Sgabeblack@google.com const string m_cache_name; 14912950Sgabeblack@google.com AbstractController* m_controller; 15012950Sgabeblack@google.com int m_latency; 15112950Sgabeblack@google.com 15212950Sgabeblack@google.com // Data Members (m_prefix) 15312950Sgabeblack@google.com bool m_is_instruction_only_cache; 15412950Sgabeblack@google.com bool m_is_data_only_cache; 15512950Sgabeblack@google.com 15612950Sgabeblack@google.com // The first index is the # of cache lines. 15712950Sgabeblack@google.com // The second index is the the amount associativity. 15812950Sgabeblack@google.com Vector<Vector<AbstractCacheEntry*> > m_cache; 15912950Sgabeblack@google.com Vector<Vector<int> > m_locked; 16012950Sgabeblack@google.com 16112950Sgabeblack@google.com AbstractReplacementPolicy *m_replacementPolicy_ptr; 16212950Sgabeblack@google.com 16312955Sgabeblack@google.com CacheProfiler* m_profiler_ptr; 16412950Sgabeblack@google.com 16512950Sgabeblack@google.com int m_cache_num_sets; 16612950Sgabeblack@google.com int m_cache_num_set_bits; 16712950Sgabeblack@google.com int m_cache_assoc; 16812950Sgabeblack@google.com 16912950Sgabeblack@google.com static Vector< CacheMemory* > m_all_caches; 17012950Sgabeblack@google.com}; 17112950Sgabeblack@google.com 17212950Sgabeblack@google.com// Output operator declaration 17312950Sgabeblack@google.com//ostream& operator<<(ostream& out, const CacheMemory<ENTRY>& obj); 17412950Sgabeblack@google.com 17512950Sgabeblack@google.com// ******************* Definitions ******************* 17612950Sgabeblack@google.com 17712950Sgabeblack@google.com// Output operator definition 17812950Sgabeblack@google.cominline 17912950Sgabeblack@google.comostream& operator<<(ostream& out, const CacheMemory& obj) 18012950Sgabeblack@google.com{ 18112950Sgabeblack@google.com obj.print(out); 18212950Sgabeblack@google.com out << flush; 18312950Sgabeblack@google.com return out; 18412950Sgabeblack@google.com} 18512950Sgabeblack@google.com 18612950Sgabeblack@google.com 18712950Sgabeblack@google.com// **************************************************************** 18812950Sgabeblack@google.com 18912950Sgabeblack@google.cominline 19012950Sgabeblack@google.comCacheMemory::CacheMemory(const string & name) 19112950Sgabeblack@google.com : m_cache_name(name) 19212950Sgabeblack@google.com{ 19312950Sgabeblack@google.com m_profiler_ptr = new CacheProfiler(name); 19412950Sgabeblack@google.com} 19512950Sgabeblack@google.com 19612950Sgabeblack@google.cominline 19712950Sgabeblack@google.comvoid CacheMemory::init(const vector<string> & argv) 19812950Sgabeblack@google.com{ 19912950Sgabeblack@google.com int cache_size = 0; 20012950Sgabeblack@google.com string policy; 20112950Sgabeblack@google.com 20212950Sgabeblack@google.com m_controller = NULL; 20312950Sgabeblack@google.com for (uint32 i=0; i<argv.size(); i+=2) { 20412950Sgabeblack@google.com if (argv[i] == "size_kb") { 20512950Sgabeblack@google.com cache_size = atoi(argv[i+1].c_str()); 20612950Sgabeblack@google.com } else if (argv[i] == "latency") { 20712950Sgabeblack@google.com m_latency = atoi(argv[i+1].c_str()); 20812950Sgabeblack@google.com } else if (argv[i] == "assoc") { 20912950Sgabeblack@google.com m_cache_assoc = atoi(argv[i+1].c_str()); 21012950Sgabeblack@google.com } else if (argv[i] == "replacement_policy") { 21112950Sgabeblack@google.com policy = argv[i+1]; 21212950Sgabeblack@google.com } else if (argv[i] == "controller") { 21312950Sgabeblack@google.com m_controller = RubySystem::getController(argv[i+1]); 21412950Sgabeblack@google.com } else { 21512950Sgabeblack@google.com cerr << "WARNING: CacheMemory: Unknown configuration parameter: " << argv[i] << endl; 21612950Sgabeblack@google.com } 21712950Sgabeblack@google.com } 21812950Sgabeblack@google.com 21912950Sgabeblack@google.com m_cache_num_sets = cache_size / m_cache_assoc; 22012950Sgabeblack@google.com m_cache_num_set_bits = log_int(m_cache_num_sets); 22112950Sgabeblack@google.com 22212950Sgabeblack@google.com if(policy == "PSEUDO_LRU") 22312950Sgabeblack@google.com m_replacementPolicy_ptr = new PseudoLRUPolicy(m_cache_num_sets, m_cache_assoc); 22412950Sgabeblack@google.com else if (policy == "LRU") 22512950Sgabeblack@google.com m_replacementPolicy_ptr = new LRUPolicy(m_cache_num_sets, m_cache_assoc); 22612950Sgabeblack@google.com else 22712950Sgabeblack@google.com assert(false); 22812950Sgabeblack@google.com 22912950Sgabeblack@google.com m_cache.setSize(m_cache_num_sets); 23012950Sgabeblack@google.com m_locked.setSize(m_cache_num_sets); 23112950Sgabeblack@google.com for (int i = 0; i < m_cache_num_sets; i++) { 23212955Sgabeblack@google.com m_cache[i].setSize(m_cache_assoc); 23312955Sgabeblack@google.com m_locked[i].setSize(m_cache_assoc); 23412955Sgabeblack@google.com for (int j = 0; j < m_cache_assoc; j++) { 23512955Sgabeblack@google.com m_cache[i][j] = NULL; 23612955Sgabeblack@google.com m_locked[i][j] = -1; 23712955Sgabeblack@google.com } 23812955Sgabeblack@google.com } 23912988Sgabeblack@google.com} 24012955Sgabeblack@google.com 24112988Sgabeblack@google.cominline 24212988Sgabeblack@google.comCacheMemory::~CacheMemory() 24312955Sgabeblack@google.com{ 24412955Sgabeblack@google.com if(m_replacementPolicy_ptr != NULL) 24512955Sgabeblack@google.com delete m_replacementPolicy_ptr; 24612955Sgabeblack@google.com} 24712950Sgabeblack@google.com 24812950Sgabeblack@google.cominline 24912950Sgabeblack@google.comvoid CacheMemory::printConfig(ostream& out) 25012950Sgabeblack@google.com{ 25112950Sgabeblack@google.com out << "Cache config: " << m_cache_name << endl; 25212950Sgabeblack@google.com if (m_controller != NULL) 25312950Sgabeblack@google.com out << " controller: " << m_controller->getName() << endl; 25412950Sgabeblack@google.com out << " cache_associativity: " << m_cache_assoc << endl; 25512950Sgabeblack@google.com out << " num_cache_sets_bits: " << m_cache_num_set_bits << endl; 25612950Sgabeblack@google.com const int cache_num_sets = 1 << m_cache_num_set_bits; 25712950Sgabeblack@google.com out << " num_cache_sets: " << cache_num_sets << endl; 25812950Sgabeblack@google.com out << " cache_set_size_bytes: " << cache_num_sets * RubySystem::getBlockSizeBytes() << endl; 25912950Sgabeblack@google.com out << " cache_set_size_Kbytes: " 26012950Sgabeblack@google.com << double(cache_num_sets * RubySystem::getBlockSizeBytes()) / (1<<10) << endl; 26112950Sgabeblack@google.com out << " cache_set_size_Mbytes: " 26212950Sgabeblack@google.com << double(cache_num_sets * RubySystem::getBlockSizeBytes()) / (1<<20) << endl; 26312950Sgabeblack@google.com out << " cache_size_bytes: " 26412950Sgabeblack@google.com << cache_num_sets * RubySystem::getBlockSizeBytes() * m_cache_assoc << endl; 265 out << " cache_size_Kbytes: " 266 << double(cache_num_sets * RubySystem::getBlockSizeBytes() * m_cache_assoc) / (1<<10) << endl; 267 out << " cache_size_Mbytes: " 268 << double(cache_num_sets * RubySystem::getBlockSizeBytes() * m_cache_assoc) / (1<<20) << endl; 269} 270 271// PRIVATE METHODS 272 273// convert a Address to its location in the cache 274inline 275Index CacheMemory::addressToCacheSet(const Address& address) const 276{ 277 assert(address == line_address(address)); 278 return address.bitSelect(RubySystem::getBlockSizeBits(), RubySystem::getBlockSizeBits() + m_cache_num_set_bits-1); 279} 280 281// Given a cache index: returns the index of the tag in a set. 282// returns -1 if the tag is not found. 283inline 284int CacheMemory::findTagInSet(Index cacheSet, const Address& tag) const 285{ 286 assert(tag == line_address(tag)); 287 // search the set for the tags 288 for (int i=0; i < m_cache_assoc; i++) { 289 if ((m_cache[cacheSet][i] != NULL) && 290 (m_cache[cacheSet][i]->m_Address == tag) && 291 (m_cache[cacheSet][i]->m_Permission != AccessPermission_NotPresent)) { 292 return i; 293 } 294 } 295 return -1; // Not found 296} 297 298// Given a cache index: returns the index of the tag in a set. 299// returns -1 if the tag is not found. 300inline 301int CacheMemory::findTagInSetIgnorePermissions(Index cacheSet, const Address& tag) const 302{ 303 assert(tag == line_address(tag)); 304 // search the set for the tags 305 for (int i=0; i < m_cache_assoc; i++) { 306 if (m_cache[cacheSet][i] != NULL && m_cache[cacheSet][i]->m_Address == tag) 307 return i; 308 } 309 return -1; // Not found 310} 311 312// PUBLIC METHODS 313inline 314bool CacheMemory::tryCacheAccess(const Address& address, 315 CacheRequestType type, 316 DataBlock*& data_ptr) 317{ 318 assert(address == line_address(address)); 319 DEBUG_EXPR(CACHE_COMP, HighPrio, address); 320 Index cacheSet = addressToCacheSet(address); 321 int loc = findTagInSet(cacheSet, address); 322 if(loc != -1){ // Do we even have a tag match? 323 AbstractCacheEntry* entry = m_cache[cacheSet][loc]; 324 m_replacementPolicy_ptr->touch(cacheSet, loc, g_eventQueue_ptr->getTime()); 325 data_ptr = &(entry->getDataBlk()); 326 327 if(entry->m_Permission == AccessPermission_Read_Write) { 328 return true; 329 } 330 if ((entry->m_Permission == AccessPermission_Read_Only) && 331 (type == CacheRequestType_LD || type == CacheRequestType_IFETCH)) { 332 return true; 333 } 334 // The line must not be accessible 335 } 336 data_ptr = NULL; 337 return false; 338} 339 340inline 341bool CacheMemory::testCacheAccess(const Address& address, 342 CacheRequestType type, 343 DataBlock*& data_ptr) 344{ 345 assert(address == line_address(address)); 346 DEBUG_EXPR(CACHE_COMP, HighPrio, address); 347 Index cacheSet = addressToCacheSet(address); 348 int loc = findTagInSet(cacheSet, address); 349 if(loc != -1){ // Do we even have a tag match? 350 AbstractCacheEntry* entry = m_cache[cacheSet][loc]; 351 m_replacementPolicy_ptr->touch(cacheSet, loc, g_eventQueue_ptr->getTime()); 352 data_ptr = &(entry->getDataBlk()); 353 354 return (m_cache[cacheSet][loc]->m_Permission != AccessPermission_NotPresent); 355 } 356 data_ptr = NULL; 357 return false; 358} 359 360// tests to see if an address is present in the cache 361inline 362bool CacheMemory::isTagPresent(const Address& address) const 363{ 364 assert(address == line_address(address)); 365 Index cacheSet = addressToCacheSet(address); 366 int location = findTagInSet(cacheSet, address); 367 368 if (location == -1) { 369 // We didn't find the tag 370 DEBUG_EXPR(CACHE_COMP, LowPrio, address); 371 DEBUG_MSG(CACHE_COMP, LowPrio, "No tag match"); 372 return false; 373 } 374 DEBUG_EXPR(CACHE_COMP, LowPrio, address); 375 DEBUG_MSG(CACHE_COMP, LowPrio, "found"); 376 return true; 377} 378 379// Returns true if there is: 380// a) a tag match on this address or there is 381// b) an unused line in the same cache "way" 382inline 383bool CacheMemory::cacheAvail(const Address& address) const 384{ 385 assert(address == line_address(address)); 386 387 Index cacheSet = addressToCacheSet(address); 388 389 for (int i=0; i < m_cache_assoc; i++) { 390 AbstractCacheEntry* entry = m_cache[cacheSet][i]; 391 if (entry != NULL) { 392 if (entry->m_Address == address || // Already in the cache 393 entry->m_Permission == AccessPermission_NotPresent) { // We found an empty entry 394 return true; 395 } 396 } else { 397 return true; 398 } 399 } 400 return false; 401} 402 403inline 404void CacheMemory::allocate(const Address& address, AbstractCacheEntry* entry) 405{ 406 assert(address == line_address(address)); 407 assert(!isTagPresent(address)); 408 assert(cacheAvail(address)); 409 DEBUG_EXPR(CACHE_COMP, HighPrio, address); 410 411 // Find the first open slot 412 Index cacheSet = addressToCacheSet(address); 413 for (int i=0; i < m_cache_assoc; i++) { 414 if (m_cache[cacheSet][i] == NULL || 415 m_cache[cacheSet][i]->m_Permission == AccessPermission_NotPresent) { 416 m_cache[cacheSet][i] = entry; // Init entry 417 m_cache[cacheSet][i]->m_Address = address; 418 m_cache[cacheSet][i]->m_Permission = AccessPermission_Invalid; 419 m_locked[cacheSet][i] = -1; 420 421 m_replacementPolicy_ptr->touch(cacheSet, i, g_eventQueue_ptr->getTime()); 422 423 return; 424 } 425 } 426 ERROR_MSG("Allocate didn't find an available entry"); 427} 428 429inline 430void CacheMemory::deallocate(const Address& address) 431{ 432 assert(address == line_address(address)); 433 assert(isTagPresent(address)); 434 DEBUG_EXPR(CACHE_COMP, HighPrio, address); 435 Index cacheSet = addressToCacheSet(address); 436 int location = findTagInSet(cacheSet, address); 437 if (location != -1){ 438 delete m_cache[cacheSet][location]; 439 m_cache[cacheSet][location] = NULL; 440 m_locked[cacheSet][location] = -1; 441 } 442} 443 444// Returns with the physical address of the conflicting cache line 445inline 446Address CacheMemory::cacheProbe(const Address& address) const 447{ 448 assert(address == line_address(address)); 449 assert(!cacheAvail(address)); 450 451 Index cacheSet = addressToCacheSet(address); 452 return m_cache[cacheSet][m_replacementPolicy_ptr->getVictim(cacheSet)]->m_Address; 453} 454 455// looks an address up in the cache 456inline 457AbstractCacheEntry& CacheMemory::lookup(const Address& address) 458{ 459 assert(address == line_address(address)); 460 Index cacheSet = addressToCacheSet(address); 461 int loc = findTagInSet(cacheSet, address); 462 assert(loc != -1); 463 return *m_cache[cacheSet][loc]; 464} 465 466// looks an address up in the cache 467inline 468const AbstractCacheEntry& CacheMemory::lookup(const Address& address) const 469{ 470 assert(address == line_address(address)); 471 Index cacheSet = addressToCacheSet(address); 472 int loc = findTagInSet(cacheSet, address); 473 assert(loc != -1); 474 return *m_cache[cacheSet][loc]; 475} 476 477inline 478AccessPermission CacheMemory::getPermission(const Address& address) const 479{ 480 assert(address == line_address(address)); 481 return lookup(address).m_Permission; 482} 483 484inline 485void CacheMemory::changePermission(const Address& address, AccessPermission new_perm) 486{ 487 assert(address == line_address(address)); 488 lookup(address).m_Permission = new_perm; 489 Index cacheSet = addressToCacheSet(address); 490 int loc = findTagInSet(cacheSet, address); 491 m_locked[cacheSet][loc] = -1; 492 assert(getPermission(address) == new_perm); 493} 494 495// Sets the most recently used bit for a cache block 496inline 497void CacheMemory::setMRU(const Address& address) 498{ 499 Index cacheSet; 500 501 cacheSet = addressToCacheSet(address); 502 m_replacementPolicy_ptr->touch(cacheSet, 503 findTagInSet(cacheSet, address), 504 g_eventQueue_ptr->getTime()); 505} 506 507inline 508void CacheMemory::profileMiss(const CacheMsg & msg) 509{ 510 m_profiler_ptr->addStatSample(msg.getType(), msg.getAccessMode(), 511 msg.getSize(), msg.getPrefetch()); 512} 513 514inline 515void CacheMemory::recordCacheContents(CacheRecorder& tr) const 516{ 517 for (int i = 0; i < m_cache_num_sets; i++) { 518 for (int j = 0; j < m_cache_assoc; j++) { 519 AccessPermission perm = m_cache[i][j]->m_Permission; 520 CacheRequestType request_type = CacheRequestType_NULL; 521 if (perm == AccessPermission_Read_Only) { 522 if (m_is_instruction_only_cache) { 523 request_type = CacheRequestType_IFETCH; 524 } else { 525 request_type = CacheRequestType_LD; 526 } 527 } else if (perm == AccessPermission_Read_Write) { 528 request_type = CacheRequestType_ST; 529 } 530 531 if (request_type != CacheRequestType_NULL) { 532 // tr.addRecord(m_chip_ptr->getID(), m_cache[i][j].m_Address, 533 // Address(0), request_type, m_replacementPolicy_ptr->getLastAccess(i, j)); 534 } 535 } 536 } 537} 538 539inline 540void CacheMemory::print(ostream& out) const 541{ 542 out << "Cache dump: " << m_cache_name << endl; 543 for (int i = 0; i < m_cache_num_sets; i++) { 544 for (int j = 0; j < m_cache_assoc; j++) { 545 if (m_cache[i][j] != NULL) { 546 out << " Index: " << i 547 << " way: " << j 548 << " entry: " << *m_cache[i][j] << endl; 549 } else { 550 out << " Index: " << i 551 << " way: " << j 552 << " entry: NULL" << endl; 553 } 554 } 555 } 556} 557 558inline 559void CacheMemory::printData(ostream& out) const 560{ 561 out << "printData() not supported" << endl; 562} 563 564inline 565void CacheMemory::printStats(ostream& out) const 566{ 567 m_profiler_ptr->printStats(out); 568} 569 570inline 571void CacheMemory::getMemoryValue(const Address& addr, char* value, 572 unsigned int size_in_bytes ){ 573 AbstractCacheEntry& entry = lookup(line_address(addr)); 574 unsigned int startByte = addr.getAddress() - line_address(addr).getAddress(); 575 for(unsigned int i=0; i<size_in_bytes; ++i){ 576 value[i] = entry.getDataBlk().getByte(i + startByte); 577 } 578} 579 580inline 581void CacheMemory::setMemoryValue(const Address& addr, char* value, 582 unsigned int size_in_bytes ){ 583 AbstractCacheEntry& entry = lookup(line_address(addr)); 584 unsigned int startByte = addr.getAddress() - line_address(addr).getAddress(); 585 assert(size_in_bytes > 0); 586 for(unsigned int i=0; i<size_in_bytes; ++i){ 587 entry.getDataBlk().setByte(i + startByte, value[i]); 588 } 589 590 // entry = lookup(line_address(addr)); 591} 592 593inline 594void 595CacheMemory::setLocked(const Address& address, int context) 596{ 597 assert(address == line_address(address)); 598 Index cacheSet = addressToCacheSet(address); 599 int loc = findTagInSet(cacheSet, address); 600 assert(loc != -1); 601 m_locked[cacheSet][loc] = context; 602} 603 604inline 605void 606CacheMemory::clearLocked(const Address& address) 607{ 608 assert(address == line_address(address)); 609 Index cacheSet = addressToCacheSet(address); 610 int loc = findTagInSet(cacheSet, address); 611 assert(loc != -1); 612 m_locked[cacheSet][loc] = -1; 613} 614 615inline 616bool 617CacheMemory::isLocked(const Address& address, int context) 618{ 619 assert(address == line_address(address)); 620 Index cacheSet = addressToCacheSet(address); 621 int loc = findTagInSet(cacheSet, address); 622 assert(loc != -1); 623 return m_locked[cacheSet][loc] == context; 624} 625 626#endif //CACHEMEMORY_H 627 628