CacheMemory.hh revision 6285
16145Snate@binkert.org/* 26145Snate@binkert.org * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood 36145Snate@binkert.org * All rights reserved. 46145Snate@binkert.org * 56145Snate@binkert.org * Redistribution and use in source and binary forms, with or without 66145Snate@binkert.org * modification, are permitted provided that the following conditions are 76145Snate@binkert.org * met: redistributions of source code must retain the above copyright 86145Snate@binkert.org * notice, this list of conditions and the following disclaimer; 96145Snate@binkert.org * redistributions in binary form must reproduce the above copyright 106145Snate@binkert.org * notice, this list of conditions and the following disclaimer in the 116145Snate@binkert.org * documentation and/or other materials provided with the distribution; 126145Snate@binkert.org * neither the name of the copyright holders nor the names of its 136145Snate@binkert.org * contributors may be used to endorse or promote products derived from 146145Snate@binkert.org * this software without specific prior written permission. 156145Snate@binkert.org * 166145Snate@binkert.org * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 176145Snate@binkert.org * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 186145Snate@binkert.org * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 196145Snate@binkert.org * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 206145Snate@binkert.org * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 216145Snate@binkert.org * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 226145Snate@binkert.org * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 236145Snate@binkert.org * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 246145Snate@binkert.org * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 256145Snate@binkert.org * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 266145Snate@binkert.org * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 276145Snate@binkert.org */ 286145Snate@binkert.org 296145Snate@binkert.org/* 307039Snate@binkert.org * CacheMemory.hh 317039Snate@binkert.org * 327039Snate@binkert.org * Description: 336145Snate@binkert.org * 346145Snate@binkert.org * $Id: CacheMemory.hh,v 3.7 2004/06/18 20:15:15 beckmann Exp $ 357039Snate@binkert.org * 367039Snate@binkert.org */ 376145Snate@binkert.org 387002Snate@binkert.org#ifndef CACHEMEMORY_H 397021Stushar@csail.mit.edu#define CACHEMEMORY_H 407002Snate@binkert.org 419465Snilay@cs.wisc.edu#include "mem/ruby/common/Global.hh" 426145Snate@binkert.org#include "mem/protocol/AccessPermission.hh" 437039Snate@binkert.org#include "mem/ruby/common/Address.hh" 447039Snate@binkert.org#include "mem/ruby/recorder/CacheRecorder.hh" 457039Snate@binkert.org#include "mem/protocol/CacheRequestType.hh" 469465Snilay@cs.wisc.edu#include "mem/gems_common/Vector.hh" 4710123Snilay@cs.wisc.edu#include "mem/ruby/common/DataBlock.hh" 487039Snate@binkert.org#include "mem/protocol/MachineType.hh" 497039Snate@binkert.org#include "mem/ruby/slicc_interface/RubySlicc_ComponentMapping.hh" 506145Snate@binkert.org#include "mem/ruby/system/PseudoLRUPolicy.hh" 517039Snate@binkert.org#include "mem/ruby/system/LRUPolicy.hh" 527039Snate@binkert.org#include "mem/ruby/slicc_interface/AbstractCacheEntry.hh" 537039Snate@binkert.org#include "mem/ruby/system/System.hh" 546145Snate@binkert.org#include "mem/ruby/slicc_interface/AbstractController.hh" 557039Snate@binkert.org#include <vector> 567039Snate@binkert.org 577973Snilay@cs.wisc.educlass CacheMemory { 586145Snate@binkert.orgpublic: 597039Snate@binkert.org 609171Snilay@cs.wisc.edu // Constructors 617039Snate@binkert.org CacheMemory(const string & name); 627039Snate@binkert.org void init(const vector<string> & argv); 637039Snate@binkert.org 647039Snate@binkert.org // Destructor 657039Snate@binkert.org ~CacheMemory(); 669171Snilay@cs.wisc.edu 677039Snate@binkert.org // factory 687039Snate@binkert.org // static CacheMemory* createCache(int level, int num, char split_type, AbstractCacheEntry* (*entry_factory)()); 697039Snate@binkert.org // static CacheMemory* getCache(int cache_id); 707039Snate@binkert.org 719600Snilay@cs.wisc.edu // Public Methods 729600Snilay@cs.wisc.edu void printConfig(ostream& out); 739600Snilay@cs.wisc.edu 749499Snilay@cs.wisc.edu // perform a cache access and see if we hit or not. Return true on a hit. 759171Snilay@cs.wisc.edu bool tryCacheAccess(const Address& address, CacheRequestType type, DataBlock*& data_ptr); 767039Snate@binkert.org 779171Snilay@cs.wisc.edu // similar to above, but doesn't require full access check 789465Snilay@cs.wisc.edu bool testCacheAccess(const Address& address, CacheRequestType type, DataBlock*& data_ptr); 799171Snilay@cs.wisc.edu 809171Snilay@cs.wisc.edu // tests to see if an address is present in the cache 819171Snilay@cs.wisc.edu bool isTagPresent(const Address& address) const; 829171Snilay@cs.wisc.edu 839171Snilay@cs.wisc.edu // Returns true if there is: 849171Snilay@cs.wisc.edu // a) a tag match on this address or there is 859171Snilay@cs.wisc.edu // b) an unused line in the same cache "way" 869171Snilay@cs.wisc.edu bool cacheAvail(const Address& address) const; 879171Snilay@cs.wisc.edu 8810123Snilay@cs.wisc.edu // find an unused entry and sets the tag appropriate for the address 899171Snilay@cs.wisc.edu void allocate(const Address& address, AbstractCacheEntry* new_entry); 909171Snilay@cs.wisc.edu 919171Snilay@cs.wisc.edu // Explicitly free up this address 929171Snilay@cs.wisc.edu void deallocate(const Address& address); 936145Snate@binkert.org 946145Snate@binkert.org // Returns with the physical address of the conflicting cache line 957039Snate@binkert.org Address cacheProbe(const Address& address) const; 967039Snate@binkert.org 976145Snate@binkert.org // looks an address up in the cache 987039Snate@binkert.org AbstractCacheEntry& lookup(const Address& address); 997039Snate@binkert.org const AbstractCacheEntry& lookup(const Address& address) const; 1007039Snate@binkert.org 1016145Snate@binkert.org // Get/Set permission of cache block 1026145Snate@binkert.org AccessPermission getPermission(const Address& address) const; 1037039Snate@binkert.org void changePermission(const Address& address, AccessPermission new_perm); 104 105 int getLatency() const { return m_latency; } 106 107 // Hook for checkpointing the contents of the cache 108 void recordCacheContents(CacheRecorder& tr) const; 109 void setAsInstructionCache(bool is_icache) { m_is_instruction_only_cache = is_icache; } 110 111 // Set this address to most recently used 112 void setMRU(const Address& address); 113 114 void getMemoryValue(const Address& addr, char* value, 115 unsigned int size_in_bytes ); 116 void setMemoryValue(const Address& addr, char* value, 117 unsigned int size_in_bytes ); 118 119 // Print cache contents 120 void print(ostream& out) const; 121 void printData(ostream& out) const; 122 123private: 124 // Private Methods 125 126 // convert a Address to its location in the cache 127 Index addressToCacheSet(const Address& address) const; 128 129 // Given a cache tag: returns the index of the tag in a set. 130 // returns -1 if the tag is not found. 131 int findTagInSet(Index line, const Address& tag) const; 132 int findTagInSetIgnorePermissions(Index cacheSet, const Address& tag) const; 133 134 // Private copy constructor and assignment operator 135 CacheMemory(const CacheMemory& obj); 136 CacheMemory& operator=(const CacheMemory& obj); 137 138private: 139 const string m_cache_name; 140 AbstractController* m_controller; 141 int m_latency; 142 143 // Data Members (m_prefix) 144 bool m_is_instruction_only_cache; 145 bool m_is_data_only_cache; 146 147 // The first index is the # of cache lines. 148 // The second index is the the amount associativity. 149 Vector<Vector<AbstractCacheEntry*> > m_cache; 150 151 AbstractReplacementPolicy *m_replacementPolicy_ptr; 152 153 int m_cache_num_sets; 154 int m_cache_num_set_bits; 155 int m_cache_assoc; 156 157 static Vector< CacheMemory* > m_all_caches; 158}; 159/* 160inline 161CacheMemory* CacheMemory::getCache(int cache_id) 162{ 163 assert(cache_id < RubyConfig::getNumberOfCaches()); 164 if (m_all_caches[cache_id] == NULL) { 165 cerr << "ERROR: Tried to obtain CacheMemory that hasn't been created yet." << endl; 166 assert(0); 167 } 168 return m_all_caches[cache_id]; 169} 170 171inline 172CacheMemory* CacheMemory::createCache(int level, int num, char split_type_c, AbstractCacheEntry* (*entry_factory)()) 173{ 174 string split_type; 175 switch(split_type_c) { 176 case 'i': 177 split_type = "instruction"; break; 178 case 'd': 179 split_type = "data"; break; 180 default: 181 split_type = "unified"; break; 182 } 183 int cache_id = RubyConfig::getCacheIDFromParams(level, num, split_type); 184 assert(cache_id < RubyConfig::getNumberOfCaches()); 185 if (m_all_caches.size() == 0) { 186 m_all_caches.setSize(RubyConfig::getNumberOfCaches()); 187 for (int i=0; i<m_all_caches.size(); i++) 188 m_all_caches[i] = NULL; 189 } 190 191 string type = RubyConfig::getCacheType(cache_id); 192 if ( type == "SetAssociativeCache" ) { 193 m_all_caches[cache_id] = new CacheMemory(cache_id, entry_factory); 194 } 195 return m_all_caches[cache_id]; 196} 197*/ 198// Output operator declaration 199//ostream& operator<<(ostream& out, const CacheMemory<ENTRY>& obj); 200 201// ******************* Definitions ******************* 202 203// Output operator definition 204inline 205ostream& operator<<(ostream& out, const CacheMemory& obj) 206{ 207 obj.print(out); 208 out << flush; 209 return out; 210} 211 212 213// **************************************************************** 214 215inline 216CacheMemory::CacheMemory(const string & name) 217 : m_cache_name(name) 218{ 219} 220 221inline 222void CacheMemory::init(const vector<string> & argv) 223{ 224 int cache_size = 0; 225 string policy; 226 227 m_controller = NULL; 228 for (uint32 i=0; i<argv.size(); i+=2) { 229 if (argv[i] == "size_kb") { 230 cache_size = atoi(argv[i+1].c_str()); 231 } else if (argv[i] == "latency") { 232 m_latency = atoi(argv[i+1].c_str()); 233 } else if (argv[i] == "assoc") { 234 m_cache_assoc = atoi(argv[i+1].c_str()); 235 } else if (argv[i] == "replacement_policy") { 236 policy = argv[i+1]; 237 } else if (argv[i] == "controller") { 238 m_controller = RubySystem::getController(argv[i+1]); 239 } else { 240 cerr << "WARNING: CacheMemory: Unknown configuration parameter: " << argv[i] << endl; 241 } 242 } 243 244 m_cache_num_sets = cache_size / m_cache_assoc; 245 m_cache_num_set_bits = log_int(m_cache_num_sets); 246 247 if(policy == "PSEUDO_LRU") 248 m_replacementPolicy_ptr = new PseudoLRUPolicy(m_cache_num_sets, m_cache_assoc); 249 else if (policy == "LRU") 250 m_replacementPolicy_ptr = new LRUPolicy(m_cache_num_sets, m_cache_assoc); 251 else 252 assert(false); 253 254 m_cache.setSize(m_cache_num_sets); 255 for (int i = 0; i < m_cache_num_sets; i++) { 256 m_cache[i].setSize(m_cache_assoc); 257 for (int j = 0; j < m_cache_assoc; j++) { 258 m_cache[i][j] = NULL; 259 } 260 } 261} 262/* 263inline 264CacheMemory::CacheMemory(int cache_id, AbstractCacheEntry* (*entry_factory)()) 265{ 266 string split_type; 267 268 m_cache_id = cache_id; 269 m_entry_factory = entry_factory; 270 271 m_cache_num_set_bits = RubyConfig::getNumberOfCacheSetBits(cache_id); 272 m_cache_num_sets = RubyConfig::getNumberOfCacheSets(cache_id); 273 m_cache_assoc = RubyConfig::getCacheAssoc(cache_id); 274 split_type = RubyConfig::getCacheSplitType(cache_id); 275 m_is_instruction_only_cache = m_is_data_only_cache = false; 276 if (split_type == "instruction") 277 m_is_instruction_only_cache = true; 278 else if (split_type == "data") 279 m_is_data_only_cache = true; 280 else 281 assert(split_type == "unified"); 282 283 if(RubyConfig::getCacheReplacementPolicy(cache_id) == "PSEUDO_LRU") 284 m_replacementPolicy_ptr = new PseudoLRUPolicy(m_cache_num_sets, m_cache_assoc); 285 else if(RubyConfig::getCacheReplacementPolicy(cache_id) == "LRU") 286 m_replacementPolicy_ptr = new LRUPolicy(m_cache_num_sets, m_cache_assoc); 287 else 288 assert(false); 289 290 m_cache.setSize(m_cache_num_sets); 291 for (int i = 0; i < m_cache_num_sets; i++) { 292 m_cache[i].setSize(m_cache_assoc); 293 for (int j = 0; j < m_cache_assoc; j++) { 294 m_cache[i][j] = m_entry_factory(); 295 } 296 } 297} 298*/ 299inline 300CacheMemory::~CacheMemory() 301{ 302 if(m_replacementPolicy_ptr != NULL) 303 delete m_replacementPolicy_ptr; 304} 305 306inline 307void CacheMemory::printConfig(ostream& out) 308{ 309 out << "Cache config: " << m_cache_name << endl; 310 if (m_controller != NULL) 311 out << " controller: " << m_controller->getName() << endl; 312 out << " cache_associativity: " << m_cache_assoc << endl; 313 out << " num_cache_sets_bits: " << m_cache_num_set_bits << endl; 314 const int cache_num_sets = 1 << m_cache_num_set_bits; 315 out << " num_cache_sets: " << cache_num_sets << endl; 316 out << " cache_set_size_bytes: " << cache_num_sets * RubySystem::getBlockSizeBytes() << endl; 317 out << " cache_set_size_Kbytes: " 318 << double(cache_num_sets * RubySystem::getBlockSizeBytes()) / (1<<10) << endl; 319 out << " cache_set_size_Mbytes: " 320 << double(cache_num_sets * RubySystem::getBlockSizeBytes()) / (1<<20) << endl; 321 out << " cache_size_bytes: " 322 << cache_num_sets * RubySystem::getBlockSizeBytes() * m_cache_assoc << endl; 323 out << " cache_size_Kbytes: " 324 << double(cache_num_sets * RubySystem::getBlockSizeBytes() * m_cache_assoc) / (1<<10) << endl; 325 out << " cache_size_Mbytes: " 326 << double(cache_num_sets * RubySystem::getBlockSizeBytes() * m_cache_assoc) / (1<<20) << endl; 327} 328 329// PRIVATE METHODS 330 331// convert a Address to its location in the cache 332inline 333Index CacheMemory::addressToCacheSet(const Address& address) const 334{ 335 assert(address == line_address(address)); 336 Index temp = -1; 337 return address.bitSelect(RubySystem::getBlockSizeBits(), RubySystem::getBlockSizeBits() + m_cache_num_set_bits-1); 338} 339 340// Given a cache index: returns the index of the tag in a set. 341// returns -1 if the tag is not found. 342inline 343int CacheMemory::findTagInSet(Index cacheSet, const Address& tag) const 344{ 345 assert(tag == line_address(tag)); 346 // search the set for the tags 347 for (int i=0; i < m_cache_assoc; i++) { 348 if ((m_cache[cacheSet][i] != NULL) && 349 (m_cache[cacheSet][i]->m_Address == tag) && 350 (m_cache[cacheSet][i]->m_Permission != AccessPermission_NotPresent)) { 351 return i; 352 } 353 } 354 return -1; // Not found 355} 356 357// Given a cache index: returns the index of the tag in a set. 358// returns -1 if the tag is not found. 359inline 360int CacheMemory::findTagInSetIgnorePermissions(Index cacheSet, const Address& tag) const 361{ 362 assert(tag == line_address(tag)); 363 // search the set for the tags 364 for (int i=0; i < m_cache_assoc; i++) { 365 if (m_cache[cacheSet][i] != NULL && m_cache[cacheSet][i]->m_Address == tag) 366 return i; 367 } 368 return -1; // Not found 369} 370 371// PUBLIC METHODS 372inline 373bool CacheMemory::tryCacheAccess(const Address& address, 374 CacheRequestType type, 375 DataBlock*& data_ptr) 376{ 377 assert(address == line_address(address)); 378 DEBUG_EXPR(CACHE_COMP, HighPrio, address); 379 Index cacheSet = addressToCacheSet(address); 380 int loc = findTagInSet(cacheSet, address); 381 if(loc != -1){ // Do we even have a tag match? 382 AbstractCacheEntry* entry = m_cache[cacheSet][loc]; 383 m_replacementPolicy_ptr->touch(cacheSet, loc, g_eventQueue_ptr->getTime()); 384 data_ptr = &(entry->getDataBlk()); 385 386 if(entry->m_Permission == AccessPermission_Read_Write) { 387 return true; 388 } 389 if ((entry->m_Permission == AccessPermission_Read_Only) && 390 (type == CacheRequestType_LD || type == CacheRequestType_IFETCH)) { 391 return true; 392 } 393 // The line must not be accessible 394 } 395 data_ptr = NULL; 396 return false; 397} 398 399inline 400bool CacheMemory::testCacheAccess(const Address& address, 401 CacheRequestType type, 402 DataBlock*& data_ptr) 403{ 404 assert(address == line_address(address)); 405 DEBUG_EXPR(CACHE_COMP, HighPrio, address); 406 Index cacheSet = addressToCacheSet(address); 407 int loc = findTagInSet(cacheSet, address); 408 if(loc != -1){ // Do we even have a tag match? 409 AbstractCacheEntry* entry = m_cache[cacheSet][loc]; 410 m_replacementPolicy_ptr->touch(cacheSet, loc, g_eventQueue_ptr->getTime()); 411 data_ptr = &(entry->getDataBlk()); 412 413 return (m_cache[cacheSet][loc]->m_Permission != AccessPermission_NotPresent); 414 } 415 data_ptr = NULL; 416 return false; 417} 418 419// tests to see if an address is present in the cache 420inline 421bool CacheMemory::isTagPresent(const Address& address) const 422{ 423 assert(address == line_address(address)); 424 Index cacheSet = addressToCacheSet(address); 425 int location = findTagInSet(cacheSet, address); 426 427 if (location == -1) { 428 // We didn't find the tag 429 DEBUG_EXPR(CACHE_COMP, LowPrio, address); 430 DEBUG_MSG(CACHE_COMP, LowPrio, "No tag match"); 431 return false; 432 } 433 DEBUG_EXPR(CACHE_COMP, LowPrio, address); 434 DEBUG_MSG(CACHE_COMP, LowPrio, "found"); 435 return true; 436} 437 438// Returns true if there is: 439// a) a tag match on this address or there is 440// b) an unused line in the same cache "way" 441inline 442bool CacheMemory::cacheAvail(const Address& address) const 443{ 444 assert(address == line_address(address)); 445 446 Index cacheSet = addressToCacheSet(address); 447 448 for (int i=0; i < m_cache_assoc; i++) { 449 AbstractCacheEntry* entry = m_cache[cacheSet][i]; 450 if (entry != NULL) { 451 if (entry->m_Address == address || // Already in the cache 452 entry->m_Permission == AccessPermission_NotPresent) { // We found an empty entry 453 return true; 454 } 455 } else { 456 return true; 457 } 458 } 459 return false; 460} 461 462inline 463void CacheMemory::allocate(const Address& address, AbstractCacheEntry* entry) 464{ 465 assert(address == line_address(address)); 466 assert(!isTagPresent(address)); 467 assert(cacheAvail(address)); 468 DEBUG_EXPR(CACHE_COMP, HighPrio, address); 469 470 // Find the first open slot 471 Index cacheSet = addressToCacheSet(address); 472 for (int i=0; i < m_cache_assoc; i++) { 473 if (m_cache[cacheSet][i] == NULL || 474 m_cache[cacheSet][i]->m_Permission == AccessPermission_NotPresent) { 475 m_cache[cacheSet][i] = entry; // Init entry 476 m_cache[cacheSet][i]->m_Address = address; 477 m_cache[cacheSet][i]->m_Permission = AccessPermission_Invalid; 478 479 m_replacementPolicy_ptr->touch(cacheSet, i, g_eventQueue_ptr->getTime()); 480 481 return; 482 } 483 } 484 ERROR_MSG("Allocate didn't find an available entry"); 485} 486 487inline 488void CacheMemory::deallocate(const Address& address) 489{ 490 assert(address == line_address(address)); 491 assert(isTagPresent(address)); 492 DEBUG_EXPR(CACHE_COMP, HighPrio, address); 493 Index cacheSet = addressToCacheSet(address); 494 int location = findTagInSet(cacheSet, address); 495 if (location != -1){ 496 delete m_cache[cacheSet][location]; 497 m_cache[cacheSet][location] = NULL; 498 } 499} 500 501// Returns with the physical address of the conflicting cache line 502inline 503Address CacheMemory::cacheProbe(const Address& address) const 504{ 505 assert(address == line_address(address)); 506 assert(!cacheAvail(address)); 507 508 Index cacheSet = addressToCacheSet(address); 509 return m_cache[cacheSet][m_replacementPolicy_ptr->getVictim(cacheSet)]->m_Address; 510} 511 512// looks an address up in the cache 513inline 514AbstractCacheEntry& CacheMemory::lookup(const Address& address) 515{ 516 assert(address == line_address(address)); 517 Index cacheSet = addressToCacheSet(address); 518 int loc = findTagInSet(cacheSet, address); 519 assert(loc != -1); 520 return *m_cache[cacheSet][loc]; 521} 522 523// looks an address up in the cache 524inline 525const AbstractCacheEntry& CacheMemory::lookup(const Address& address) const 526{ 527 assert(address == line_address(address)); 528 Index cacheSet = addressToCacheSet(address); 529 int loc = findTagInSet(cacheSet, address); 530 assert(loc != -1); 531 return *m_cache[cacheSet][loc]; 532} 533 534inline 535AccessPermission CacheMemory::getPermission(const Address& address) const 536{ 537 assert(address == line_address(address)); 538 return lookup(address).m_Permission; 539} 540 541inline 542void CacheMemory::changePermission(const Address& address, AccessPermission new_perm) 543{ 544 assert(address == line_address(address)); 545 lookup(address).m_Permission = new_perm; 546 assert(getPermission(address) == new_perm); 547} 548 549// Sets the most recently used bit for a cache block 550inline 551void CacheMemory::setMRU(const Address& address) 552{ 553 Index cacheSet; 554 555 cacheSet = addressToCacheSet(address); 556 m_replacementPolicy_ptr->touch(cacheSet, 557 findTagInSet(cacheSet, address), 558 g_eventQueue_ptr->getTime()); 559} 560 561inline 562void CacheMemory::recordCacheContents(CacheRecorder& tr) const 563{ 564 for (int i = 0; i < m_cache_num_sets; i++) { 565 for (int j = 0; j < m_cache_assoc; j++) { 566 AccessPermission perm = m_cache[i][j]->m_Permission; 567 CacheRequestType request_type = CacheRequestType_NULL; 568 if (perm == AccessPermission_Read_Only) { 569 if (m_is_instruction_only_cache) { 570 request_type = CacheRequestType_IFETCH; 571 } else { 572 request_type = CacheRequestType_LD; 573 } 574 } else if (perm == AccessPermission_Read_Write) { 575 request_type = CacheRequestType_ST; 576 } 577 578 if (request_type != CacheRequestType_NULL) { 579 // tr.addRecord(m_chip_ptr->getID(), m_cache[i][j].m_Address, 580 // Address(0), request_type, m_replacementPolicy_ptr->getLastAccess(i, j)); 581 } 582 } 583 } 584} 585 586inline 587void CacheMemory::print(ostream& out) const 588{ 589 out << "Cache dump: " << m_cache_name << endl; 590 for (int i = 0; i < m_cache_num_sets; i++) { 591 for (int j = 0; j < m_cache_assoc; j++) { 592 if (m_cache[i][j] != NULL) { 593 out << " Index: " << i 594 << " way: " << j 595 << " entry: " << *m_cache[i][j] << endl; 596 } else { 597 out << " Index: " << i 598 << " way: " << j 599 << " entry: NULL" << endl; 600 } 601 } 602 } 603} 604 605inline 606void CacheMemory::printData(ostream& out) const 607{ 608 out << "printData() not supported" << endl; 609} 610 611inline 612void CacheMemory::getMemoryValue(const Address& addr, char* value, 613 unsigned int size_in_bytes ){ 614 AbstractCacheEntry& entry = lookup(line_address(addr)); 615 unsigned int startByte = addr.getAddress() - line_address(addr).getAddress(); 616 for(unsigned int i=0; i<size_in_bytes; ++i){ 617 value[i] = entry.getDataBlk().getByte(i + startByte); 618 } 619} 620 621inline 622void CacheMemory::setMemoryValue(const Address& addr, char* value, 623 unsigned int size_in_bytes ){ 624 AbstractCacheEntry& entry = lookup(line_address(addr)); 625 unsigned int startByte = addr.getAddress() - line_address(addr).getAddress(); 626 assert(size_in_bytes > 0); 627 for(unsigned int i=0; i<size_in_bytes; ++i){ 628 entry.getDataBlk().setByte(i + startByte, value[i]); 629 } 630 631 // entry = lookup(line_address(addr)); 632} 633 634#endif //CACHEMEMORY_H 635 636