CacheMemory.hh revision 6374
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 "mem/ruby/profiler/CacheProfiler.hh" 5611051Sandreas.hansson@arm.com#include "mem/protocol/CacheMsg.hh" 5711051Sandreas.hansson@arm.com#include <vector> 5811051Sandreas.hansson@arm.com 5911051Sandreas.hansson@arm.comclass CacheMemory { 6011051Sandreas.hansson@arm.compublic: 6111051Sandreas.hansson@arm.com 6211051Sandreas.hansson@arm.com // Constructors 6311051Sandreas.hansson@arm.com CacheMemory(const string & name); 6411051Sandreas.hansson@arm.com void init(const vector<string> & argv); 6511051Sandreas.hansson@arm.com 6611053Sandreas.hansson@arm.com // Destructor 6711053Sandreas.hansson@arm.com ~CacheMemory(); 6811051Sandreas.hansson@arm.com 6911051Sandreas.hansson@arm.com // factory 7011051Sandreas.hansson@arm.com // static CacheMemory* createCache(int level, int num, char split_type, AbstractCacheEntry* (*entry_factory)()); 7111197Sandreas.hansson@arm.com // static CacheMemory* getCache(int cache_id); 7211197Sandreas.hansson@arm.com 7311199Sandreas.hansson@arm.com // Public Methods 7411197Sandreas.hansson@arm.com void printConfig(ostream& out); 7511197Sandreas.hansson@arm.com 7611197Sandreas.hansson@arm.com // perform a cache access and see if we hit or not. Return true on a hit. 7711051Sandreas.hansson@arm.com bool tryCacheAccess(const Address& address, CacheRequestType type, DataBlock*& data_ptr); 7811051Sandreas.hansson@arm.com 7911051Sandreas.hansson@arm.com // similar to above, but doesn't require full access check 8011051Sandreas.hansson@arm.com bool testCacheAccess(const Address& address, CacheRequestType type, DataBlock*& data_ptr); 8111051Sandreas.hansson@arm.com 8211051Sandreas.hansson@arm.com // tests to see if an address is present in the cache 8311051Sandreas.hansson@arm.com bool isTagPresent(const Address& address) const; 8411051Sandreas.hansson@arm.com 8511051Sandreas.hansson@arm.com // Returns true if there is: 8611051Sandreas.hansson@arm.com // a) a tag match on this address or there is 8711051Sandreas.hansson@arm.com // b) an unused line in the same cache "way" 8811051Sandreas.hansson@arm.com bool cacheAvail(const Address& address) const; 8911051Sandreas.hansson@arm.com 9011051Sandreas.hansson@arm.com // find an unused entry and sets the tag appropriate for the address 9111051Sandreas.hansson@arm.com void allocate(const Address& address, AbstractCacheEntry* new_entry); 9211051Sandreas.hansson@arm.com 9311051Sandreas.hansson@arm.com // Explicitly free up this address 9411051Sandreas.hansson@arm.com void deallocate(const Address& address); 9511051Sandreas.hansson@arm.com 9611051Sandreas.hansson@arm.com // Returns with the physical address of the conflicting cache line 9711051Sandreas.hansson@arm.com Address cacheProbe(const Address& address) const; 9811051Sandreas.hansson@arm.com 9911051Sandreas.hansson@arm.com // looks an address up in the cache 10011051Sandreas.hansson@arm.com AbstractCacheEntry& lookup(const Address& address); 10111051Sandreas.hansson@arm.com const AbstractCacheEntry& lookup(const Address& address) const; 10211051Sandreas.hansson@arm.com 10311051Sandreas.hansson@arm.com // Get/Set permission of cache block 10411051Sandreas.hansson@arm.com AccessPermission getPermission(const Address& address) const; 10511051Sandreas.hansson@arm.com void changePermission(const Address& address, AccessPermission new_perm); 10611051Sandreas.hansson@arm.com 10711051Sandreas.hansson@arm.com int getLatency() const { return m_latency; } 10811051Sandreas.hansson@arm.com 10911051Sandreas.hansson@arm.com // Hook for checkpointing the contents of the cache 11011051Sandreas.hansson@arm.com void recordCacheContents(CacheRecorder& tr) const; 11111051Sandreas.hansson@arm.com void setAsInstructionCache(bool is_icache) { m_is_instruction_only_cache = is_icache; } 11211051Sandreas.hansson@arm.com 11311051Sandreas.hansson@arm.com // Set this address to most recently used 11411051Sandreas.hansson@arm.com void setMRU(const Address& address); 11511051Sandreas.hansson@arm.com 11611051Sandreas.hansson@arm.com void profileMiss(const CacheMsg & msg); 11711051Sandreas.hansson@arm.com 11811051Sandreas.hansson@arm.com void getMemoryValue(const Address& addr, char* value, 11911051Sandreas.hansson@arm.com unsigned int size_in_bytes ); 12011051Sandreas.hansson@arm.com void setMemoryValue(const Address& addr, char* value, 12111051Sandreas.hansson@arm.com unsigned int size_in_bytes ); 12211051Sandreas.hansson@arm.com 12311051Sandreas.hansson@arm.com void setLocked (const Address& addr, int context); 12411051Sandreas.hansson@arm.com void clearLocked (const Address& addr); 12511051Sandreas.hansson@arm.com bool isLocked (const Address& addr, int context); 12611051Sandreas.hansson@arm.com // Print cache contents 12711051Sandreas.hansson@arm.com void print(ostream& out) const; 12811051Sandreas.hansson@arm.com void printData(ostream& out) const; 12911051Sandreas.hansson@arm.com 13011051Sandreas.hansson@arm.com void printStats(ostream& out) const; 13111051Sandreas.hansson@arm.com 13211051Sandreas.hansson@arm.comprivate: 13311051Sandreas.hansson@arm.com // Private Methods 13411051Sandreas.hansson@arm.com 13511051Sandreas.hansson@arm.com // convert a Address to its location in the cache 13611051Sandreas.hansson@arm.com Index addressToCacheSet(const Address& address) const; 13711051Sandreas.hansson@arm.com 13811051Sandreas.hansson@arm.com // Given a cache tag: returns the index of the tag in a set. 13911051Sandreas.hansson@arm.com // returns -1 if the tag is not found. 14011051Sandreas.hansson@arm.com int findTagInSet(Index line, const Address& tag) const; 14111051Sandreas.hansson@arm.com int findTagInSetIgnorePermissions(Index cacheSet, const Address& tag) const; 14211051Sandreas.hansson@arm.com 14311051Sandreas.hansson@arm.com // Private copy constructor and assignment operator 14411051Sandreas.hansson@arm.com CacheMemory(const CacheMemory& obj); 14511051Sandreas.hansson@arm.com CacheMemory& operator=(const CacheMemory& obj); 14611051Sandreas.hansson@arm.com 14711051Sandreas.hansson@arm.comprivate: 14811051Sandreas.hansson@arm.com const string m_cache_name; 14911051Sandreas.hansson@arm.com AbstractController* m_controller; 15011051Sandreas.hansson@arm.com int m_latency; 15111051Sandreas.hansson@arm.com 15211051Sandreas.hansson@arm.com // Data Members (m_prefix) 15311051Sandreas.hansson@arm.com bool m_is_instruction_only_cache; 15411051Sandreas.hansson@arm.com bool m_is_data_only_cache; 15511051Sandreas.hansson@arm.com 15611051Sandreas.hansson@arm.com // The first index is the # of cache lines. 15711051Sandreas.hansson@arm.com // The second index is the the amount associativity. 15811051Sandreas.hansson@arm.com Vector<Vector<AbstractCacheEntry*> > m_cache; 15911051Sandreas.hansson@arm.com Vector<Vector<int> > m_locked; 16011051Sandreas.hansson@arm.com 16111051Sandreas.hansson@arm.com AbstractReplacementPolicy *m_replacementPolicy_ptr; 16211051Sandreas.hansson@arm.com 16311051Sandreas.hansson@arm.com CacheProfiler* m_profiler_ptr; 16411051Sandreas.hansson@arm.com 16511051Sandreas.hansson@arm.com int m_cache_num_sets; 16611051Sandreas.hansson@arm.com int m_cache_num_set_bits; 16711051Sandreas.hansson@arm.com int m_cache_assoc; 16811051Sandreas.hansson@arm.com 16911051Sandreas.hansson@arm.com static Vector< CacheMemory* > m_all_caches; 17011051Sandreas.hansson@arm.com}; 17111051Sandreas.hansson@arm.com 17211051Sandreas.hansson@arm.com// Output operator declaration 17311051Sandreas.hansson@arm.com//ostream& operator<<(ostream& out, const CacheMemory<ENTRY>& obj); 17411051Sandreas.hansson@arm.com 17511051Sandreas.hansson@arm.com// ******************* Definitions ******************* 17611051Sandreas.hansson@arm.com 17711051Sandreas.hansson@arm.com// Output operator definition 17811051Sandreas.hansson@arm.cominline 17911051Sandreas.hansson@arm.comostream& operator<<(ostream& out, const CacheMemory& obj) 18011051Sandreas.hansson@arm.com{ 18111051Sandreas.hansson@arm.com obj.print(out); 18211051Sandreas.hansson@arm.com out << flush; 18311051Sandreas.hansson@arm.com return out; 18411051Sandreas.hansson@arm.com} 18511051Sandreas.hansson@arm.com 18611051Sandreas.hansson@arm.com 18711051Sandreas.hansson@arm.com// **************************************************************** 18811051Sandreas.hansson@arm.com 18911051Sandreas.hansson@arm.cominline 19011051Sandreas.hansson@arm.comCacheMemory::CacheMemory(const string & name) 19111051Sandreas.hansson@arm.com : m_cache_name(name) 19211051Sandreas.hansson@arm.com{ 19311051Sandreas.hansson@arm.com m_profiler_ptr = new CacheProfiler(name); 19411051Sandreas.hansson@arm.com} 19511051Sandreas.hansson@arm.com 19611051Sandreas.hansson@arm.cominline 19711051Sandreas.hansson@arm.comvoid CacheMemory::init(const vector<string> & argv) 19811051Sandreas.hansson@arm.com{ 19911051Sandreas.hansson@arm.com int cache_size = 0; 20011051Sandreas.hansson@arm.com string policy; 20111051Sandreas.hansson@arm.com 20211051Sandreas.hansson@arm.com m_controller = NULL; 20311051Sandreas.hansson@arm.com for (uint32 i=0; i<argv.size(); i+=2) { 20411051Sandreas.hansson@arm.com if (argv[i] == "size_kb") { 20511051Sandreas.hansson@arm.com cache_size = atoi(argv[i+1].c_str()); 20611197Sandreas.hansson@arm.com } else if (argv[i] == "latency") { 20711197Sandreas.hansson@arm.com m_latency = atoi(argv[i+1].c_str()); 20811197Sandreas.hansson@arm.com } else if (argv[i] == "assoc") { 20911197Sandreas.hansson@arm.com m_cache_assoc = atoi(argv[i+1].c_str()); 21011051Sandreas.hansson@arm.com } else if (argv[i] == "replacement_policy") { 21111051Sandreas.hansson@arm.com policy = argv[i+1]; 21211051Sandreas.hansson@arm.com } else if (argv[i] == "controller") { 21311051Sandreas.hansson@arm.com m_controller = RubySystem::getController(argv[i+1]); 21411051Sandreas.hansson@arm.com } else { 21511051Sandreas.hansson@arm.com cerr << "WARNING: CacheMemory: Unknown configuration parameter: " << argv[i] << endl; 21611051Sandreas.hansson@arm.com } 21711051Sandreas.hansson@arm.com } 21811051Sandreas.hansson@arm.com 21911051Sandreas.hansson@arm.com m_cache_num_sets = cache_size / m_cache_assoc; 22011051Sandreas.hansson@arm.com m_cache_num_set_bits = log_int(m_cache_num_sets); 22111051Sandreas.hansson@arm.com 22211051Sandreas.hansson@arm.com if(policy == "PSEUDO_LRU") 22311051Sandreas.hansson@arm.com m_replacementPolicy_ptr = new PseudoLRUPolicy(m_cache_num_sets, m_cache_assoc); 22411051Sandreas.hansson@arm.com else if (policy == "LRU") 22511051Sandreas.hansson@arm.com m_replacementPolicy_ptr = new LRUPolicy(m_cache_num_sets, m_cache_assoc); 22611051Sandreas.hansson@arm.com else 22711051Sandreas.hansson@arm.com assert(false); 22811197Sandreas.hansson@arm.com 22911197Sandreas.hansson@arm.com m_cache.setSize(m_cache_num_sets); 23011051Sandreas.hansson@arm.com m_locked.setSize(m_cache_num_sets); 23111197Sandreas.hansson@arm.com for (int i = 0; i < m_cache_num_sets; i++) { 23211197Sandreas.hansson@arm.com m_cache[i].setSize(m_cache_assoc); 23311197Sandreas.hansson@arm.com m_locked[i].setSize(m_cache_assoc); 23411197Sandreas.hansson@arm.com for (int j = 0; j < m_cache_assoc; j++) { 23511197Sandreas.hansson@arm.com m_cache[i][j] = NULL; 23611197Sandreas.hansson@arm.com m_locked[i][j] = -1; 23711197Sandreas.hansson@arm.com } 23811197Sandreas.hansson@arm.com } 23911197Sandreas.hansson@arm.com} 24011197Sandreas.hansson@arm.com 24111197Sandreas.hansson@arm.cominline 24211197Sandreas.hansson@arm.comCacheMemory::~CacheMemory() 24311197Sandreas.hansson@arm.com{ 24411197Sandreas.hansson@arm.com if(m_replacementPolicy_ptr != NULL) 24511051Sandreas.hansson@arm.com delete m_replacementPolicy_ptr; 24611197Sandreas.hansson@arm.com} 24711197Sandreas.hansson@arm.com 24811197Sandreas.hansson@arm.cominline 24911197Sandreas.hansson@arm.comvoid CacheMemory::printConfig(ostream& out) 25011197Sandreas.hansson@arm.com{ 25111197Sandreas.hansson@arm.com out << "Cache config: " << m_cache_name << endl; 25211051Sandreas.hansson@arm.com if (m_controller != NULL) 25311051Sandreas.hansson@arm.com out << " controller: " << m_controller->getName() << endl; 25411051Sandreas.hansson@arm.com out << " cache_associativity: " << m_cache_assoc << endl; 25511051Sandreas.hansson@arm.com out << " num_cache_sets_bits: " << m_cache_num_set_bits << endl; 25611051Sandreas.hansson@arm.com const int cache_num_sets = 1 << m_cache_num_set_bits; 25711051Sandreas.hansson@arm.com out << " num_cache_sets: " << cache_num_sets << endl; 25811051Sandreas.hansson@arm.com out << " cache_set_size_bytes: " << cache_num_sets * RubySystem::getBlockSizeBytes() << endl; 25911051Sandreas.hansson@arm.com out << " cache_set_size_Kbytes: " 26011051Sandreas.hansson@arm.com << double(cache_num_sets * RubySystem::getBlockSizeBytes()) / (1<<10) << endl; 26111051Sandreas.hansson@arm.com out << " cache_set_size_Mbytes: " 26211051Sandreas.hansson@arm.com << double(cache_num_sets * RubySystem::getBlockSizeBytes()) / (1<<20) << endl; 26311051Sandreas.hansson@arm.com out << " cache_size_bytes: " 26411051Sandreas.hansson@arm.com << cache_num_sets * RubySystem::getBlockSizeBytes() * m_cache_assoc << endl; 26511051Sandreas.hansson@arm.com out << " cache_size_Kbytes: " 26611051Sandreas.hansson@arm.com << double(cache_num_sets * RubySystem::getBlockSizeBytes() * m_cache_assoc) / (1<<10) << endl; 26711051Sandreas.hansson@arm.com out << " cache_size_Mbytes: " 26811051Sandreas.hansson@arm.com << double(cache_num_sets * RubySystem::getBlockSizeBytes() * m_cache_assoc) / (1<<20) << endl; 26911051Sandreas.hansson@arm.com} 27011197Sandreas.hansson@arm.com 27111197Sandreas.hansson@arm.com// PRIVATE METHODS 27211197Sandreas.hansson@arm.com 27311197Sandreas.hansson@arm.com// convert a Address to its location in the cache 27411051Sandreas.hansson@arm.cominline 27511051Sandreas.hansson@arm.comIndex CacheMemory::addressToCacheSet(const Address& address) const 27611051Sandreas.hansson@arm.com{ 27711051Sandreas.hansson@arm.com assert(address == line_address(address)); 27811051Sandreas.hansson@arm.com return address.bitSelect(RubySystem::getBlockSizeBits(), RubySystem::getBlockSizeBits() + m_cache_num_set_bits-1); 27911051Sandreas.hansson@arm.com} 28011051Sandreas.hansson@arm.com 28111051Sandreas.hansson@arm.com// Given a cache index: returns the index of the tag in a set. 28211051Sandreas.hansson@arm.com// returns -1 if the tag is not found. 28311051Sandreas.hansson@arm.cominline 28411051Sandreas.hansson@arm.comint CacheMemory::findTagInSet(Index cacheSet, const Address& tag) const 28511051Sandreas.hansson@arm.com{ 28611051Sandreas.hansson@arm.com assert(tag == line_address(tag)); 28711051Sandreas.hansson@arm.com // search the set for the tags 28811051Sandreas.hansson@arm.com for (int i=0; i < m_cache_assoc; i++) { 28911051Sandreas.hansson@arm.com if ((m_cache[cacheSet][i] != NULL) && 29011051Sandreas.hansson@arm.com (m_cache[cacheSet][i]->m_Address == tag) && 29111051Sandreas.hansson@arm.com (m_cache[cacheSet][i]->m_Permission != AccessPermission_NotPresent)) { 29211051Sandreas.hansson@arm.com return i; 29311051Sandreas.hansson@arm.com } 29411051Sandreas.hansson@arm.com } 29511051Sandreas.hansson@arm.com return -1; // Not found 29611051Sandreas.hansson@arm.com} 29711051Sandreas.hansson@arm.com 29811051Sandreas.hansson@arm.com// Given a cache index: returns the index of the tag in a set. 29911051Sandreas.hansson@arm.com// returns -1 if the tag is not found. 30011051Sandreas.hansson@arm.cominline 30111051Sandreas.hansson@arm.comint CacheMemory::findTagInSetIgnorePermissions(Index cacheSet, const Address& tag) const 30211051Sandreas.hansson@arm.com{ 30311051Sandreas.hansson@arm.com assert(tag == line_address(tag)); 30411051Sandreas.hansson@arm.com // search the set for the tags 30511051Sandreas.hansson@arm.com for (int i=0; i < m_cache_assoc; i++) { 30611051Sandreas.hansson@arm.com if (m_cache[cacheSet][i] != NULL && m_cache[cacheSet][i]->m_Address == tag) 30711051Sandreas.hansson@arm.com return i; 30811051Sandreas.hansson@arm.com } 30911051Sandreas.hansson@arm.com return -1; // Not found 31011051Sandreas.hansson@arm.com} 31111051Sandreas.hansson@arm.com 31211051Sandreas.hansson@arm.com// PUBLIC METHODS 31311051Sandreas.hansson@arm.cominline 31411051Sandreas.hansson@arm.combool CacheMemory::tryCacheAccess(const Address& address, 31511051Sandreas.hansson@arm.com CacheRequestType type, 31611051Sandreas.hansson@arm.com DataBlock*& data_ptr) 31711051Sandreas.hansson@arm.com{ 31811051Sandreas.hansson@arm.com assert(address == line_address(address)); 31911051Sandreas.hansson@arm.com DEBUG_EXPR(CACHE_COMP, HighPrio, address); 32011051Sandreas.hansson@arm.com Index cacheSet = addressToCacheSet(address); 32111199Sandreas.hansson@arm.com int loc = findTagInSet(cacheSet, address); 32211051Sandreas.hansson@arm.com if(loc != -1){ // Do we even have a tag match? 32311051Sandreas.hansson@arm.com AbstractCacheEntry* entry = m_cache[cacheSet][loc]; 32411051Sandreas.hansson@arm.com m_replacementPolicy_ptr->touch(cacheSet, loc, g_eventQueue_ptr->getTime()); 32511051Sandreas.hansson@arm.com data_ptr = &(entry->getDataBlk()); 32611051Sandreas.hansson@arm.com 32711051Sandreas.hansson@arm.com if(entry->m_Permission == AccessPermission_Read_Write) { 32811051Sandreas.hansson@arm.com return true; 32911051Sandreas.hansson@arm.com } 33011051Sandreas.hansson@arm.com if ((entry->m_Permission == AccessPermission_Read_Only) && 33111051Sandreas.hansson@arm.com (type == CacheRequestType_LD || type == CacheRequestType_IFETCH)) { 33211051Sandreas.hansson@arm.com return true; 33311051Sandreas.hansson@arm.com } 33411051Sandreas.hansson@arm.com // The line must not be accessible 33511051Sandreas.hansson@arm.com } 33611051Sandreas.hansson@arm.com data_ptr = NULL; 33711051Sandreas.hansson@arm.com return false; 33811051Sandreas.hansson@arm.com} 33911051Sandreas.hansson@arm.com 34011051Sandreas.hansson@arm.cominline 34111051Sandreas.hansson@arm.combool CacheMemory::testCacheAccess(const Address& address, 34211051Sandreas.hansson@arm.com CacheRequestType type, 34311051Sandreas.hansson@arm.com DataBlock*& data_ptr) 34411051Sandreas.hansson@arm.com{ 34511051Sandreas.hansson@arm.com assert(address == line_address(address)); 34611051Sandreas.hansson@arm.com DEBUG_EXPR(CACHE_COMP, HighPrio, address); 34711199Sandreas.hansson@arm.com Index cacheSet = addressToCacheSet(address); 34811051Sandreas.hansson@arm.com int loc = findTagInSet(cacheSet, address); 34911051Sandreas.hansson@arm.com if(loc != -1){ // Do we even have a tag match? 35011051Sandreas.hansson@arm.com AbstractCacheEntry* entry = m_cache[cacheSet][loc]; 35111051Sandreas.hansson@arm.com m_replacementPolicy_ptr->touch(cacheSet, loc, g_eventQueue_ptr->getTime()); 35211051Sandreas.hansson@arm.com data_ptr = &(entry->getDataBlk()); 35311051Sandreas.hansson@arm.com 35411051Sandreas.hansson@arm.com return (m_cache[cacheSet][loc]->m_Permission != AccessPermission_NotPresent); 35511051Sandreas.hansson@arm.com } 35611051Sandreas.hansson@arm.com data_ptr = NULL; 35711051Sandreas.hansson@arm.com return false; 35811051Sandreas.hansson@arm.com} 35911051Sandreas.hansson@arm.com 36011199Sandreas.hansson@arm.com// tests to see if an address is present in the cache 36111199Sandreas.hansson@arm.cominline 36211199Sandreas.hansson@arm.combool CacheMemory::isTagPresent(const Address& address) const 36311199Sandreas.hansson@arm.com{ 36411199Sandreas.hansson@arm.com assert(address == line_address(address)); 36511199Sandreas.hansson@arm.com Index cacheSet = addressToCacheSet(address); 36611199Sandreas.hansson@arm.com int location = findTagInSet(cacheSet, address); 36711199Sandreas.hansson@arm.com 36811199Sandreas.hansson@arm.com if (location == -1) { 36911199Sandreas.hansson@arm.com // We didn't find the tag 37011199Sandreas.hansson@arm.com DEBUG_EXPR(CACHE_COMP, LowPrio, address); 37111199Sandreas.hansson@arm.com DEBUG_MSG(CACHE_COMP, LowPrio, "No tag match"); 37211199Sandreas.hansson@arm.com return false; 37311199Sandreas.hansson@arm.com } 37411199Sandreas.hansson@arm.com DEBUG_EXPR(CACHE_COMP, LowPrio, address); 37511199Sandreas.hansson@arm.com DEBUG_MSG(CACHE_COMP, LowPrio, "found"); 37611199Sandreas.hansson@arm.com return true; 37711199Sandreas.hansson@arm.com} 37811199Sandreas.hansson@arm.com 37911199Sandreas.hansson@arm.com// Returns true if there is: 38011199Sandreas.hansson@arm.com// a) a tag match on this address or there is 38111199Sandreas.hansson@arm.com// b) an unused line in the same cache "way" 38211199Sandreas.hansson@arm.cominline 38311199Sandreas.hansson@arm.combool CacheMemory::cacheAvail(const Address& address) const 38411051Sandreas.hansson@arm.com{ 38511051Sandreas.hansson@arm.com assert(address == line_address(address)); 38611051Sandreas.hansson@arm.com 38711051Sandreas.hansson@arm.com Index cacheSet = addressToCacheSet(address); 38811051Sandreas.hansson@arm.com 38911199Sandreas.hansson@arm.com for (int i=0; i < m_cache_assoc; i++) { 39011051Sandreas.hansson@arm.com AbstractCacheEntry* entry = m_cache[cacheSet][i]; 39111199Sandreas.hansson@arm.com if (entry != NULL) { 39211199Sandreas.hansson@arm.com if (entry->m_Address == address || // Already in the cache 39311199Sandreas.hansson@arm.com entry->m_Permission == AccessPermission_NotPresent) { // We found an empty entry 39411199Sandreas.hansson@arm.com return true; 39511199Sandreas.hansson@arm.com } 39611199Sandreas.hansson@arm.com } else { 39711199Sandreas.hansson@arm.com return true; 39811199Sandreas.hansson@arm.com } 39911199Sandreas.hansson@arm.com } 40011199Sandreas.hansson@arm.com return false; 40111199Sandreas.hansson@arm.com} 40211199Sandreas.hansson@arm.com 40311051Sandreas.hansson@arm.cominline 40411051Sandreas.hansson@arm.comvoid CacheMemory::allocate(const Address& address, AbstractCacheEntry* entry) 40511051Sandreas.hansson@arm.com{ 40611051Sandreas.hansson@arm.com assert(address == line_address(address)); 40711051Sandreas.hansson@arm.com assert(!isTagPresent(address)); 40811051Sandreas.hansson@arm.com assert(cacheAvail(address)); 40911051Sandreas.hansson@arm.com DEBUG_EXPR(CACHE_COMP, HighPrio, address); 41011051Sandreas.hansson@arm.com 41111051Sandreas.hansson@arm.com // Find the first open slot 41211051Sandreas.hansson@arm.com Index cacheSet = addressToCacheSet(address); 41311051Sandreas.hansson@arm.com for (int i=0; i < m_cache_assoc; i++) { 41411051Sandreas.hansson@arm.com if (m_cache[cacheSet][i] == NULL || 41511051Sandreas.hansson@arm.com m_cache[cacheSet][i]->m_Permission == AccessPermission_NotPresent) { 41611051Sandreas.hansson@arm.com m_cache[cacheSet][i] = entry; // Init entry 41711051Sandreas.hansson@arm.com m_cache[cacheSet][i]->m_Address = address; 41811199Sandreas.hansson@arm.com m_cache[cacheSet][i]->m_Permission = AccessPermission_Invalid; 41911199Sandreas.hansson@arm.com m_locked[cacheSet][i] = -1; 42011199Sandreas.hansson@arm.com 42111199Sandreas.hansson@arm.com m_replacementPolicy_ptr->touch(cacheSet, i, g_eventQueue_ptr->getTime()); 42211199Sandreas.hansson@arm.com 42311051Sandreas.hansson@arm.com return; 42411051Sandreas.hansson@arm.com } 42511051Sandreas.hansson@arm.com } 42611051Sandreas.hansson@arm.com ERROR_MSG("Allocate didn't find an available entry"); 42711051Sandreas.hansson@arm.com} 42811051Sandreas.hansson@arm.com 42911051Sandreas.hansson@arm.cominline 43011051Sandreas.hansson@arm.comvoid CacheMemory::deallocate(const Address& address) 43111051Sandreas.hansson@arm.com{ 43211051Sandreas.hansson@arm.com assert(address == line_address(address)); 43311051Sandreas.hansson@arm.com assert(isTagPresent(address)); 43411051Sandreas.hansson@arm.com DEBUG_EXPR(CACHE_COMP, HighPrio, address); 43511051Sandreas.hansson@arm.com Index cacheSet = addressToCacheSet(address); 43611051Sandreas.hansson@arm.com int location = findTagInSet(cacheSet, address); 43711051Sandreas.hansson@arm.com if (location != -1){ 43811051Sandreas.hansson@arm.com delete m_cache[cacheSet][location]; 43911051Sandreas.hansson@arm.com m_cache[cacheSet][location] = NULL; 44011051Sandreas.hansson@arm.com m_locked[cacheSet][location] = -1; 44111051Sandreas.hansson@arm.com } 44211051Sandreas.hansson@arm.com} 44311051Sandreas.hansson@arm.com 44411051Sandreas.hansson@arm.com// Returns with the physical address of the conflicting cache line 44511051Sandreas.hansson@arm.cominline 44611051Sandreas.hansson@arm.comAddress CacheMemory::cacheProbe(const Address& address) const 44711051Sandreas.hansson@arm.com{ 44811051Sandreas.hansson@arm.com assert(address == line_address(address)); 44911051Sandreas.hansson@arm.com assert(!cacheAvail(address)); 45011051Sandreas.hansson@arm.com 45111051Sandreas.hansson@arm.com Index cacheSet = addressToCacheSet(address); 45211051Sandreas.hansson@arm.com return m_cache[cacheSet][m_replacementPolicy_ptr->getVictim(cacheSet)]->m_Address; 45311051Sandreas.hansson@arm.com} 45411051Sandreas.hansson@arm.com 45511051Sandreas.hansson@arm.com// looks an address up in the cache 45611051Sandreas.hansson@arm.cominline 45711051Sandreas.hansson@arm.comAbstractCacheEntry& CacheMemory::lookup(const Address& address) 45811051Sandreas.hansson@arm.com{ 45911051Sandreas.hansson@arm.com assert(address == line_address(address)); 46011051Sandreas.hansson@arm.com Index cacheSet = addressToCacheSet(address); 46111051Sandreas.hansson@arm.com int loc = findTagInSet(cacheSet, address); 46211051Sandreas.hansson@arm.com assert(loc != -1); 46311051Sandreas.hansson@arm.com return *m_cache[cacheSet][loc]; 46411051Sandreas.hansson@arm.com} 46511051Sandreas.hansson@arm.com 46611051Sandreas.hansson@arm.com// looks an address up in the cache 46711051Sandreas.hansson@arm.cominline 46811051Sandreas.hansson@arm.comconst AbstractCacheEntry& CacheMemory::lookup(const Address& address) const 46911051Sandreas.hansson@arm.com{ 47011051Sandreas.hansson@arm.com assert(address == line_address(address)); 47111051Sandreas.hansson@arm.com Index cacheSet = addressToCacheSet(address); 47211051Sandreas.hansson@arm.com int loc = findTagInSet(cacheSet, address); 47311051Sandreas.hansson@arm.com assert(loc != -1); 47411051Sandreas.hansson@arm.com return *m_cache[cacheSet][loc]; 47511051Sandreas.hansson@arm.com} 47611051Sandreas.hansson@arm.com 47711051Sandreas.hansson@arm.cominline 47811051Sandreas.hansson@arm.comAccessPermission CacheMemory::getPermission(const Address& address) const 47911051Sandreas.hansson@arm.com{ 48011051Sandreas.hansson@arm.com assert(address == line_address(address)); 48111051Sandreas.hansson@arm.com return lookup(address).m_Permission; 48211051Sandreas.hansson@arm.com} 48311051Sandreas.hansson@arm.com 48411051Sandreas.hansson@arm.cominline 48511051Sandreas.hansson@arm.comvoid CacheMemory::changePermission(const Address& address, AccessPermission new_perm) 48611051Sandreas.hansson@arm.com{ 48711051Sandreas.hansson@arm.com assert(address == line_address(address)); 48811051Sandreas.hansson@arm.com lookup(address).m_Permission = new_perm; 48911051Sandreas.hansson@arm.com Index cacheSet = addressToCacheSet(address); 49011051Sandreas.hansson@arm.com int loc = findTagInSet(cacheSet, address); 49111051Sandreas.hansson@arm.com m_locked[cacheSet][loc] = -1; 49211051Sandreas.hansson@arm.com assert(getPermission(address) == new_perm); 49311051Sandreas.hansson@arm.com} 49411199Sandreas.hansson@arm.com 49511199Sandreas.hansson@arm.com// Sets the most recently used bit for a cache block 49611199Sandreas.hansson@arm.cominline 49711199Sandreas.hansson@arm.comvoid CacheMemory::setMRU(const Address& address) 49811199Sandreas.hansson@arm.com{ 49911051Sandreas.hansson@arm.com Index cacheSet; 50011199Sandreas.hansson@arm.com 50111051Sandreas.hansson@arm.com cacheSet = addressToCacheSet(address); 50211051Sandreas.hansson@arm.com m_replacementPolicy_ptr->touch(cacheSet, 50311051Sandreas.hansson@arm.com findTagInSet(cacheSet, address), 50411051Sandreas.hansson@arm.com g_eventQueue_ptr->getTime()); 50511051Sandreas.hansson@arm.com} 50611051Sandreas.hansson@arm.com 50711051Sandreas.hansson@arm.cominline 50811051Sandreas.hansson@arm.comvoid CacheMemory::profileMiss(const CacheMsg & msg) 50911051Sandreas.hansson@arm.com{ 51011051Sandreas.hansson@arm.com m_profiler_ptr->addStatSample(msg.getType(), msg.getAccessMode(), 51111051Sandreas.hansson@arm.com msg.getSize(), msg.getPrefetch()); 51211051Sandreas.hansson@arm.com} 51311051Sandreas.hansson@arm.com 51411051Sandreas.hansson@arm.cominline 51511051Sandreas.hansson@arm.comvoid CacheMemory::recordCacheContents(CacheRecorder& tr) const 51611051Sandreas.hansson@arm.com{ 51711051Sandreas.hansson@arm.com for (int i = 0; i < m_cache_num_sets; i++) { 51811130Sali.jafri@arm.com for (int j = 0; j < m_cache_assoc; j++) { 51911130Sali.jafri@arm.com AccessPermission perm = m_cache[i][j]->m_Permission; 52011130Sali.jafri@arm.com CacheRequestType request_type = CacheRequestType_NULL; 52111130Sali.jafri@arm.com if (perm == AccessPermission_Read_Only) { 52211130Sali.jafri@arm.com if (m_is_instruction_only_cache) { 52311130Sali.jafri@arm.com request_type = CacheRequestType_IFETCH; 52411130Sali.jafri@arm.com } else { 52511130Sali.jafri@arm.com request_type = CacheRequestType_LD; 52611130Sali.jafri@arm.com } 52711199Sandreas.hansson@arm.com } else if (perm == AccessPermission_Read_Write) { 52811130Sali.jafri@arm.com request_type = CacheRequestType_ST; 52911130Sali.jafri@arm.com } 53011130Sali.jafri@arm.com 53111130Sali.jafri@arm.com if (request_type != CacheRequestType_NULL) { 53211130Sali.jafri@arm.com // tr.addRecord(m_chip_ptr->getID(), m_cache[i][j].m_Address, 53311130Sali.jafri@arm.com // Address(0), request_type, m_replacementPolicy_ptr->getLastAccess(i, j)); 53411130Sali.jafri@arm.com } 53511130Sali.jafri@arm.com } 53611130Sali.jafri@arm.com } 53711130Sali.jafri@arm.com} 53811130Sali.jafri@arm.com 53911130Sali.jafri@arm.cominline 54011130Sali.jafri@arm.comvoid CacheMemory::print(ostream& out) const 54111130Sali.jafri@arm.com{ 54211130Sali.jafri@arm.com out << "Cache dump: " << m_cache_name << endl; 54311130Sali.jafri@arm.com for (int i = 0; i < m_cache_num_sets; i++) { 54411130Sali.jafri@arm.com for (int j = 0; j < m_cache_assoc; j++) { 54511130Sali.jafri@arm.com if (m_cache[i][j] != NULL) { 54611130Sali.jafri@arm.com out << " Index: " << i 54711130Sali.jafri@arm.com << " way: " << j 54811130Sali.jafri@arm.com << " entry: " << *m_cache[i][j] << endl; 54911130Sali.jafri@arm.com } else { 55011130Sali.jafri@arm.com out << " Index: " << i 55111051Sandreas.hansson@arm.com << " way: " << j 55211051Sandreas.hansson@arm.com << " entry: NULL" << endl; 55311051Sandreas.hansson@arm.com } 55411051Sandreas.hansson@arm.com } 55511051Sandreas.hansson@arm.com } 55611051Sandreas.hansson@arm.com} 55711051Sandreas.hansson@arm.com 55811051Sandreas.hansson@arm.cominline 55911051Sandreas.hansson@arm.comvoid CacheMemory::printData(ostream& out) const 56011051Sandreas.hansson@arm.com{ 56111051Sandreas.hansson@arm.com out << "printData() not supported" << endl; 56211051Sandreas.hansson@arm.com} 56311051Sandreas.hansson@arm.com 56411051Sandreas.hansson@arm.cominline 56511051Sandreas.hansson@arm.comvoid CacheMemory::printStats(ostream& out) const 56611051Sandreas.hansson@arm.com{ 56711051Sandreas.hansson@arm.com m_profiler_ptr->printStats(out); 56811051Sandreas.hansson@arm.com} 56911051Sandreas.hansson@arm.com 57011051Sandreas.hansson@arm.cominline 57111051Sandreas.hansson@arm.comvoid CacheMemory::getMemoryValue(const Address& addr, char* value, 57211051Sandreas.hansson@arm.com unsigned int size_in_bytes ){ 57311051Sandreas.hansson@arm.com AbstractCacheEntry& entry = lookup(line_address(addr)); 57411051Sandreas.hansson@arm.com unsigned int startByte = addr.getAddress() - line_address(addr).getAddress(); 57511051Sandreas.hansson@arm.com for(unsigned int i=0; i<size_in_bytes; ++i){ 57611051Sandreas.hansson@arm.com value[i] = entry.getDataBlk().getByte(i + startByte); 57711051Sandreas.hansson@arm.com } 57811051Sandreas.hansson@arm.com} 57911051Sandreas.hansson@arm.com 58011051Sandreas.hansson@arm.cominline 58111051Sandreas.hansson@arm.comvoid CacheMemory::setMemoryValue(const Address& addr, char* value, 58211051Sandreas.hansson@arm.com unsigned int size_in_bytes ){ 58311051Sandreas.hansson@arm.com AbstractCacheEntry& entry = lookup(line_address(addr)); 58411051Sandreas.hansson@arm.com unsigned int startByte = addr.getAddress() - line_address(addr).getAddress(); 58511051Sandreas.hansson@arm.com assert(size_in_bytes > 0); 58611051Sandreas.hansson@arm.com for(unsigned int i=0; i<size_in_bytes; ++i){ 58711051Sandreas.hansson@arm.com entry.getDataBlk().setByte(i + startByte, value[i]); 58811051Sandreas.hansson@arm.com } 58911051Sandreas.hansson@arm.com 59011051Sandreas.hansson@arm.com // entry = lookup(line_address(addr)); 59111051Sandreas.hansson@arm.com} 59211051Sandreas.hansson@arm.com 59311051Sandreas.hansson@arm.cominline 59411051Sandreas.hansson@arm.comvoid 59511051Sandreas.hansson@arm.comCacheMemory::setLocked(const Address& address, int context) 59611051Sandreas.hansson@arm.com{ 59711051Sandreas.hansson@arm.com assert(address == line_address(address)); 59811051Sandreas.hansson@arm.com Index cacheSet = addressToCacheSet(address); 59911051Sandreas.hansson@arm.com int loc = findTagInSet(cacheSet, address); 60011051Sandreas.hansson@arm.com assert(loc != -1); 60111051Sandreas.hansson@arm.com m_locked[cacheSet][loc] = context; 60211051Sandreas.hansson@arm.com} 60311051Sandreas.hansson@arm.com 60411051Sandreas.hansson@arm.cominline 60511051Sandreas.hansson@arm.comvoid 60611051Sandreas.hansson@arm.comCacheMemory::clearLocked(const Address& address) 60711051Sandreas.hansson@arm.com{ 60811051Sandreas.hansson@arm.com assert(address == line_address(address)); 60911051Sandreas.hansson@arm.com Index cacheSet = addressToCacheSet(address); 61011051Sandreas.hansson@arm.com int loc = findTagInSet(cacheSet, address); 61111051Sandreas.hansson@arm.com assert(loc != -1); 61211051Sandreas.hansson@arm.com m_locked[cacheSet][loc] = -1; 61311051Sandreas.hansson@arm.com} 61411051Sandreas.hansson@arm.com 61511051Sandreas.hansson@arm.cominline 61611051Sandreas.hansson@arm.combool 61711051Sandreas.hansson@arm.comCacheMemory::isLocked(const Address& address, int context) 61811051Sandreas.hansson@arm.com{ 61911051Sandreas.hansson@arm.com assert(address == line_address(address)); 62011051Sandreas.hansson@arm.com Index cacheSet = addressToCacheSet(address); 62111051Sandreas.hansson@arm.com int loc = findTagInSet(cacheSet, address); 62211051Sandreas.hansson@arm.com assert(loc != -1); 62311051Sandreas.hansson@arm.com return m_locked[cacheSet][loc] == context; 62411051Sandreas.hansson@arm.com} 62511051Sandreas.hansson@arm.com 62611051Sandreas.hansson@arm.com#endif //CACHEMEMORY_H 62711051Sandreas.hansson@arm.com 62811051Sandreas.hansson@arm.com