CacheMemory.hh revision 6145
15245Sgblack@eecs.umich.edu/* 25245Sgblack@eecs.umich.edu * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood 35245Sgblack@eecs.umich.edu * All rights reserved. 45245Sgblack@eecs.umich.edu * 57087Snate@binkert.org * Redistribution and use in source and binary forms, with or without 67087Snate@binkert.org * modification, are permitted provided that the following conditions are 77087Snate@binkert.org * met: redistributions of source code must retain the above copyright 87087Snate@binkert.org * notice, this list of conditions and the following disclaimer; 97087Snate@binkert.org * redistributions in binary form must reproduce the above copyright 107087Snate@binkert.org * notice, this list of conditions and the following disclaimer in the 117087Snate@binkert.org * documentation and/or other materials provided with the distribution; 127087Snate@binkert.org * neither the name of the copyright holders nor the names of its 135245Sgblack@eecs.umich.edu * contributors may be used to endorse or promote products derived from 147087Snate@binkert.org * this software without specific prior written permission. 157087Snate@binkert.org * 167087Snate@binkert.org * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 177087Snate@binkert.org * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 187087Snate@binkert.org * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 197087Snate@binkert.org * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 207087Snate@binkert.org * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 217087Snate@binkert.org * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 225245Sgblack@eecs.umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 237087Snate@binkert.org * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 245245Sgblack@eecs.umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 255245Sgblack@eecs.umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 265245Sgblack@eecs.umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 275245Sgblack@eecs.umich.edu */ 285245Sgblack@eecs.umich.edu 295245Sgblack@eecs.umich.edu/* 305245Sgblack@eecs.umich.edu * CacheMemory.h 315245Sgblack@eecs.umich.edu * 325245Sgblack@eecs.umich.edu * Description: 335245Sgblack@eecs.umich.edu * 345245Sgblack@eecs.umich.edu * $Id: CacheMemory.h,v 3.7 2004/06/18 20:15:15 beckmann Exp $ 355245Sgblack@eecs.umich.edu * 365245Sgblack@eecs.umich.edu */ 375245Sgblack@eecs.umich.edu 385245Sgblack@eecs.umich.edu#ifndef CACHEMEMORY_H 395245Sgblack@eecs.umich.edu#define CACHEMEMORY_H 405245Sgblack@eecs.umich.edu 415245Sgblack@eecs.umich.edu#include "AbstractChip.hh" 425245Sgblack@eecs.umich.edu#include "Global.hh" 435245Sgblack@eecs.umich.edu#include "AccessPermission.hh" 445245Sgblack@eecs.umich.edu#include "Address.hh" 455245Sgblack@eecs.umich.edu#include "CacheRecorder.hh" 465245Sgblack@eecs.umich.edu#include "CacheRequestType.hh" 478229Snate@binkert.org#include "Vector.hh" 486216Snate@binkert.org#include "DataBlock.hh" 495245Sgblack@eecs.umich.edu#include "MachineType.hh" 505245Sgblack@eecs.umich.edu#include "RubySlicc_ComponentMapping.hh" 515245Sgblack@eecs.umich.edu#include "PseudoLRUPolicy.hh" 527901Shestness@cs.utexas.edu#include "LRUPolicy.hh" 538832SAli.Saidi@ARM.com#include <vector> 545245Sgblack@eecs.umich.edu 555245Sgblack@eecs.umich.edutemplate<class ENTRY> 565245Sgblack@eecs.umich.educlass CacheMemory { 575245Sgblack@eecs.umich.edupublic: 585245Sgblack@eecs.umich.edu 595245Sgblack@eecs.umich.edu // Constructors 605245Sgblack@eecs.umich.edu CacheMemory(AbstractChip* chip_ptr, int numSetBits, int cacheAssoc, const MachineType machType, const string& description); 615245Sgblack@eecs.umich.edu 627912Shestness@cs.utexas.edu // Destructor 638922Swilliam.wang@arm.com ~CacheMemory(); 645245Sgblack@eecs.umich.edu 655245Sgblack@eecs.umich.edu // Public Methods 665245Sgblack@eecs.umich.edu void printConfig(ostream& out); 678922Swilliam.wang@arm.com 685245Sgblack@eecs.umich.edu // perform a cache access and see if we hit or not. Return true on a hit. 695245Sgblack@eecs.umich.edu bool tryCacheAccess(const Address& address, CacheRequestType type, DataBlock*& data_ptr); 705245Sgblack@eecs.umich.edu 718832SAli.Saidi@ARM.com // similar to above, but doesn't require full access check 725245Sgblack@eecs.umich.edu bool testCacheAccess(const Address& address, CacheRequestType type, DataBlock*& data_ptr); 735245Sgblack@eecs.umich.edu 748948Sandreas.hansson@arm.com // tests to see if an address is present in the cache 758948Sandreas.hansson@arm.com bool isTagPresent(const Address& address) const; 768948Sandreas.hansson@arm.com 778948Sandreas.hansson@arm.com // Returns true if there is: 788948Sandreas.hansson@arm.com // a) a tag match on this address or there is 798948Sandreas.hansson@arm.com // b) an unused line in the same cache "way" 808948Sandreas.hansson@arm.com bool cacheAvail(const Address& address) const; 815245Sgblack@eecs.umich.edu 828922Swilliam.wang@arm.com // find an unused entry and sets the tag appropriate for the address 835245Sgblack@eecs.umich.edu void allocate(const Address& address); 845245Sgblack@eecs.umich.edu 857912Shestness@cs.utexas.edu // Explicitly free up this address 867912Shestness@cs.utexas.edu void deallocate(const Address& address); 875245Sgblack@eecs.umich.edu 887912Shestness@cs.utexas.edu // Returns with the physical address of the conflicting cache line 897912Shestness@cs.utexas.edu Address cacheProbe(const Address& address) const; 907912Shestness@cs.utexas.edu 917912Shestness@cs.utexas.edu // looks an address up in the cache 927912Shestness@cs.utexas.edu ENTRY& lookup(const Address& address); 937912Shestness@cs.utexas.edu const ENTRY& lookup(const Address& address) const; 947912Shestness@cs.utexas.edu 957912Shestness@cs.utexas.edu // Get/Set permission of cache block 967912Shestness@cs.utexas.edu AccessPermission getPermission(const Address& address) const; 977912Shestness@cs.utexas.edu void changePermission(const Address& address, AccessPermission new_perm); 987912Shestness@cs.utexas.edu 997912Shestness@cs.utexas.edu // Hook for checkpointing the contents of the cache 1007912Shestness@cs.utexas.edu void recordCacheContents(CacheRecorder& tr) const; 1017912Shestness@cs.utexas.edu void setAsInstructionCache(bool is_icache) { m_is_instruction_cache = is_icache; } 1025245Sgblack@eecs.umich.edu 1037912Shestness@cs.utexas.edu // Set this address to most recently used 1048832SAli.Saidi@ARM.com void setMRU(const Address& address); 1057912Shestness@cs.utexas.edu 1067912Shestness@cs.utexas.edu void getMemoryValue(const Address& addr, char* value, 1077912Shestness@cs.utexas.edu unsigned int size_in_bytes ); 1087912Shestness@cs.utexas.edu void setMemoryValue(const Address& addr, char* value, 1097912Shestness@cs.utexas.edu unsigned int size_in_bytes ); 1107912Shestness@cs.utexas.edu 1117912Shestness@cs.utexas.edu // Print cache contents 1127912Shestness@cs.utexas.edu void print(ostream& out) const; 1137912Shestness@cs.utexas.edu void printData(ostream& out) const; 1147912Shestness@cs.utexas.edu 1157912Shestness@cs.utexas.eduprivate: 1167912Shestness@cs.utexas.edu // Private Methods 1177912Shestness@cs.utexas.edu 1187912Shestness@cs.utexas.edu // convert a Address to its location in the cache 1197912Shestness@cs.utexas.edu Index addressToCacheSet(const Address& address) const; 1207912Shestness@cs.utexas.edu 1217912Shestness@cs.utexas.edu // Given a cache tag: returns the index of the tag in a set. 1227912Shestness@cs.utexas.edu // returns -1 if the tag is not found. 1237912Shestness@cs.utexas.edu int findTagInSet(Index line, const Address& tag) const; 1247912Shestness@cs.utexas.edu int findTagInSetIgnorePermissions(Index cacheSet, const Address& tag) const; 1257912Shestness@cs.utexas.edu 1267912Shestness@cs.utexas.edu // Private copy constructor and assignment operator 1277912Shestness@cs.utexas.edu CacheMemory(const CacheMemory& obj); 1287912Shestness@cs.utexas.edu CacheMemory& operator=(const CacheMemory& obj); 1297912Shestness@cs.utexas.edu 1307912Shestness@cs.utexas.edu // Data Members (m_prefix) 1317912Shestness@cs.utexas.edu AbstractChip* m_chip_ptr; 1327912Shestness@cs.utexas.edu MachineType m_machType; 1337912Shestness@cs.utexas.edu string m_description; 1347912Shestness@cs.utexas.edu bool m_is_instruction_cache; 1358953Sgblack@eecs.umich.edu 1367912Shestness@cs.utexas.edu // The first index is the # of cache lines. 1377912Shestness@cs.utexas.edu // The second index is the the amount associativity. 1387912Shestness@cs.utexas.edu Vector<Vector<ENTRY> > m_cache; 1397912Shestness@cs.utexas.edu 1407912Shestness@cs.utexas.edu AbstractReplacementPolicy *m_replacementPolicy_ptr; 1417912Shestness@cs.utexas.edu 1427912Shestness@cs.utexas.edu int m_cache_num_sets; 1437912Shestness@cs.utexas.edu int m_cache_num_set_bits; 1447912Shestness@cs.utexas.edu int m_cache_assoc; 1457912Shestness@cs.utexas.edu}; 1467912Shestness@cs.utexas.edu 1477912Shestness@cs.utexas.edu// Output operator declaration 1487912Shestness@cs.utexas.edu//ostream& operator<<(ostream& out, const CacheMemory<ENTRY>& obj); 1497912Shestness@cs.utexas.edu 1507912Shestness@cs.utexas.edu// ******************* Definitions ******************* 1517912Shestness@cs.utexas.edu 1527912Shestness@cs.utexas.edu// Output operator definition 1537912Shestness@cs.utexas.edutemplate<class ENTRY> 1547912Shestness@cs.utexas.eduinline 1557912Shestness@cs.utexas.eduostream& operator<<(ostream& out, const CacheMemory<ENTRY>& obj) 1567912Shestness@cs.utexas.edu{ 1577912Shestness@cs.utexas.edu obj.print(out); 1587912Shestness@cs.utexas.edu out << flush; 1597912Shestness@cs.utexas.edu return out; 1607912Shestness@cs.utexas.edu} 1617912Shestness@cs.utexas.edu 1627912Shestness@cs.utexas.edu 1637912Shestness@cs.utexas.edu// **************************************************************** 1647912Shestness@cs.utexas.edu 1657912Shestness@cs.utexas.edutemplate<class ENTRY> 1667912Shestness@cs.utexas.eduinline 1677912Shestness@cs.utexas.eduCacheMemory<ENTRY>::CacheMemory(AbstractChip* chip_ptr, int numSetBits, 1687912Shestness@cs.utexas.edu int cacheAssoc, const MachineType machType, const string& description) 1697912Shestness@cs.utexas.edu 1707912Shestness@cs.utexas.edu{ 1717912Shestness@cs.utexas.edu //cout << "CacheMemory constructor numThreads = " << numThreads << endl; 1728953Sgblack@eecs.umich.edu m_chip_ptr = chip_ptr; 1738922Swilliam.wang@arm.com m_machType = machType; 1747912Shestness@cs.utexas.edu m_description = MachineType_to_string(m_machType)+"_"+description; 1757912Shestness@cs.utexas.edu m_cache_num_set_bits = numSetBits; 1765245Sgblack@eecs.umich.edu m_cache_num_sets = 1 << numSetBits; 1775245Sgblack@eecs.umich.edu m_cache_assoc = cacheAssoc; 1785245Sgblack@eecs.umich.edu m_is_instruction_cache = false; 1798832SAli.Saidi@ARM.com 1805245Sgblack@eecs.umich.edu m_cache.setSize(m_cache_num_sets); 1817912Shestness@cs.utexas.edu if(strcmp(g_REPLACEMENT_POLICY, "PSEDUO_LRU") == 0) 1827912Shestness@cs.utexas.edu m_replacementPolicy_ptr = new PseudoLRUPolicy(m_cache_num_sets, m_cache_assoc); 1837912Shestness@cs.utexas.edu else if(strcmp(g_REPLACEMENT_POLICY, "LRU") == 0) 1847912Shestness@cs.utexas.edu m_replacementPolicy_ptr = new LRUPolicy(m_cache_num_sets, m_cache_assoc); 1855245Sgblack@eecs.umich.edu else 1865245Sgblack@eecs.umich.edu assert(false); 1875245Sgblack@eecs.umich.edu for (int i = 0; i < m_cache_num_sets; i++) { 1885245Sgblack@eecs.umich.edu m_cache[i].setSize(m_cache_assoc); 1895245Sgblack@eecs.umich.edu for (int j = 0; j < m_cache_assoc; j++) { 1905245Sgblack@eecs.umich.edu m_cache[i][j].m_Address.setAddress(0); 1915245Sgblack@eecs.umich.edu m_cache[i][j].m_Permission = AccessPermission_NotPresent; 1925245Sgblack@eecs.umich.edu } 1935245Sgblack@eecs.umich.edu } 1945245Sgblack@eecs.umich.edu 1958832SAli.Saidi@ARM.com 1968832SAli.Saidi@ARM.com // cout << "Before setting trans address list size" << endl; 1978832SAli.Saidi@ARM.com //create a trans address for each SMT thread 1988832SAli.Saidi@ARM.com// m_trans_address_list.setSize(numThreads); 1998832SAli.Saidi@ARM.com// for(int i=0; i < numThreads; ++i){ 2008832SAli.Saidi@ARM.com// cout << "Setting list size for list " << i << endl; 2015245Sgblack@eecs.umich.edu// m_trans_address_list[i].setSize(30); 2027912Shestness@cs.utexas.edu// } 2038832SAli.Saidi@ARM.com //cout << "CacheMemory constructor finished" << endl; 2048832SAli.Saidi@ARM.com} 2055245Sgblack@eecs.umich.edu 2065245Sgblack@eecs.umich.edutemplate<class ENTRY> 2075245Sgblack@eecs.umich.eduinline 2085245Sgblack@eecs.umich.eduCacheMemory<ENTRY>::~CacheMemory() 2095245Sgblack@eecs.umich.edu{ 210 if(m_replacementPolicy_ptr != NULL) 211 delete m_replacementPolicy_ptr; 212} 213 214template<class ENTRY> 215inline 216void CacheMemory<ENTRY>::printConfig(ostream& out) 217{ 218 out << "Cache config: " << m_description << endl; 219 out << " cache_associativity: " << m_cache_assoc << endl; 220 out << " num_cache_sets_bits: " << m_cache_num_set_bits << endl; 221 const int cache_num_sets = 1 << m_cache_num_set_bits; 222 out << " num_cache_sets: " << cache_num_sets << endl; 223 out << " cache_set_size_bytes: " << cache_num_sets * RubyConfig::dataBlockBytes() << endl; 224 out << " cache_set_size_Kbytes: " 225 << double(cache_num_sets * RubyConfig::dataBlockBytes()) / (1<<10) << endl; 226 out << " cache_set_size_Mbytes: " 227 << double(cache_num_sets * RubyConfig::dataBlockBytes()) / (1<<20) << endl; 228 out << " cache_size_bytes: " 229 << cache_num_sets * RubyConfig::dataBlockBytes() * m_cache_assoc << endl; 230 out << " cache_size_Kbytes: " 231 << double(cache_num_sets * RubyConfig::dataBlockBytes() * m_cache_assoc) / (1<<10) << endl; 232 out << " cache_size_Mbytes: " 233 << double(cache_num_sets * RubyConfig::dataBlockBytes() * m_cache_assoc) / (1<<20) << endl; 234} 235 236// PRIVATE METHODS 237 238// convert a Address to its location in the cache 239template<class ENTRY> 240inline 241Index CacheMemory<ENTRY>::addressToCacheSet(const Address& address) const 242{ 243 assert(address == line_address(address)); 244 Index temp = -1; 245 switch (m_machType) { 246 case MACHINETYPE_L1CACHE_ENUM: 247 temp = map_address_to_L1CacheSet(address, m_cache_num_set_bits); 248 break; 249 case MACHINETYPE_L2CACHE_ENUM: 250 temp = map_address_to_L2CacheSet(address, m_cache_num_set_bits); 251 break; 252 default: 253 ERROR_MSG("Don't recognize m_machType"); 254 } 255 assert(temp < m_cache_num_sets); 256 assert(temp >= 0); 257 return temp; 258} 259 260// Given a cache index: returns the index of the tag in a set. 261// returns -1 if the tag is not found. 262template<class ENTRY> 263inline 264int CacheMemory<ENTRY>::findTagInSet(Index cacheSet, const Address& tag) const 265{ 266 assert(tag == line_address(tag)); 267 // search the set for the tags 268 for (int i=0; i < m_cache_assoc; i++) { 269 if ((m_cache[cacheSet][i].m_Address == tag) && 270 (m_cache[cacheSet][i].m_Permission != AccessPermission_NotPresent)) { 271 return i; 272 } 273 } 274 return -1; // Not found 275} 276 277// Given a cache index: returns the index of the tag in a set. 278// returns -1 if the tag is not found. 279template<class ENTRY> 280inline 281int CacheMemory<ENTRY>::findTagInSetIgnorePermissions(Index cacheSet, const Address& tag) const 282{ 283 assert(tag == line_address(tag)); 284 // search the set for the tags 285 for (int i=0; i < m_cache_assoc; i++) { 286 if (m_cache[cacheSet][i].m_Address == tag) 287 return i; 288 } 289 return -1; // Not found 290} 291 292// PUBLIC METHODS 293template<class ENTRY> 294inline 295bool CacheMemory<ENTRY>::tryCacheAccess(const Address& address, 296 CacheRequestType type, 297 DataBlock*& data_ptr) 298{ 299 assert(address == line_address(address)); 300 DEBUG_EXPR(CACHE_COMP, HighPrio, address); 301 Index cacheSet = addressToCacheSet(address); 302 int loc = findTagInSet(cacheSet, address); 303 if(loc != -1){ // Do we even have a tag match? 304 ENTRY& entry = m_cache[cacheSet][loc]; 305 m_replacementPolicy_ptr->touch(cacheSet, loc, g_eventQueue_ptr->getTime()); 306 data_ptr = &(entry.getDataBlk()); 307 308 if(entry.m_Permission == AccessPermission_Read_Write) { 309 return true; 310 } 311 if ((entry.m_Permission == AccessPermission_Read_Only) && 312 (type == CacheRequestType_LD || type == CacheRequestType_IFETCH)) { 313 return true; 314 } 315 // The line must not be accessible 316 } 317 data_ptr = NULL; 318 return false; 319} 320 321template<class ENTRY> 322inline 323bool CacheMemory<ENTRY>::testCacheAccess(const Address& address, 324 CacheRequestType type, 325 DataBlock*& data_ptr) 326{ 327 assert(address == line_address(address)); 328 DEBUG_EXPR(CACHE_COMP, HighPrio, address); 329 Index cacheSet = addressToCacheSet(address); 330 int loc = findTagInSet(cacheSet, address); 331 if(loc != -1){ // Do we even have a tag match? 332 ENTRY& entry = m_cache[cacheSet][loc]; 333 m_replacementPolicy_ptr->touch(cacheSet, loc, g_eventQueue_ptr->getTime()); 334 data_ptr = &(entry.getDataBlk()); 335 336 return (m_cache[cacheSet][loc].m_Permission != AccessPermission_NotPresent); 337 } 338 data_ptr = NULL; 339 return false; 340} 341 342// tests to see if an address is present in the cache 343template<class ENTRY> 344inline 345bool CacheMemory<ENTRY>::isTagPresent(const Address& address) const 346{ 347 assert(address == line_address(address)); 348 Index cacheSet = addressToCacheSet(address); 349 int location = findTagInSet(cacheSet, address); 350 351 if (location == -1) { 352 // We didn't find the tag 353 DEBUG_EXPR(CACHE_COMP, LowPrio, address); 354 DEBUG_MSG(CACHE_COMP, LowPrio, "No tag match"); 355 return false; 356 } 357 DEBUG_EXPR(CACHE_COMP, LowPrio, address); 358 DEBUG_MSG(CACHE_COMP, LowPrio, "found"); 359 return true; 360} 361 362// Returns true if there is: 363// a) a tag match on this address or there is 364// b) an unused line in the same cache "way" 365template<class ENTRY> 366inline 367bool CacheMemory<ENTRY>::cacheAvail(const Address& address) const 368{ 369 assert(address == line_address(address)); 370 371 Index cacheSet = addressToCacheSet(address); 372 373 for (int i=0; i < m_cache_assoc; i++) { 374 if (m_cache[cacheSet][i].m_Address == address) { 375 // Already in the cache 376 return true; 377 } 378 379 if (m_cache[cacheSet][i].m_Permission == AccessPermission_NotPresent) { 380 // We found an empty entry 381 return true; 382 } 383 } 384 return false; 385} 386 387template<class ENTRY> 388inline 389void CacheMemory<ENTRY>::allocate(const Address& address) 390{ 391 assert(address == line_address(address)); 392 assert(!isTagPresent(address)); 393 assert(cacheAvail(address)); 394 DEBUG_EXPR(CACHE_COMP, HighPrio, address); 395 396 // Find the first open slot 397 Index cacheSet = addressToCacheSet(address); 398 for (int i=0; i < m_cache_assoc; i++) { 399 if (m_cache[cacheSet][i].m_Permission == AccessPermission_NotPresent) { 400 m_cache[cacheSet][i] = ENTRY(); // Init entry 401 m_cache[cacheSet][i].m_Address = address; 402 m_cache[cacheSet][i].m_Permission = AccessPermission_Invalid; 403 404 m_replacementPolicy_ptr->touch(cacheSet, i, g_eventQueue_ptr->getTime()); 405 406 return; 407 } 408 } 409 ERROR_MSG("Allocate didn't find an available entry"); 410} 411 412template<class ENTRY> 413inline 414void CacheMemory<ENTRY>::deallocate(const Address& address) 415{ 416 assert(address == line_address(address)); 417 assert(isTagPresent(address)); 418 DEBUG_EXPR(CACHE_COMP, HighPrio, address); 419 lookup(address).m_Permission = AccessPermission_NotPresent; 420} 421 422// Returns with the physical address of the conflicting cache line 423template<class ENTRY> 424inline 425Address CacheMemory<ENTRY>::cacheProbe(const Address& address) const 426{ 427 assert(address == line_address(address)); 428 assert(!cacheAvail(address)); 429 430 Index cacheSet = addressToCacheSet(address); 431 return m_cache[cacheSet][m_replacementPolicy_ptr->getVictim(cacheSet)].m_Address; 432} 433 434// looks an address up in the cache 435template<class ENTRY> 436inline 437ENTRY& CacheMemory<ENTRY>::lookup(const Address& address) 438{ 439 assert(address == line_address(address)); 440 Index cacheSet = addressToCacheSet(address); 441 int loc = findTagInSet(cacheSet, address); 442 assert(loc != -1); 443 return m_cache[cacheSet][loc]; 444} 445 446// looks an address up in the cache 447template<class ENTRY> 448inline 449const ENTRY& CacheMemory<ENTRY>::lookup(const Address& address) const 450{ 451 assert(address == line_address(address)); 452 Index cacheSet = addressToCacheSet(address); 453 int loc = findTagInSet(cacheSet, address); 454 assert(loc != -1); 455 return m_cache[cacheSet][loc]; 456} 457 458template<class ENTRY> 459inline 460AccessPermission CacheMemory<ENTRY>::getPermission(const Address& address) const 461{ 462 assert(address == line_address(address)); 463 return lookup(address).m_Permission; 464} 465 466template<class ENTRY> 467inline 468void CacheMemory<ENTRY>::changePermission(const Address& address, AccessPermission new_perm) 469{ 470 assert(address == line_address(address)); 471 lookup(address).m_Permission = new_perm; 472 assert(getPermission(address) == new_perm); 473} 474 475// Sets the most recently used bit for a cache block 476template<class ENTRY> 477inline 478void CacheMemory<ENTRY>::setMRU(const Address& address) 479{ 480 Index cacheSet; 481 482 cacheSet = addressToCacheSet(address); 483 m_replacementPolicy_ptr->touch(cacheSet, 484 findTagInSet(cacheSet, address), 485 g_eventQueue_ptr->getTime()); 486} 487 488template<class ENTRY> 489inline 490void CacheMemory<ENTRY>::recordCacheContents(CacheRecorder& tr) const 491{ 492 for (int i = 0; i < m_cache_num_sets; i++) { 493 for (int j = 0; j < m_cache_assoc; j++) { 494 AccessPermission perm = m_cache[i][j].m_Permission; 495 CacheRequestType request_type = CacheRequestType_NULL; 496 if (perm == AccessPermission_Read_Only) { 497 if (m_is_instruction_cache) { 498 request_type = CacheRequestType_IFETCH; 499 } else { 500 request_type = CacheRequestType_LD; 501 } 502 } else if (perm == AccessPermission_Read_Write) { 503 request_type = CacheRequestType_ST; 504 } 505 506 if (request_type != CacheRequestType_NULL) { 507 tr.addRecord(m_chip_ptr->getID(), m_cache[i][j].m_Address, 508 Address(0), request_type, m_replacementPolicy_ptr->getLastAccess(i, j)); 509 } 510 } 511 } 512} 513 514template<class ENTRY> 515inline 516void CacheMemory<ENTRY>::print(ostream& out) const 517{ 518 out << "Cache dump: " << m_description << endl; 519 for (int i = 0; i < m_cache_num_sets; i++) { 520 for (int j = 0; j < m_cache_assoc; j++) { 521 out << " Index: " << i 522 << " way: " << j 523 << " entry: " << m_cache[i][j] << endl; 524 } 525 } 526} 527 528template<class ENTRY> 529inline 530void CacheMemory<ENTRY>::printData(ostream& out) const 531{ 532 out << "printData() not supported" << endl; 533} 534 535template<class ENTRY> 536void CacheMemory<ENTRY>::getMemoryValue(const Address& addr, char* value, 537 unsigned int size_in_bytes ){ 538 ENTRY entry = lookup(line_address(addr)); 539 unsigned int startByte = addr.getAddress() - line_address(addr).getAddress(); 540 for(unsigned int i=0; i<size_in_bytes; ++i){ 541 value[i] = entry.m_DataBlk.getByte(i + startByte); 542 } 543} 544 545template<class ENTRY> 546void CacheMemory<ENTRY>::setMemoryValue(const Address& addr, char* value, 547 unsigned int size_in_bytes ){ 548 ENTRY& entry = lookup(line_address(addr)); 549 unsigned int startByte = addr.getAddress() - line_address(addr).getAddress(); 550 assert(size_in_bytes > 0); 551 for(unsigned int i=0; i<size_in_bytes; ++i){ 552 entry.m_DataBlk.setByte(i + startByte, value[i]); 553 } 554 555 entry = lookup(line_address(addr)); 556} 557 558#endif //CACHEMEMORY_H 559 560