CacheMemory.hh revision 6285
12810Srdreslin@umich.edu/* 211051Sandreas.hansson@arm.com * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood 311051Sandreas.hansson@arm.com * All rights reserved. 411051Sandreas.hansson@arm.com * 511051Sandreas.hansson@arm.com * Redistribution and use in source and binary forms, with or without 611051Sandreas.hansson@arm.com * modification, are permitted provided that the following conditions are 711051Sandreas.hansson@arm.com * met: redistributions of source code must retain the above copyright 811051Sandreas.hansson@arm.com * notice, this list of conditions and the following disclaimer; 911051Sandreas.hansson@arm.com * redistributions in binary form must reproduce the above copyright 1011051Sandreas.hansson@arm.com * notice, this list of conditions and the following disclaimer in the 1111051Sandreas.hansson@arm.com * documentation and/or other materials provided with the distribution; 1211051Sandreas.hansson@arm.com * neither the name of the copyright holders nor the names of its 1311051Sandreas.hansson@arm.com * contributors may be used to endorse or promote products derived from 1411051Sandreas.hansson@arm.com * this software without specific prior written permission. 1511051Sandreas.hansson@arm.com * 162810Srdreslin@umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 172810Srdreslin@umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 182810Srdreslin@umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 192810Srdreslin@umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 202810Srdreslin@umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 212810Srdreslin@umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 222810Srdreslin@umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 232810Srdreslin@umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 242810Srdreslin@umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 252810Srdreslin@umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 262810Srdreslin@umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 272810Srdreslin@umich.edu */ 282810Srdreslin@umich.edu 292810Srdreslin@umich.edu/* 302810Srdreslin@umich.edu * CacheMemory.hh 312810Srdreslin@umich.edu * 322810Srdreslin@umich.edu * Description: 332810Srdreslin@umich.edu * 342810Srdreslin@umich.edu * $Id: CacheMemory.hh,v 3.7 2004/06/18 20:15:15 beckmann Exp $ 352810Srdreslin@umich.edu * 362810Srdreslin@umich.edu */ 372810Srdreslin@umich.edu 382810Srdreslin@umich.edu#ifndef CACHEMEMORY_H 392810Srdreslin@umich.edu#define CACHEMEMORY_H 402810Srdreslin@umich.edu 412810Srdreslin@umich.edu#include "mem/ruby/common/Global.hh" 4211051Sandreas.hansson@arm.com#include "mem/protocol/AccessPermission.hh" 4311051Sandreas.hansson@arm.com#include "mem/ruby/common/Address.hh" 442810Srdreslin@umich.edu#include "mem/ruby/recorder/CacheRecorder.hh" 4511051Sandreas.hansson@arm.com#include "mem/protocol/CacheRequestType.hh" 4611051Sandreas.hansson@arm.com#include "mem/gems_common/Vector.hh" 472810Srdreslin@umich.edu#include "mem/ruby/common/DataBlock.hh" 482810Srdreslin@umich.edu#include "mem/protocol/MachineType.hh" 492810Srdreslin@umich.edu#include "mem/ruby/slicc_interface/RubySlicc_ComponentMapping.hh" 502810Srdreslin@umich.edu#include "mem/ruby/system/PseudoLRUPolicy.hh" 5111051Sandreas.hansson@arm.com#include "mem/ruby/system/LRUPolicy.hh" 522810Srdreslin@umich.edu#include "mem/ruby/slicc_interface/AbstractCacheEntry.hh" 532810Srdreslin@umich.edu#include "mem/ruby/system/System.hh" 5411051Sandreas.hansson@arm.com#include "mem/ruby/slicc_interface/AbstractController.hh" 552810Srdreslin@umich.edu#include <vector> 5611051Sandreas.hansson@arm.com 5711051Sandreas.hansson@arm.comclass CacheMemory { 5811051Sandreas.hansson@arm.compublic: 5911051Sandreas.hansson@arm.com 6011051Sandreas.hansson@arm.com // Constructors 6111288Ssteve.reinhardt@amd.com CacheMemory(const string & name); 6211051Sandreas.hansson@arm.com void init(const vector<string> & argv); 6311051Sandreas.hansson@arm.com 6411051Sandreas.hansson@arm.com // Destructor 6511051Sandreas.hansson@arm.com ~CacheMemory(); 6611051Sandreas.hansson@arm.com 6711053Sandreas.hansson@arm.com // factory 6811053Sandreas.hansson@arm.com // static CacheMemory* createCache(int level, int num, char split_type, AbstractCacheEntry* (*entry_factory)()); 6911051Sandreas.hansson@arm.com // static CacheMemory* getCache(int cache_id); 7011051Sandreas.hansson@arm.com 7111051Sandreas.hansson@arm.com // Public Methods 7211197Sandreas.hansson@arm.com void printConfig(ostream& out); 7311197Sandreas.hansson@arm.com 7411199Sandreas.hansson@arm.com // perform a cache access and see if we hit or not. Return true on a hit. 7511197Sandreas.hansson@arm.com bool tryCacheAccess(const Address& address, CacheRequestType type, DataBlock*& data_ptr); 7611197Sandreas.hansson@arm.com 7711197Sandreas.hansson@arm.com // similar to above, but doesn't require full access check 7811051Sandreas.hansson@arm.com bool testCacheAccess(const Address& address, CacheRequestType type, DataBlock*& data_ptr); 7911051Sandreas.hansson@arm.com 8011051Sandreas.hansson@arm.com // tests to see if an address is present in the cache 8111051Sandreas.hansson@arm.com bool isTagPresent(const Address& address) const; 8211051Sandreas.hansson@arm.com 8311051Sandreas.hansson@arm.com // Returns true if there is: 8411051Sandreas.hansson@arm.com // a) a tag match on this address or there is 8511051Sandreas.hansson@arm.com // b) an unused line in the same cache "way" 8611051Sandreas.hansson@arm.com bool cacheAvail(const Address& address) const; 8711051Sandreas.hansson@arm.com 8811051Sandreas.hansson@arm.com // find an unused entry and sets the tag appropriate for the address 8911051Sandreas.hansson@arm.com void allocate(const Address& address, AbstractCacheEntry* new_entry); 9011051Sandreas.hansson@arm.com 9111051Sandreas.hansson@arm.com // Explicitly free up this address 9211051Sandreas.hansson@arm.com void deallocate(const Address& address); 9311051Sandreas.hansson@arm.com 9411051Sandreas.hansson@arm.com // Returns with the physical address of the conflicting cache line 9511051Sandreas.hansson@arm.com Address cacheProbe(const Address& address) const; 9611051Sandreas.hansson@arm.com 9711051Sandreas.hansson@arm.com // looks an address up in the cache 9811051Sandreas.hansson@arm.com AbstractCacheEntry& lookup(const Address& address); 9911051Sandreas.hansson@arm.com const AbstractCacheEntry& lookup(const Address& address) const; 10011051Sandreas.hansson@arm.com 10111051Sandreas.hansson@arm.com // Get/Set permission of cache block 10211051Sandreas.hansson@arm.com AccessPermission getPermission(const Address& address) const; 10311051Sandreas.hansson@arm.com void changePermission(const Address& address, AccessPermission new_perm); 10411051Sandreas.hansson@arm.com 10511051Sandreas.hansson@arm.com int getLatency() const { return m_latency; } 10611051Sandreas.hansson@arm.com 10711051Sandreas.hansson@arm.com // Hook for checkpointing the contents of the cache 10811051Sandreas.hansson@arm.com void recordCacheContents(CacheRecorder& tr) const; 10911051Sandreas.hansson@arm.com void setAsInstructionCache(bool is_icache) { m_is_instruction_only_cache = is_icache; } 11011051Sandreas.hansson@arm.com 11111051Sandreas.hansson@arm.com // Set this address to most recently used 11211051Sandreas.hansson@arm.com void setMRU(const Address& address); 11311051Sandreas.hansson@arm.com 11411051Sandreas.hansson@arm.com void getMemoryValue(const Address& addr, char* value, 11511051Sandreas.hansson@arm.com unsigned int size_in_bytes ); 11611051Sandreas.hansson@arm.com void setMemoryValue(const Address& addr, char* value, 11711051Sandreas.hansson@arm.com unsigned int size_in_bytes ); 11811051Sandreas.hansson@arm.com 11911051Sandreas.hansson@arm.com // Print cache contents 12011051Sandreas.hansson@arm.com void print(ostream& out) const; 12111051Sandreas.hansson@arm.com void printData(ostream& out) const; 12211051Sandreas.hansson@arm.com 12311051Sandreas.hansson@arm.comprivate: 12411051Sandreas.hansson@arm.com // Private Methods 12511051Sandreas.hansson@arm.com 12611051Sandreas.hansson@arm.com // convert a Address to its location in the cache 12711051Sandreas.hansson@arm.com Index addressToCacheSet(const Address& address) const; 12811051Sandreas.hansson@arm.com 12911051Sandreas.hansson@arm.com // Given a cache tag: returns the index of the tag in a set. 13011051Sandreas.hansson@arm.com // returns -1 if the tag is not found. 13111051Sandreas.hansson@arm.com int findTagInSet(Index line, const Address& tag) const; 13211051Sandreas.hansson@arm.com int findTagInSetIgnorePermissions(Index cacheSet, const Address& tag) const; 13311051Sandreas.hansson@arm.com 13411051Sandreas.hansson@arm.com // Private copy constructor and assignment operator 13511051Sandreas.hansson@arm.com CacheMemory(const CacheMemory& obj); 13611051Sandreas.hansson@arm.com CacheMemory& operator=(const CacheMemory& obj); 13711051Sandreas.hansson@arm.com 13811051Sandreas.hansson@arm.comprivate: 13911051Sandreas.hansson@arm.com const string m_cache_name; 14011051Sandreas.hansson@arm.com AbstractController* m_controller; 14111051Sandreas.hansson@arm.com int m_latency; 14211051Sandreas.hansson@arm.com 14311051Sandreas.hansson@arm.com // Data Members (m_prefix) 14411051Sandreas.hansson@arm.com bool m_is_instruction_only_cache; 14511051Sandreas.hansson@arm.com bool m_is_data_only_cache; 14611051Sandreas.hansson@arm.com 14711051Sandreas.hansson@arm.com // The first index is the # of cache lines. 14811051Sandreas.hansson@arm.com // The second index is the the amount associativity. 14911051Sandreas.hansson@arm.com Vector<Vector<AbstractCacheEntry*> > m_cache; 15011051Sandreas.hansson@arm.com 15111051Sandreas.hansson@arm.com AbstractReplacementPolicy *m_replacementPolicy_ptr; 15211051Sandreas.hansson@arm.com 15311051Sandreas.hansson@arm.com int m_cache_num_sets; 15411051Sandreas.hansson@arm.com int m_cache_num_set_bits; 15511051Sandreas.hansson@arm.com int m_cache_assoc; 15611051Sandreas.hansson@arm.com 15711051Sandreas.hansson@arm.com static Vector< CacheMemory* > m_all_caches; 15811051Sandreas.hansson@arm.com}; 15911051Sandreas.hansson@arm.com/* 16011051Sandreas.hansson@arm.cominline 16111284Sandreas.hansson@arm.comCacheMemory* CacheMemory::getCache(int cache_id) 16211051Sandreas.hansson@arm.com{ 16311051Sandreas.hansson@arm.com assert(cache_id < RubyConfig::getNumberOfCaches()); 16411051Sandreas.hansson@arm.com if (m_all_caches[cache_id] == NULL) { 16511051Sandreas.hansson@arm.com cerr << "ERROR: Tried to obtain CacheMemory that hasn't been created yet." << endl; 16611051Sandreas.hansson@arm.com assert(0); 16711051Sandreas.hansson@arm.com } 16811051Sandreas.hansson@arm.com return m_all_caches[cache_id]; 16911284Sandreas.hansson@arm.com} 17011284Sandreas.hansson@arm.com 17111284Sandreas.hansson@arm.cominline 17211284Sandreas.hansson@arm.comCacheMemory* CacheMemory::createCache(int level, int num, char split_type_c, AbstractCacheEntry* (*entry_factory)()) 17311051Sandreas.hansson@arm.com{ 17411284Sandreas.hansson@arm.com string split_type; 17511051Sandreas.hansson@arm.com switch(split_type_c) { 17611051Sandreas.hansson@arm.com case 'i': 17711051Sandreas.hansson@arm.com split_type = "instruction"; break; 17811284Sandreas.hansson@arm.com case 'd': 17911284Sandreas.hansson@arm.com split_type = "data"; break; 18011284Sandreas.hansson@arm.com default: 18111284Sandreas.hansson@arm.com split_type = "unified"; break; 18211051Sandreas.hansson@arm.com } 18311288Ssteve.reinhardt@amd.com int cache_id = RubyConfig::getCacheIDFromParams(level, num, split_type); 18411288Ssteve.reinhardt@amd.com assert(cache_id < RubyConfig::getNumberOfCaches()); 18511051Sandreas.hansson@arm.com if (m_all_caches.size() == 0) { 18611051Sandreas.hansson@arm.com m_all_caches.setSize(RubyConfig::getNumberOfCaches()); 18711051Sandreas.hansson@arm.com for (int i=0; i<m_all_caches.size(); i++) 18811051Sandreas.hansson@arm.com m_all_caches[i] = NULL; 18911286Sandreas.hansson@arm.com } 19011286Sandreas.hansson@arm.com 19111286Sandreas.hansson@arm.com string type = RubyConfig::getCacheType(cache_id); 19211051Sandreas.hansson@arm.com if ( type == "SetAssociativeCache" ) { 19311286Sandreas.hansson@arm.com m_all_caches[cache_id] = new CacheMemory(cache_id, entry_factory); 19411051Sandreas.hansson@arm.com } 19511051Sandreas.hansson@arm.com return m_all_caches[cache_id]; 19611051Sandreas.hansson@arm.com} 19711051Sandreas.hansson@arm.com*/ 19811051Sandreas.hansson@arm.com// Output operator declaration 19911051Sandreas.hansson@arm.com//ostream& operator<<(ostream& out, const CacheMemory<ENTRY>& obj); 20011051Sandreas.hansson@arm.com 20111051Sandreas.hansson@arm.com// ******************* Definitions ******************* 20211051Sandreas.hansson@arm.com 20311051Sandreas.hansson@arm.com// Output operator definition 20411051Sandreas.hansson@arm.cominline 20511284Sandreas.hansson@arm.comostream& operator<<(ostream& out, const CacheMemory& obj) 20611051Sandreas.hansson@arm.com{ 20711051Sandreas.hansson@arm.com obj.print(out); 20811051Sandreas.hansson@arm.com out << flush; 20911051Sandreas.hansson@arm.com return out; 21011051Sandreas.hansson@arm.com} 21111284Sandreas.hansson@arm.com 21211051Sandreas.hansson@arm.com 21311284Sandreas.hansson@arm.com// **************************************************************** 21411051Sandreas.hansson@arm.com 21511197Sandreas.hansson@arm.cominline 21611197Sandreas.hansson@arm.comCacheMemory::CacheMemory(const string & name) 21711197Sandreas.hansson@arm.com : m_cache_name(name) 21811197Sandreas.hansson@arm.com{ 21911051Sandreas.hansson@arm.com} 22011284Sandreas.hansson@arm.com 22111051Sandreas.hansson@arm.cominline 22211284Sandreas.hansson@arm.comvoid CacheMemory::init(const vector<string> & argv) 22311284Sandreas.hansson@arm.com{ 22411284Sandreas.hansson@arm.com int cache_size = 0; 22511051Sandreas.hansson@arm.com string policy; 22611051Sandreas.hansson@arm.com 22711051Sandreas.hansson@arm.com m_controller = NULL; 22811284Sandreas.hansson@arm.com for (uint32 i=0; i<argv.size(); i+=2) { 22911284Sandreas.hansson@arm.com if (argv[i] == "size_kb") { 23011284Sandreas.hansson@arm.com cache_size = atoi(argv[i+1].c_str()); 23111284Sandreas.hansson@arm.com } else if (argv[i] == "latency") { 23211051Sandreas.hansson@arm.com m_latency = atoi(argv[i+1].c_str()); 23311051Sandreas.hansson@arm.com } else if (argv[i] == "assoc") { 23411051Sandreas.hansson@arm.com m_cache_assoc = atoi(argv[i+1].c_str()); 23511284Sandreas.hansson@arm.com } else if (argv[i] == "replacement_policy") { 23611284Sandreas.hansson@arm.com policy = argv[i+1]; 23711284Sandreas.hansson@arm.com } else if (argv[i] == "controller") { 23811197Sandreas.hansson@arm.com m_controller = RubySystem::getController(argv[i+1]); 23911284Sandreas.hansson@arm.com } else { 24011284Sandreas.hansson@arm.com cerr << "WARNING: CacheMemory: Unknown configuration parameter: " << argv[i] << endl; 24111284Sandreas.hansson@arm.com } 24211284Sandreas.hansson@arm.com } 24311284Sandreas.hansson@arm.com 24411284Sandreas.hansson@arm.com m_cache_num_sets = cache_size / m_cache_assoc; 24511284Sandreas.hansson@arm.com m_cache_num_set_bits = log_int(m_cache_num_sets); 24611284Sandreas.hansson@arm.com 24711284Sandreas.hansson@arm.com if(policy == "PSEUDO_LRU") 24811284Sandreas.hansson@arm.com m_replacementPolicy_ptr = new PseudoLRUPolicy(m_cache_num_sets, m_cache_assoc); 24911284Sandreas.hansson@arm.com else if (policy == "LRU") 25011284Sandreas.hansson@arm.com m_replacementPolicy_ptr = new LRUPolicy(m_cache_num_sets, m_cache_assoc); 25111284Sandreas.hansson@arm.com else 25211284Sandreas.hansson@arm.com assert(false); 25311284Sandreas.hansson@arm.com 25411197Sandreas.hansson@arm.com m_cache.setSize(m_cache_num_sets); 25511284Sandreas.hansson@arm.com for (int i = 0; i < m_cache_num_sets; i++) { 25611284Sandreas.hansson@arm.com m_cache[i].setSize(m_cache_assoc); 25711284Sandreas.hansson@arm.com for (int j = 0; j < m_cache_assoc; j++) { 25811284Sandreas.hansson@arm.com m_cache[i][j] = NULL; 25911284Sandreas.hansson@arm.com } 26011284Sandreas.hansson@arm.com } 26111284Sandreas.hansson@arm.com} 26211197Sandreas.hansson@arm.com/* 26311051Sandreas.hansson@arm.cominline 26411051Sandreas.hansson@arm.comCacheMemory::CacheMemory(int cache_id, AbstractCacheEntry* (*entry_factory)()) 26511051Sandreas.hansson@arm.com{ 26611051Sandreas.hansson@arm.com string split_type; 26711051Sandreas.hansson@arm.com 26811284Sandreas.hansson@arm.com m_cache_id = cache_id; 26911284Sandreas.hansson@arm.com m_entry_factory = entry_factory; 27011051Sandreas.hansson@arm.com 27111051Sandreas.hansson@arm.com m_cache_num_set_bits = RubyConfig::getNumberOfCacheSetBits(cache_id); 27211051Sandreas.hansson@arm.com m_cache_num_sets = RubyConfig::getNumberOfCacheSets(cache_id); 27311051Sandreas.hansson@arm.com m_cache_assoc = RubyConfig::getCacheAssoc(cache_id); 27411284Sandreas.hansson@arm.com split_type = RubyConfig::getCacheSplitType(cache_id); 27511051Sandreas.hansson@arm.com m_is_instruction_only_cache = m_is_data_only_cache = false; 27611051Sandreas.hansson@arm.com if (split_type == "instruction") 27711051Sandreas.hansson@arm.com m_is_instruction_only_cache = true; 27811284Sandreas.hansson@arm.com else if (split_type == "data") 27911051Sandreas.hansson@arm.com m_is_data_only_cache = true; 28011197Sandreas.hansson@arm.com else 28111197Sandreas.hansson@arm.com assert(split_type == "unified"); 28211197Sandreas.hansson@arm.com 28311197Sandreas.hansson@arm.com if(RubyConfig::getCacheReplacementPolicy(cache_id) == "PSEUDO_LRU") 28411288Ssteve.reinhardt@amd.com m_replacementPolicy_ptr = new PseudoLRUPolicy(m_cache_num_sets, m_cache_assoc); 28511051Sandreas.hansson@arm.com else if(RubyConfig::getCacheReplacementPolicy(cache_id) == "LRU") 28611051Sandreas.hansson@arm.com m_replacementPolicy_ptr = new LRUPolicy(m_cache_num_sets, m_cache_assoc); 28711051Sandreas.hansson@arm.com else 28811051Sandreas.hansson@arm.com assert(false); 28911051Sandreas.hansson@arm.com 29011051Sandreas.hansson@arm.com m_cache.setSize(m_cache_num_sets); 29111051Sandreas.hansson@arm.com for (int i = 0; i < m_cache_num_sets; i++) { 29211051Sandreas.hansson@arm.com m_cache[i].setSize(m_cache_assoc); 29311051Sandreas.hansson@arm.com for (int j = 0; j < m_cache_assoc; j++) { 29411051Sandreas.hansson@arm.com m_cache[i][j] = m_entry_factory(); 29511051Sandreas.hansson@arm.com } 29611051Sandreas.hansson@arm.com } 29711051Sandreas.hansson@arm.com} 29811284Sandreas.hansson@arm.com*/ 29911051Sandreas.hansson@arm.cominline 30011284Sandreas.hansson@arm.comCacheMemory::~CacheMemory() 30111051Sandreas.hansson@arm.com{ 30211051Sandreas.hansson@arm.com if(m_replacementPolicy_ptr != NULL) 30311051Sandreas.hansson@arm.com delete m_replacementPolicy_ptr; 30411051Sandreas.hansson@arm.com} 30511051Sandreas.hansson@arm.com 30611051Sandreas.hansson@arm.cominline 30711051Sandreas.hansson@arm.comvoid CacheMemory::printConfig(ostream& out) 30811051Sandreas.hansson@arm.com{ 30911051Sandreas.hansson@arm.com out << "Cache config: " << m_cache_name << endl; 31011051Sandreas.hansson@arm.com if (m_controller != NULL) 31111051Sandreas.hansson@arm.com out << " controller: " << m_controller->getName() << endl; 31211051Sandreas.hansson@arm.com out << " cache_associativity: " << m_cache_assoc << endl; 31311051Sandreas.hansson@arm.com out << " num_cache_sets_bits: " << m_cache_num_set_bits << endl; 31411051Sandreas.hansson@arm.com const int cache_num_sets = 1 << m_cache_num_set_bits; 31511051Sandreas.hansson@arm.com out << " num_cache_sets: " << cache_num_sets << endl; 31611051Sandreas.hansson@arm.com out << " cache_set_size_bytes: " << cache_num_sets * RubySystem::getBlockSizeBytes() << endl; 31711051Sandreas.hansson@arm.com out << " cache_set_size_Kbytes: " 31811051Sandreas.hansson@arm.com << double(cache_num_sets * RubySystem::getBlockSizeBytes()) / (1<<10) << endl; 31911051Sandreas.hansson@arm.com out << " cache_set_size_Mbytes: " 32011288Ssteve.reinhardt@amd.com << double(cache_num_sets * RubySystem::getBlockSizeBytes()) / (1<<20) << endl; 32111051Sandreas.hansson@arm.com out << " cache_size_bytes: " 32211051Sandreas.hansson@arm.com << cache_num_sets * RubySystem::getBlockSizeBytes() * m_cache_assoc << endl; 32311051Sandreas.hansson@arm.com out << " cache_size_Kbytes: " 32411051Sandreas.hansson@arm.com << double(cache_num_sets * RubySystem::getBlockSizeBytes() * m_cache_assoc) / (1<<10) << endl; 32511051Sandreas.hansson@arm.com out << " cache_size_Mbytes: " 32611051Sandreas.hansson@arm.com << double(cache_num_sets * RubySystem::getBlockSizeBytes() * m_cache_assoc) / (1<<20) << endl; 32711051Sandreas.hansson@arm.com} 32811051Sandreas.hansson@arm.com 32911051Sandreas.hansson@arm.com// PRIVATE METHODS 33011051Sandreas.hansson@arm.com 33111199Sandreas.hansson@arm.com// convert a Address to its location in the cache 33211051Sandreas.hansson@arm.cominline 33311051Sandreas.hansson@arm.comIndex CacheMemory::addressToCacheSet(const Address& address) const 33411051Sandreas.hansson@arm.com{ 33511051Sandreas.hansson@arm.com assert(address == line_address(address)); 33611051Sandreas.hansson@arm.com Index temp = -1; 33711051Sandreas.hansson@arm.com return address.bitSelect(RubySystem::getBlockSizeBits(), RubySystem::getBlockSizeBits() + m_cache_num_set_bits-1); 33811051Sandreas.hansson@arm.com} 33911051Sandreas.hansson@arm.com 34011051Sandreas.hansson@arm.com// Given a cache index: returns the index of the tag in a set. 34111051Sandreas.hansson@arm.com// returns -1 if the tag is not found. 34211051Sandreas.hansson@arm.cominline 34311051Sandreas.hansson@arm.comint CacheMemory::findTagInSet(Index cacheSet, const Address& tag) const 34411051Sandreas.hansson@arm.com{ 34511051Sandreas.hansson@arm.com assert(tag == line_address(tag)); 34611051Sandreas.hansson@arm.com // search the set for the tags 34711051Sandreas.hansson@arm.com for (int i=0; i < m_cache_assoc; i++) { 34811051Sandreas.hansson@arm.com if ((m_cache[cacheSet][i] != NULL) && 34911051Sandreas.hansson@arm.com (m_cache[cacheSet][i]->m_Address == tag) && 35011051Sandreas.hansson@arm.com (m_cache[cacheSet][i]->m_Permission != AccessPermission_NotPresent)) { 35111051Sandreas.hansson@arm.com return i; 35211051Sandreas.hansson@arm.com } 35311051Sandreas.hansson@arm.com } 35411051Sandreas.hansson@arm.com return -1; // Not found 35511051Sandreas.hansson@arm.com} 35611051Sandreas.hansson@arm.com 35711199Sandreas.hansson@arm.com// Given a cache index: returns the index of the tag in a set. 35811051Sandreas.hansson@arm.com// returns -1 if the tag is not found. 35911051Sandreas.hansson@arm.cominline 36011051Sandreas.hansson@arm.comint CacheMemory::findTagInSetIgnorePermissions(Index cacheSet, const Address& tag) const 36111051Sandreas.hansson@arm.com{ 36211051Sandreas.hansson@arm.com assert(tag == line_address(tag)); 36311051Sandreas.hansson@arm.com // search the set for the tags 36411051Sandreas.hansson@arm.com for (int i=0; i < m_cache_assoc; i++) { 36511051Sandreas.hansson@arm.com if (m_cache[cacheSet][i] != NULL && m_cache[cacheSet][i]->m_Address == tag) 36611051Sandreas.hansson@arm.com return i; 36711051Sandreas.hansson@arm.com } 36811051Sandreas.hansson@arm.com return -1; // Not found 36911051Sandreas.hansson@arm.com} 37011199Sandreas.hansson@arm.com 37111199Sandreas.hansson@arm.com// PUBLIC METHODS 37211199Sandreas.hansson@arm.cominline 37311199Sandreas.hansson@arm.combool CacheMemory::tryCacheAccess(const Address& address, 37411199Sandreas.hansson@arm.com CacheRequestType type, 37511199Sandreas.hansson@arm.com DataBlock*& data_ptr) 37611199Sandreas.hansson@arm.com{ 37711199Sandreas.hansson@arm.com assert(address == line_address(address)); 37811199Sandreas.hansson@arm.com DEBUG_EXPR(CACHE_COMP, HighPrio, address); 37911199Sandreas.hansson@arm.com Index cacheSet = addressToCacheSet(address); 38011199Sandreas.hansson@arm.com int loc = findTagInSet(cacheSet, address); 38111199Sandreas.hansson@arm.com if(loc != -1){ // Do we even have a tag match? 38211199Sandreas.hansson@arm.com AbstractCacheEntry* entry = m_cache[cacheSet][loc]; 38311199Sandreas.hansson@arm.com m_replacementPolicy_ptr->touch(cacheSet, loc, g_eventQueue_ptr->getTime()); 38411199Sandreas.hansson@arm.com data_ptr = &(entry->getDataBlk()); 38511199Sandreas.hansson@arm.com 38611199Sandreas.hansson@arm.com if(entry->m_Permission == AccessPermission_Read_Write) { 38711199Sandreas.hansson@arm.com return true; 38811199Sandreas.hansson@arm.com } 38911199Sandreas.hansson@arm.com if ((entry->m_Permission == AccessPermission_Read_Only) && 39011199Sandreas.hansson@arm.com (type == CacheRequestType_LD || type == CacheRequestType_IFETCH)) { 39111199Sandreas.hansson@arm.com return true; 39211199Sandreas.hansson@arm.com } 39311199Sandreas.hansson@arm.com // The line must not be accessible 39411051Sandreas.hansson@arm.com } 39511051Sandreas.hansson@arm.com data_ptr = NULL; 39611051Sandreas.hansson@arm.com return false; 39711051Sandreas.hansson@arm.com} 39811051Sandreas.hansson@arm.com 39911199Sandreas.hansson@arm.cominline 40011051Sandreas.hansson@arm.combool CacheMemory::testCacheAccess(const Address& address, 40111199Sandreas.hansson@arm.com CacheRequestType type, 40211199Sandreas.hansson@arm.com DataBlock*& data_ptr) 40311199Sandreas.hansson@arm.com{ 40411199Sandreas.hansson@arm.com assert(address == line_address(address)); 40511199Sandreas.hansson@arm.com DEBUG_EXPR(CACHE_COMP, HighPrio, address); 40611199Sandreas.hansson@arm.com Index cacheSet = addressToCacheSet(address); 40711199Sandreas.hansson@arm.com int loc = findTagInSet(cacheSet, address); 40811199Sandreas.hansson@arm.com if(loc != -1){ // Do we even have a tag match? 40911199Sandreas.hansson@arm.com AbstractCacheEntry* entry = m_cache[cacheSet][loc]; 41011199Sandreas.hansson@arm.com m_replacementPolicy_ptr->touch(cacheSet, loc, g_eventQueue_ptr->getTime()); 41111199Sandreas.hansson@arm.com data_ptr = &(entry->getDataBlk()); 41211199Sandreas.hansson@arm.com 41311051Sandreas.hansson@arm.com return (m_cache[cacheSet][loc]->m_Permission != AccessPermission_NotPresent); 41411051Sandreas.hansson@arm.com } 41511051Sandreas.hansson@arm.com data_ptr = NULL; 41611051Sandreas.hansson@arm.com return false; 41711051Sandreas.hansson@arm.com} 41811051Sandreas.hansson@arm.com 41911051Sandreas.hansson@arm.com// tests to see if an address is present in the cache 42011051Sandreas.hansson@arm.cominline 42111051Sandreas.hansson@arm.combool CacheMemory::isTagPresent(const Address& address) const 42211051Sandreas.hansson@arm.com{ 42311051Sandreas.hansson@arm.com assert(address == line_address(address)); 42411051Sandreas.hansson@arm.com Index cacheSet = addressToCacheSet(address); 42511051Sandreas.hansson@arm.com int location = findTagInSet(cacheSet, address); 42611051Sandreas.hansson@arm.com 42711051Sandreas.hansson@arm.com if (location == -1) { 42811199Sandreas.hansson@arm.com // We didn't find the tag 42911199Sandreas.hansson@arm.com DEBUG_EXPR(CACHE_COMP, LowPrio, address); 43011199Sandreas.hansson@arm.com DEBUG_MSG(CACHE_COMP, LowPrio, "No tag match"); 43111199Sandreas.hansson@arm.com return false; 43211199Sandreas.hansson@arm.com } 43311284Sandreas.hansson@arm.com DEBUG_EXPR(CACHE_COMP, LowPrio, address); 43411284Sandreas.hansson@arm.com DEBUG_MSG(CACHE_COMP, LowPrio, "found"); 43511284Sandreas.hansson@arm.com return true; 43611284Sandreas.hansson@arm.com} 43711051Sandreas.hansson@arm.com 43811051Sandreas.hansson@arm.com// Returns true if there is: 43911051Sandreas.hansson@arm.com// a) a tag match on this address or there is 44011051Sandreas.hansson@arm.com// b) an unused line in the same cache "way" 44111051Sandreas.hansson@arm.cominline 44211051Sandreas.hansson@arm.combool CacheMemory::cacheAvail(const Address& address) const 44311051Sandreas.hansson@arm.com{ 44411051Sandreas.hansson@arm.com assert(address == line_address(address)); 44511051Sandreas.hansson@arm.com 44611051Sandreas.hansson@arm.com Index cacheSet = addressToCacheSet(address); 44711051Sandreas.hansson@arm.com 44811051Sandreas.hansson@arm.com for (int i=0; i < m_cache_assoc; i++) { 44911051Sandreas.hansson@arm.com AbstractCacheEntry* entry = m_cache[cacheSet][i]; 45011051Sandreas.hansson@arm.com if (entry != NULL) { 45111051Sandreas.hansson@arm.com if (entry->m_Address == address || // Already in the cache 45211051Sandreas.hansson@arm.com entry->m_Permission == AccessPermission_NotPresent) { // We found an empty entry 45311051Sandreas.hansson@arm.com return true; 45411051Sandreas.hansson@arm.com } 45511051Sandreas.hansson@arm.com } else { 45611051Sandreas.hansson@arm.com return true; 45711051Sandreas.hansson@arm.com } 45811051Sandreas.hansson@arm.com } 45911284Sandreas.hansson@arm.com return false; 46011051Sandreas.hansson@arm.com} 46111051Sandreas.hansson@arm.com 46211051Sandreas.hansson@arm.cominline 46311051Sandreas.hansson@arm.comvoid CacheMemory::allocate(const Address& address, AbstractCacheEntry* entry) 46411051Sandreas.hansson@arm.com{ 46511051Sandreas.hansson@arm.com assert(address == line_address(address)); 46611051Sandreas.hansson@arm.com assert(!isTagPresent(address)); 46711284Sandreas.hansson@arm.com assert(cacheAvail(address)); 46811051Sandreas.hansson@arm.com DEBUG_EXPR(CACHE_COMP, HighPrio, address); 46911051Sandreas.hansson@arm.com 47011051Sandreas.hansson@arm.com // Find the first open slot 47111051Sandreas.hansson@arm.com Index cacheSet = addressToCacheSet(address); 47211051Sandreas.hansson@arm.com for (int i=0; i < m_cache_assoc; i++) { 47311051Sandreas.hansson@arm.com if (m_cache[cacheSet][i] == NULL || 47411051Sandreas.hansson@arm.com m_cache[cacheSet][i]->m_Permission == AccessPermission_NotPresent) { 47511051Sandreas.hansson@arm.com m_cache[cacheSet][i] = entry; // Init entry 47611051Sandreas.hansson@arm.com m_cache[cacheSet][i]->m_Address = address; 47711051Sandreas.hansson@arm.com m_cache[cacheSet][i]->m_Permission = AccessPermission_Invalid; 47811051Sandreas.hansson@arm.com 47911051Sandreas.hansson@arm.com m_replacementPolicy_ptr->touch(cacheSet, i, g_eventQueue_ptr->getTime()); 48011051Sandreas.hansson@arm.com 48111051Sandreas.hansson@arm.com return; 48211051Sandreas.hansson@arm.com } 48311051Sandreas.hansson@arm.com } 48411051Sandreas.hansson@arm.com ERROR_MSG("Allocate didn't find an available entry"); 48511051Sandreas.hansson@arm.com} 48611051Sandreas.hansson@arm.com 48711051Sandreas.hansson@arm.cominline 48811051Sandreas.hansson@arm.comvoid CacheMemory::deallocate(const Address& address) 48911051Sandreas.hansson@arm.com{ 49011051Sandreas.hansson@arm.com assert(address == line_address(address)); 49111051Sandreas.hansson@arm.com assert(isTagPresent(address)); 49211051Sandreas.hansson@arm.com DEBUG_EXPR(CACHE_COMP, HighPrio, address); 49311051Sandreas.hansson@arm.com Index cacheSet = addressToCacheSet(address); 49411051Sandreas.hansson@arm.com int location = findTagInSet(cacheSet, address); 49511051Sandreas.hansson@arm.com if (location != -1){ 49611199Sandreas.hansson@arm.com delete m_cache[cacheSet][location]; 49711199Sandreas.hansson@arm.com m_cache[cacheSet][location] = NULL; 49811199Sandreas.hansson@arm.com } 49911199Sandreas.hansson@arm.com} 50011199Sandreas.hansson@arm.com 50111051Sandreas.hansson@arm.com// Returns with the physical address of the conflicting cache line 50211199Sandreas.hansson@arm.cominline 50311051Sandreas.hansson@arm.comAddress CacheMemory::cacheProbe(const Address& address) const 50411051Sandreas.hansson@arm.com{ 50511051Sandreas.hansson@arm.com assert(address == line_address(address)); 50611051Sandreas.hansson@arm.com assert(!cacheAvail(address)); 50711051Sandreas.hansson@arm.com 50811051Sandreas.hansson@arm.com Index cacheSet = addressToCacheSet(address); 50911051Sandreas.hansson@arm.com return m_cache[cacheSet][m_replacementPolicy_ptr->getVictim(cacheSet)]->m_Address; 51011051Sandreas.hansson@arm.com} 51111051Sandreas.hansson@arm.com 51211051Sandreas.hansson@arm.com// looks an address up in the cache 51311051Sandreas.hansson@arm.cominline 51411051Sandreas.hansson@arm.comAbstractCacheEntry& CacheMemory::lookup(const Address& address) 51511051Sandreas.hansson@arm.com{ 51611051Sandreas.hansson@arm.com assert(address == line_address(address)); 51711051Sandreas.hansson@arm.com Index cacheSet = addressToCacheSet(address); 51811051Sandreas.hansson@arm.com int loc = findTagInSet(cacheSet, address); 51911051Sandreas.hansson@arm.com assert(loc != -1); 52011130Sali.jafri@arm.com return *m_cache[cacheSet][loc]; 52111130Sali.jafri@arm.com} 52211130Sali.jafri@arm.com 52311130Sali.jafri@arm.com// looks an address up in the cache 52411130Sali.jafri@arm.cominline 52511130Sali.jafri@arm.comconst AbstractCacheEntry& CacheMemory::lookup(const Address& address) const 52611130Sali.jafri@arm.com{ 52711130Sali.jafri@arm.com assert(address == line_address(address)); 52811130Sali.jafri@arm.com Index cacheSet = addressToCacheSet(address); 52911199Sandreas.hansson@arm.com int loc = findTagInSet(cacheSet, address); 53011130Sali.jafri@arm.com assert(loc != -1); 53111130Sali.jafri@arm.com return *m_cache[cacheSet][loc]; 53211130Sali.jafri@arm.com} 53311130Sali.jafri@arm.com 53411130Sali.jafri@arm.cominline 53511130Sali.jafri@arm.comAccessPermission CacheMemory::getPermission(const Address& address) const 53611130Sali.jafri@arm.com{ 53711130Sali.jafri@arm.com assert(address == line_address(address)); 53811130Sali.jafri@arm.com return lookup(address).m_Permission; 53911130Sali.jafri@arm.com} 54011130Sali.jafri@arm.com 54111130Sali.jafri@arm.cominline 54211130Sali.jafri@arm.comvoid CacheMemory::changePermission(const Address& address, AccessPermission new_perm) 54311130Sali.jafri@arm.com{ 54411130Sali.jafri@arm.com assert(address == line_address(address)); 54511130Sali.jafri@arm.com lookup(address).m_Permission = new_perm; 54611130Sali.jafri@arm.com assert(getPermission(address) == new_perm); 54711130Sali.jafri@arm.com} 54811130Sali.jafri@arm.com 54911130Sali.jafri@arm.com// Sets the most recently used bit for a cache block 55011130Sali.jafri@arm.cominline 55111130Sali.jafri@arm.comvoid CacheMemory::setMRU(const Address& address) 55211130Sali.jafri@arm.com{ 55311051Sandreas.hansson@arm.com Index cacheSet; 55411051Sandreas.hansson@arm.com 55511051Sandreas.hansson@arm.com cacheSet = addressToCacheSet(address); 55611051Sandreas.hansson@arm.com m_replacementPolicy_ptr->touch(cacheSet, 55711051Sandreas.hansson@arm.com findTagInSet(cacheSet, address), 55811051Sandreas.hansson@arm.com g_eventQueue_ptr->getTime()); 55911051Sandreas.hansson@arm.com} 56011051Sandreas.hansson@arm.com 56111051Sandreas.hansson@arm.cominline 56211051Sandreas.hansson@arm.comvoid CacheMemory::recordCacheContents(CacheRecorder& tr) const 56311276Sandreas.hansson@arm.com{ 56411276Sandreas.hansson@arm.com for (int i = 0; i < m_cache_num_sets; i++) { 56511276Sandreas.hansson@arm.com for (int j = 0; j < m_cache_assoc; j++) { 56611276Sandreas.hansson@arm.com AccessPermission perm = m_cache[i][j]->m_Permission; 56711276Sandreas.hansson@arm.com CacheRequestType request_type = CacheRequestType_NULL; 56811276Sandreas.hansson@arm.com if (perm == AccessPermission_Read_Only) { 56911276Sandreas.hansson@arm.com if (m_is_instruction_only_cache) { 57011276Sandreas.hansson@arm.com request_type = CacheRequestType_IFETCH; 57111276Sandreas.hansson@arm.com } else { 57211051Sandreas.hansson@arm.com request_type = CacheRequestType_LD; 57311276Sandreas.hansson@arm.com } 57411276Sandreas.hansson@arm.com } else if (perm == AccessPermission_Read_Write) { 57511276Sandreas.hansson@arm.com request_type = CacheRequestType_ST; 57611276Sandreas.hansson@arm.com } 57711276Sandreas.hansson@arm.com 57811051Sandreas.hansson@arm.com if (request_type != CacheRequestType_NULL) { 57911051Sandreas.hansson@arm.com // tr.addRecord(m_chip_ptr->getID(), m_cache[i][j].m_Address, 58011051Sandreas.hansson@arm.com // Address(0), request_type, m_replacementPolicy_ptr->getLastAccess(i, j)); 58111051Sandreas.hansson@arm.com } 58211051Sandreas.hansson@arm.com } 58311051Sandreas.hansson@arm.com } 58411051Sandreas.hansson@arm.com} 58511051Sandreas.hansson@arm.com 58611051Sandreas.hansson@arm.cominline 58711051Sandreas.hansson@arm.comvoid CacheMemory::print(ostream& out) const 58811051Sandreas.hansson@arm.com{ 58911051Sandreas.hansson@arm.com out << "Cache dump: " << m_cache_name << endl; 59011051Sandreas.hansson@arm.com for (int i = 0; i < m_cache_num_sets; i++) { 59111051Sandreas.hansson@arm.com for (int j = 0; j < m_cache_assoc; j++) { 59211051Sandreas.hansson@arm.com if (m_cache[i][j] != NULL) { 59311051Sandreas.hansson@arm.com out << " Index: " << i 59411051Sandreas.hansson@arm.com << " way: " << j 59511051Sandreas.hansson@arm.com << " entry: " << *m_cache[i][j] << endl; 59611051Sandreas.hansson@arm.com } else { 59711051Sandreas.hansson@arm.com out << " Index: " << i 59811051Sandreas.hansson@arm.com << " way: " << j 59911051Sandreas.hansson@arm.com << " entry: NULL" << endl; 60011051Sandreas.hansson@arm.com } 60111051Sandreas.hansson@arm.com } 60211051Sandreas.hansson@arm.com } 60311051Sandreas.hansson@arm.com} 60411051Sandreas.hansson@arm.com 60511051Sandreas.hansson@arm.cominline 60611051Sandreas.hansson@arm.comvoid CacheMemory::printData(ostream& out) const 60711051Sandreas.hansson@arm.com{ 60811051Sandreas.hansson@arm.com out << "printData() not supported" << endl; 60911051Sandreas.hansson@arm.com} 61011051Sandreas.hansson@arm.com 61111051Sandreas.hansson@arm.cominline 61211051Sandreas.hansson@arm.comvoid CacheMemory::getMemoryValue(const Address& addr, char* value, 61311051Sandreas.hansson@arm.com unsigned int size_in_bytes ){ 61411051Sandreas.hansson@arm.com AbstractCacheEntry& entry = lookup(line_address(addr)); 61511051Sandreas.hansson@arm.com unsigned int startByte = addr.getAddress() - line_address(addr).getAddress(); 61611051Sandreas.hansson@arm.com for(unsigned int i=0; i<size_in_bytes; ++i){ 61711051Sandreas.hansson@arm.com value[i] = entry.getDataBlk().getByte(i + startByte); 61811051Sandreas.hansson@arm.com } 61911051Sandreas.hansson@arm.com} 62011284Sandreas.hansson@arm.com 62111051Sandreas.hansson@arm.cominline 62211284Sandreas.hansson@arm.comvoid CacheMemory::setMemoryValue(const Address& addr, char* value, 62311284Sandreas.hansson@arm.com unsigned int size_in_bytes ){ 62411284Sandreas.hansson@arm.com AbstractCacheEntry& entry = lookup(line_address(addr)); 62511284Sandreas.hansson@arm.com unsigned int startByte = addr.getAddress() - line_address(addr).getAddress(); 62611051Sandreas.hansson@arm.com assert(size_in_bytes > 0); 62711051Sandreas.hansson@arm.com for(unsigned int i=0; i<size_in_bytes; ++i){ 62811284Sandreas.hansson@arm.com entry.getDataBlk().setByte(i + startByte, value[i]); 62911284Sandreas.hansson@arm.com } 63011284Sandreas.hansson@arm.com 63111284Sandreas.hansson@arm.com // entry = lookup(line_address(addr)); 63211284Sandreas.hansson@arm.com} 63311284Sandreas.hansson@arm.com 63411284Sandreas.hansson@arm.com#endif //CACHEMEMORY_H 63511284Sandreas.hansson@arm.com 63611284Sandreas.hansson@arm.com