CacheMemory.hh revision 6285
12497SN/A/* 212780Snikos.nikoleris@arm.com * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood 38711SN/A * All rights reserved. 48711SN/A * 58711SN/A * Redistribution and use in source and binary forms, with or without 68711SN/A * modification, are permitted provided that the following conditions are 78711SN/A * met: redistributions of source code must retain the above copyright 88711SN/A * notice, this list of conditions and the following disclaimer; 98711SN/A * redistributions in binary form must reproduce the above copyright 108711SN/A * notice, this list of conditions and the following disclaimer in the 118711SN/A * documentation and/or other materials provided with the distribution; 128711SN/A * neither the name of the copyright holders nor the names of its 138711SN/A * contributors may be used to endorse or promote products derived from 142497SN/A * this software without specific prior written permission. 152497SN/A * 162497SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 172497SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 182497SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 192497SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 202497SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 212497SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 222497SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 232497SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 242497SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 252497SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 262497SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 272497SN/A */ 282497SN/A 292497SN/A/* 302497SN/A * CacheMemory.hh 312497SN/A * 322497SN/A * Description: 332497SN/A * 342497SN/A * $Id: CacheMemory.hh,v 3.7 2004/06/18 20:15:15 beckmann Exp $ 352497SN/A * 362497SN/A */ 372497SN/A 382497SN/A#ifndef CACHEMEMORY_H 392665SN/A#define CACHEMEMORY_H 402665SN/A 418715SN/A#include "mem/ruby/common/Global.hh" 428922SN/A#include "mem/protocol/AccessPermission.hh" 4312351Snikos.nikoleris@arm.com#include "mem/ruby/common/Address.hh" 442497SN/A#include "mem/ruby/recorder/CacheRecorder.hh" 452497SN/A#include "mem/protocol/CacheRequestType.hh" 462497SN/A#include "mem/gems_common/Vector.hh" 472982SN/A#include "mem/ruby/common/DataBlock.hh" 4810405Sandreas.hansson@arm.com#include "mem/protocol/MachineType.hh" 492497SN/A#include "mem/ruby/slicc_interface/RubySlicc_ComponentMapping.hh" 502497SN/A#include "mem/ruby/system/PseudoLRUPolicy.hh" 5111793Sbrandon.potter@amd.com#include "mem/ruby/system/LRUPolicy.hh" 5211793Sbrandon.potter@amd.com#include "mem/ruby/slicc_interface/AbstractCacheEntry.hh" 5312334Sgabeblack@google.com#include "mem/ruby/system/System.hh" 542548SN/A#include "mem/ruby/slicc_interface/AbstractController.hh" 5510405Sandreas.hansson@arm.com#include <vector> 5610405Sandreas.hansson@arm.com 579524SN/Aclass CacheMemory { 582497SN/Apublic: 5910405Sandreas.hansson@arm.com 6010719SMarco.Balboni@ARM.com // Constructors 6111334Sandreas.hansson@arm.com CacheMemory(const string & name); 6212341Snikos.nikoleris@arm.com void init(const vector<string> & argv); 6312341Snikos.nikoleris@arm.com 647523SN/A // Destructor 658851SN/A ~CacheMemory(); 668948SN/A 678948SN/A // factory 688851SN/A // static CacheMemory* createCache(int level, int num, char split_type, AbstractCacheEntry* (*entry_factory)()); 699095SN/A // static CacheMemory* getCache(int cache_id); 7010405Sandreas.hansson@arm.com 718922SN/A // Public Methods 729715SN/A void printConfig(ostream& out); 739715SN/A 7413808Sgabeblack@google.com // perform a cache access and see if we hit or not. Return true on a hit. 7513808Sgabeblack@google.com bool tryCacheAccess(const Address& address, CacheRequestType type, DataBlock*& data_ptr); 768851SN/A 778851SN/A // similar to above, but doesn't require full access check 788948SN/A bool testCacheAccess(const Address& address, CacheRequestType type, DataBlock*& data_ptr); 798948SN/A 808915SN/A // tests to see if an address is present in the cache 819031SN/A bool isTagPresent(const Address& address) const; 829095SN/A 8310405Sandreas.hansson@arm.com // Returns true if there is: 8413808Sgabeblack@google.com // a) a tag match on this address or there is 858922SN/A // b) an unused line in the same cache "way" 869715SN/A bool cacheAvail(const Address& address) const; 8713808Sgabeblack@google.com 8810713Sandreas.hansson@arm.com // find an unused entry and sets the tag appropriate for the address 8910713Sandreas.hansson@arm.com void allocate(const Address& address, AbstractCacheEntry* new_entry); 9010713Sandreas.hansson@arm.com 918915SN/A // Explicitly free up this address 928915SN/A void deallocate(const Address& address); 938948SN/A 948851SN/A // Returns with the physical address of the conflicting cache line 959095SN/A Address cacheProbe(const Address& address) const; 9610888Sandreas.hansson@arm.com 978922SN/A // looks an address up in the cache 989715SN/A AbstractCacheEntry& lookup(const Address& address); 999715SN/A const AbstractCacheEntry& lookup(const Address& address) const; 1009716SN/A 1018851SN/A // Get/Set permission of cache block 1027523SN/A AccessPermission getPermission(const Address& address) const; 1037523SN/A void changePermission(const Address& address, AccessPermission new_perm); 10410405Sandreas.hansson@arm.com 1059715SN/A int getLatency() const { return m_latency; } 10610405Sandreas.hansson@arm.com 10710405Sandreas.hansson@arm.com // Hook for checkpointing the contents of the cache 10810405Sandreas.hansson@arm.com void recordCacheContents(CacheRecorder& tr) const; 10910405Sandreas.hansson@arm.com void setAsInstructionCache(bool is_icache) { m_is_instruction_only_cache = is_icache; } 11010405Sandreas.hansson@arm.com 11110405Sandreas.hansson@arm.com // Set this address to most recently used 11210405Sandreas.hansson@arm.com void setMRU(const Address& address); 11310405Sandreas.hansson@arm.com 1149715SN/A void getMemoryValue(const Address& addr, char* value, 1159715SN/A unsigned int size_in_bytes ); 1162568SN/A void setMemoryValue(const Address& addr, char* value, 11710405Sandreas.hansson@arm.com unsigned int size_in_bytes ); 1182568SN/A 11910405Sandreas.hansson@arm.com // Print cache contents 1209278SN/A void print(ostream& out) const; 1218948SN/A void printData(ostream& out) const; 1228948SN/A 12310405Sandreas.hansson@arm.comprivate: 1249088SN/A // Private Methods 12510405Sandreas.hansson@arm.com 12610405Sandreas.hansson@arm.com // convert a Address to its location in the cache 12710405Sandreas.hansson@arm.com Index addressToCacheSet(const Address& address) const; 12810405Sandreas.hansson@arm.com 1298711SN/A // Given a cache tag: returns the index of the tag in a set. 1308711SN/A // returns -1 if the tag is not found. 1312568SN/A int findTagInSet(Index line, const Address& tag) const; 1329036SN/A int findTagInSetIgnorePermissions(Index cacheSet, const Address& tag) const; 13310405Sandreas.hansson@arm.com 13411133Sandreas.hansson@arm.com // Private copy constructor and assignment operator 13511133Sandreas.hansson@arm.com CacheMemory(const CacheMemory& obj); 13611133Sandreas.hansson@arm.com CacheMemory& operator=(const CacheMemory& obj); 13711133Sandreas.hansson@arm.com 13811133Sandreas.hansson@arm.comprivate: 1393244SN/A const string m_cache_name; 1403244SN/A AbstractController* m_controller; 1418948SN/A int m_latency; 14210405Sandreas.hansson@arm.com 1433244SN/A // Data Members (m_prefix) 1448975SN/A bool m_is_instruction_only_cache; 1459032SN/A bool m_is_data_only_cache; 1463244SN/A 1479091SN/A // The first index is the # of cache lines. 1489091SN/A // The second index is the the amount associativity. 14911284Sandreas.hansson@arm.com Vector<Vector<AbstractCacheEntry*> > m_cache; 15010656Sandreas.hansson@arm.com 15111284Sandreas.hansson@arm.com AbstractReplacementPolicy *m_replacementPolicy_ptr; 15211284Sandreas.hansson@arm.com 1539091SN/A int m_cache_num_sets; 15412780Snikos.nikoleris@arm.com int m_cache_num_set_bits; 15513856Sodanrc@yahoo.com.br int m_cache_assoc; 1569612SN/A 15710405Sandreas.hansson@arm.com static Vector< CacheMemory* > m_all_caches; 1589033SN/A}; 1599715SN/A/* 16011744Snikos.nikoleris@arm.cominline 16111744Snikos.nikoleris@arm.comCacheMemory* CacheMemory::getCache(int cache_id) 1623244SN/A{ 1633244SN/A assert(cache_id < RubyConfig::getNumberOfCaches()); 1643244SN/A if (m_all_caches[cache_id] == NULL) { 16511744Snikos.nikoleris@arm.com cerr << "ERROR: Tried to obtain CacheMemory that hasn't been created yet." << endl; 16611744Snikos.nikoleris@arm.com assert(0); 1675197SN/A } 1689712SN/A return m_all_caches[cache_id]; 1699712SN/A} 1709712SN/A 1719712SN/Ainline 1729712SN/ACacheMemory* CacheMemory::createCache(int level, int num, char split_type_c, AbstractCacheEntry* (*entry_factory)()) 17310719SMarco.Balboni@ARM.com{ 17410719SMarco.Balboni@ARM.com string split_type; 17510719SMarco.Balboni@ARM.com switch(split_type_c) { 17610719SMarco.Balboni@ARM.com case 'i': 17710719SMarco.Balboni@ARM.com split_type = "instruction"; break; 17810719SMarco.Balboni@ARM.com case 'd': 17910719SMarco.Balboni@ARM.com split_type = "data"; break; 18010719SMarco.Balboni@ARM.com default: 18110719SMarco.Balboni@ARM.com split_type = "unified"; break; 18210719SMarco.Balboni@ARM.com } 18310719SMarco.Balboni@ARM.com int cache_id = RubyConfig::getCacheIDFromParams(level, num, split_type); 1844912SN/A assert(cache_id < RubyConfig::getNumberOfCaches()); 18512346Snikos.nikoleris@arm.com if (m_all_caches.size() == 0) { 18612346Snikos.nikoleris@arm.com m_all_caches.setSize(RubyConfig::getNumberOfCaches()); 18712346Snikos.nikoleris@arm.com for (int i=0; i<m_all_caches.size(); i++) 18812346Snikos.nikoleris@arm.com m_all_caches[i] = NULL; 18912346Snikos.nikoleris@arm.com } 19012346Snikos.nikoleris@arm.com 19112345Snikos.nikoleris@arm.com string type = RubyConfig::getCacheType(cache_id); 19212345Snikos.nikoleris@arm.com if ( type == "SetAssociativeCache" ) { 19312345Snikos.nikoleris@arm.com m_all_caches[cache_id] = new CacheMemory(cache_id, entry_factory); 19411127Sandreas.hansson@arm.com } 19511127Sandreas.hansson@arm.com return m_all_caches[cache_id]; 19612351Snikos.nikoleris@arm.com} 19712351Snikos.nikoleris@arm.com*/ 19812351Snikos.nikoleris@arm.com// Output operator declaration 19912351Snikos.nikoleris@arm.com//ostream& operator<<(ostream& out, const CacheMemory<ENTRY>& obj); 20012351Snikos.nikoleris@arm.com 20112351Snikos.nikoleris@arm.com// ******************* Definitions ******************* 20212351Snikos.nikoleris@arm.com 20312351Snikos.nikoleris@arm.com// Output operator definition 20412351Snikos.nikoleris@arm.cominline 20512351Snikos.nikoleris@arm.comostream& operator<<(ostream& out, const CacheMemory& obj) 20612351Snikos.nikoleris@arm.com{ 20712351Snikos.nikoleris@arm.com obj.print(out); 20812351Snikos.nikoleris@arm.com out << flush; 20912351Snikos.nikoleris@arm.com return out; 21012351Snikos.nikoleris@arm.com} 21112351Snikos.nikoleris@arm.com 2128979SN/A 2138979SN/A// **************************************************************** 21410402SN/A 21510402SN/Ainline 21610402SN/ACacheMemory::CacheMemory(const string & name) 21711126Sandreas.hansson@arm.com : m_cache_name(name) 21811126Sandreas.hansson@arm.com{ 21911126Sandreas.hansson@arm.com} 22010719SMarco.Balboni@ARM.com 22111744Snikos.nikoleris@arm.cominline 22211744Snikos.nikoleris@arm.comvoid CacheMemory::init(const vector<string> & argv) 22311744Snikos.nikoleris@arm.com{ 22411196Sali.jafri@arm.com int cache_size = 0; 22511199Sandreas.hansson@arm.com string policy; 22611196Sali.jafri@arm.com 22711196Sali.jafri@arm.com m_controller = NULL; 22811196Sali.jafri@arm.com for (uint32 i=0; i<argv.size(); i+=2) { 22911196Sali.jafri@arm.com if (argv[i] == "size_kb") { 23011196Sali.jafri@arm.com cache_size = atoi(argv[i+1].c_str()); 23111196Sali.jafri@arm.com } else if (argv[i] == "latency") { 23211196Sali.jafri@arm.com m_latency = atoi(argv[i+1].c_str()); 23311196Sali.jafri@arm.com } else if (argv[i] == "assoc") { 23411196Sali.jafri@arm.com m_cache_assoc = atoi(argv[i+1].c_str()); 23511196Sali.jafri@arm.com } else if (argv[i] == "replacement_policy") { 23610402SN/A policy = argv[i+1]; 23710402SN/A } else if (argv[i] == "controller") { 23810402SN/A m_controller = RubySystem::getController(argv[i+1]); 23911127Sandreas.hansson@arm.com } else { 24011127Sandreas.hansson@arm.com cerr << "WARNING: CacheMemory: Unknown configuration parameter: " << argv[i] << endl; 24111127Sandreas.hansson@arm.com } 24211127Sandreas.hansson@arm.com } 2438979SN/A 2448948SN/A m_cache_num_sets = cache_size / m_cache_assoc; 24511334Sandreas.hansson@arm.com m_cache_num_set_bits = log_int(m_cache_num_sets); 24611334Sandreas.hansson@arm.com 24710883Sali.jafri@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 25211334Sandreas.hansson@arm.com assert(false); 2538915SN/A 25411334Sandreas.hansson@arm.com m_cache.setSize(m_cache_num_sets); 25511334Sandreas.hansson@arm.com for (int i = 0; i < m_cache_num_sets; i++) { 25611334Sandreas.hansson@arm.com m_cache[i].setSize(m_cache_assoc); 25711334Sandreas.hansson@arm.com for (int j = 0; j < m_cache_assoc; j++) { 25811544Snikos.nikoleris@arm.com m_cache[i][j] = NULL; 25911544Snikos.nikoleris@arm.com } 26011544Snikos.nikoleris@arm.com } 26111334Sandreas.hansson@arm.com} 26211744Snikos.nikoleris@arm.com/* 26311744Snikos.nikoleris@arm.cominline 26411334Sandreas.hansson@arm.comCacheMemory::CacheMemory(int cache_id, AbstractCacheEntry* (*entry_factory)()) 26511334Sandreas.hansson@arm.com{ 26611334Sandreas.hansson@arm.com string split_type; 26712346Snikos.nikoleris@arm.com 26811334Sandreas.hansson@arm.com m_cache_id = cache_id; 26911334Sandreas.hansson@arm.com m_entry_factory = entry_factory; 27011334Sandreas.hansson@arm.com 27111334Sandreas.hansson@arm.com m_cache_num_set_bits = RubyConfig::getNumberOfCacheSetBits(cache_id); 27211334Sandreas.hansson@arm.com m_cache_num_sets = RubyConfig::getNumberOfCacheSets(cache_id); 27311334Sandreas.hansson@arm.com m_cache_assoc = RubyConfig::getCacheAssoc(cache_id); 27411334Sandreas.hansson@arm.com split_type = RubyConfig::getCacheSplitType(cache_id); 27511334Sandreas.hansson@arm.com m_is_instruction_only_cache = m_is_data_only_cache = false; 27611334Sandreas.hansson@arm.com if (split_type == "instruction") 27712346Snikos.nikoleris@arm.com m_is_instruction_only_cache = true; 27812346Snikos.nikoleris@arm.com else if (split_type == "data") 27912346Snikos.nikoleris@arm.com m_is_data_only_cache = true; 28012346Snikos.nikoleris@arm.com else 28112346Snikos.nikoleris@arm.com assert(split_type == "unified"); 28212346Snikos.nikoleris@arm.com 28312346Snikos.nikoleris@arm.com if(RubyConfig::getCacheReplacementPolicy(cache_id) == "PSEUDO_LRU") 28411334Sandreas.hansson@arm.com m_replacementPolicy_ptr = new PseudoLRUPolicy(m_cache_num_sets, m_cache_assoc); 28511334Sandreas.hansson@arm.com else if(RubyConfig::getCacheReplacementPolicy(cache_id) == "LRU") 28611334Sandreas.hansson@arm.com m_replacementPolicy_ptr = new LRUPolicy(m_cache_num_sets, m_cache_assoc); 28711334Sandreas.hansson@arm.com else 28811334Sandreas.hansson@arm.com assert(false); 28911334Sandreas.hansson@arm.com 29011334Sandreas.hansson@arm.com m_cache.setSize(m_cache_num_sets); 29111334Sandreas.hansson@arm.com for (int i = 0; i < m_cache_num_sets; i++) { 29211334Sandreas.hansson@arm.com m_cache[i].setSize(m_cache_assoc); 29311334Sandreas.hansson@arm.com for (int j = 0; j < m_cache_assoc; j++) { 29411334Sandreas.hansson@arm.com m_cache[i][j] = m_entry_factory(); 29511334Sandreas.hansson@arm.com } 2968948SN/A } 29712345Snikos.nikoleris@arm.com} 29810402SN/A*/ 29911605Snikos.nikoleris@arm.cominline 30010402SN/ACacheMemory::~CacheMemory() 30110402SN/A{ 30210656Sandreas.hansson@arm.com if(m_replacementPolicy_ptr != NULL) 30310656Sandreas.hansson@arm.com delete m_replacementPolicy_ptr; 30411284Sandreas.hansson@arm.com} 30510656Sandreas.hansson@arm.com 30610656Sandreas.hansson@arm.cominline 30710719SMarco.Balboni@ARM.comvoid CacheMemory::printConfig(ostream& out) 30810719SMarco.Balboni@ARM.com{ 30910656Sandreas.hansson@arm.com out << "Cache config: " << m_cache_name << endl; 31011744Snikos.nikoleris@arm.com if (m_controller != NULL) 31111744Snikos.nikoleris@arm.com out << " controller: " << m_controller->getName() << endl; 31210656Sandreas.hansson@arm.com out << " cache_associativity: " << m_cache_assoc << endl; 31310656Sandreas.hansson@arm.com out << " num_cache_sets_bits: " << m_cache_num_set_bits << endl; 31410656Sandreas.hansson@arm.com const int cache_num_sets = 1 << m_cache_num_set_bits; 31510719SMarco.Balboni@ARM.com out << " num_cache_sets: " << cache_num_sets << endl; 3169091SN/A out << " cache_set_size_bytes: " << cache_num_sets * RubySystem::getBlockSizeBytes() << endl; 31710656Sandreas.hansson@arm.com out << " cache_set_size_Kbytes: " 31810656Sandreas.hansson@arm.com << double(cache_num_sets * RubySystem::getBlockSizeBytes()) / (1<<10) << endl; 31910656Sandreas.hansson@arm.com out << " cache_set_size_Mbytes: " 32010656Sandreas.hansson@arm.com << double(cache_num_sets * RubySystem::getBlockSizeBytes()) / (1<<20) << endl; 32110656Sandreas.hansson@arm.com out << " cache_size_bytes: " 32210656Sandreas.hansson@arm.com << cache_num_sets * RubySystem::getBlockSizeBytes() * m_cache_assoc << endl; 32310656Sandreas.hansson@arm.com out << " cache_size_Kbytes: " 32410656Sandreas.hansson@arm.com << double(cache_num_sets * RubySystem::getBlockSizeBytes() * m_cache_assoc) / (1<<10) << endl; 32510656Sandreas.hansson@arm.com out << " cache_size_Mbytes: " 3268948SN/A << double(cache_num_sets * RubySystem::getBlockSizeBytes() * m_cache_assoc) / (1<<20) << endl; 32710656Sandreas.hansson@arm.com} 32810656Sandreas.hansson@arm.com 32910656Sandreas.hansson@arm.com// PRIVATE METHODS 33010656Sandreas.hansson@arm.com 3318948SN/A// convert a Address to its location in the cache 33210656Sandreas.hansson@arm.cominline 33310656Sandreas.hansson@arm.comIndex CacheMemory::addressToCacheSet(const Address& address) const 33410656Sandreas.hansson@arm.com{ 33510656Sandreas.hansson@arm.com assert(address == line_address(address)); 3369549SN/A Index temp = -1; 33710656Sandreas.hansson@arm.com return address.bitSelect(RubySystem::getBlockSizeBits(), RubySystem::getBlockSizeBits() + m_cache_num_set_bits-1); 33810656Sandreas.hansson@arm.com} 33910656Sandreas.hansson@arm.com 3408948SN/A// Given a cache index: returns the index of the tag in a set. 34110405Sandreas.hansson@arm.com// returns -1 if the tag is not found. 3429715SN/Ainline 3439091SN/Aint CacheMemory::findTagInSet(Index cacheSet, const Address& tag) const 3448975SN/A{ 34510656Sandreas.hansson@arm.com assert(tag == line_address(tag)); 3469712SN/A // search the set for the tags 34710405Sandreas.hansson@arm.com for (int i=0; i < m_cache_assoc; i++) { 3489712SN/A if ((m_cache[cacheSet][i] != NULL) && 34910656Sandreas.hansson@arm.com (m_cache[cacheSet][i]->m_Address == tag) && 35011564Sdavid.guillen@arm.com (m_cache[cacheSet][i]->m_Permission != AccessPermission_NotPresent)) { 35110656Sandreas.hansson@arm.com return i; 35211564Sdavid.guillen@arm.com } 35311564Sdavid.guillen@arm.com } 3549712SN/A return -1; // Not found 3559712SN/A} 35611334Sandreas.hansson@arm.com 35711334Sandreas.hansson@arm.com// Given a cache index: returns the index of the tag in a set. 35811334Sandreas.hansson@arm.com// returns -1 if the tag is not found. 35911334Sandreas.hansson@arm.cominline 36012351Snikos.nikoleris@arm.comint CacheMemory::findTagInSetIgnorePermissions(Index cacheSet, const Address& tag) const 36112351Snikos.nikoleris@arm.com{ 36212351Snikos.nikoleris@arm.com assert(tag == line_address(tag)); 36312351Snikos.nikoleris@arm.com // search the set for the tags 36412351Snikos.nikoleris@arm.com for (int i=0; i < m_cache_assoc; i++) { 36512351Snikos.nikoleris@arm.com if (m_cache[cacheSet][i] != NULL && m_cache[cacheSet][i]->m_Address == tag) 36612351Snikos.nikoleris@arm.com return i; 36712351Snikos.nikoleris@arm.com } 36812351Snikos.nikoleris@arm.com return -1; // Not found 36912351Snikos.nikoleris@arm.com} 37012351Snikos.nikoleris@arm.com 37112351Snikos.nikoleris@arm.com// PUBLIC METHODS 37212351Snikos.nikoleris@arm.cominline 37312351Snikos.nikoleris@arm.combool CacheMemory::tryCacheAccess(const Address& address, 37412351Snikos.nikoleris@arm.com CacheRequestType type, 37512351Snikos.nikoleris@arm.com DataBlock*& data_ptr) 37612351Snikos.nikoleris@arm.com{ 37712351Snikos.nikoleris@arm.com assert(address == line_address(address)); 37812351Snikos.nikoleris@arm.com DEBUG_EXPR(CACHE_COMP, HighPrio, address); 37912351Snikos.nikoleris@arm.com Index cacheSet = addressToCacheSet(address); 38012351Snikos.nikoleris@arm.com int loc = findTagInSet(cacheSet, address); 38112351Snikos.nikoleris@arm.com if(loc != -1){ // Do we even have a tag match? 38212351Snikos.nikoleris@arm.com AbstractCacheEntry* entry = m_cache[cacheSet][loc]; 38312351Snikos.nikoleris@arm.com m_replacementPolicy_ptr->touch(cacheSet, loc, g_eventQueue_ptr->getTime()); 38412351Snikos.nikoleris@arm.com data_ptr = &(entry->getDataBlk()); 38512351Snikos.nikoleris@arm.com 38612351Snikos.nikoleris@arm.com if(entry->m_Permission == AccessPermission_Read_Write) { 38712351Snikos.nikoleris@arm.com return true; 38812351Snikos.nikoleris@arm.com } 38912351Snikos.nikoleris@arm.com if ((entry->m_Permission == AccessPermission_Read_Only) && 39012351Snikos.nikoleris@arm.com (type == CacheRequestType_LD || type == CacheRequestType_IFETCH)) { 39112351Snikos.nikoleris@arm.com return true; 39212351Snikos.nikoleris@arm.com } 39312351Snikos.nikoleris@arm.com // The line must not be accessible 39412351Snikos.nikoleris@arm.com } 39512351Snikos.nikoleris@arm.com data_ptr = NULL; 39612351Snikos.nikoleris@arm.com return false; 39712351Snikos.nikoleris@arm.com} 39812351Snikos.nikoleris@arm.com 39912351Snikos.nikoleris@arm.cominline 40012351Snikos.nikoleris@arm.combool CacheMemory::testCacheAccess(const Address& address, 40112351Snikos.nikoleris@arm.com CacheRequestType type, 40212351Snikos.nikoleris@arm.com DataBlock*& data_ptr) 40312351Snikos.nikoleris@arm.com{ 40412351Snikos.nikoleris@arm.com assert(address == line_address(address)); 40512351Snikos.nikoleris@arm.com DEBUG_EXPR(CACHE_COMP, HighPrio, address); 40612351Snikos.nikoleris@arm.com Index cacheSet = addressToCacheSet(address); 40712351Snikos.nikoleris@arm.com int loc = findTagInSet(cacheSet, address); 40812351Snikos.nikoleris@arm.com if(loc != -1){ // Do we even have a tag match? 40912351Snikos.nikoleris@arm.com AbstractCacheEntry* entry = m_cache[cacheSet][loc]; 41012351Snikos.nikoleris@arm.com m_replacementPolicy_ptr->touch(cacheSet, loc, g_eventQueue_ptr->getTime()); 41111334Sandreas.hansson@arm.com data_ptr = &(entry->getDataBlk()); 41212351Snikos.nikoleris@arm.com 41311334Sandreas.hansson@arm.com return (m_cache[cacheSet][loc]->m_Permission != AccessPermission_NotPresent); 41411334Sandreas.hansson@arm.com } 41512351Snikos.nikoleris@arm.com data_ptr = NULL; 41611334Sandreas.hansson@arm.com return false; 41711334Sandreas.hansson@arm.com} 41811334Sandreas.hansson@arm.com 41912351Snikos.nikoleris@arm.com// tests to see if an address is present in the cache 42011334Sandreas.hansson@arm.cominline 42111334Sandreas.hansson@arm.combool CacheMemory::isTagPresent(const Address& address) const 42212351Snikos.nikoleris@arm.com{ 42312351Snikos.nikoleris@arm.com assert(address == line_address(address)); 42412351Snikos.nikoleris@arm.com Index cacheSet = addressToCacheSet(address); 42512351Snikos.nikoleris@arm.com int location = findTagInSet(cacheSet, address); 42611334Sandreas.hansson@arm.com 42712351Snikos.nikoleris@arm.com if (location == -1) { 42811334Sandreas.hansson@arm.com // We didn't find the tag 42912351Snikos.nikoleris@arm.com DEBUG_EXPR(CACHE_COMP, LowPrio, address); 43011334Sandreas.hansson@arm.com DEBUG_MSG(CACHE_COMP, LowPrio, "No tag match"); 43111334Sandreas.hansson@arm.com return false; 4329091SN/A } 4338975SN/A DEBUG_EXPR(CACHE_COMP, LowPrio, address); 4348975SN/A DEBUG_MSG(CACHE_COMP, LowPrio, "found"); 4358975SN/A return true; 43610405Sandreas.hansson@arm.com} 4378975SN/A 4388975SN/A// Returns true if there is: 4399032SN/A// a) a tag match on this address or there is 4408975SN/A// b) an unused line in the same cache "way" 44110656Sandreas.hansson@arm.cominline 44210656Sandreas.hansson@arm.combool CacheMemory::cacheAvail(const Address& address) const 44310656Sandreas.hansson@arm.com{ 44410656Sandreas.hansson@arm.com assert(address == line_address(address)); 44510572Sandreas.hansson@arm.com 44610572Sandreas.hansson@arm.com Index cacheSet = addressToCacheSet(address); 4479713SN/A 44810405Sandreas.hansson@arm.com for (int i=0; i < m_cache_assoc; i++) { 44910405Sandreas.hansson@arm.com AbstractCacheEntry* entry = m_cache[cacheSet][i]; 4509715SN/A if (entry != NULL) { 45111744Snikos.nikoleris@arm.com if (entry->m_Address == address || // Already in the cache 45211744Snikos.nikoleris@arm.com entry->m_Permission == AccessPermission_NotPresent) { // We found an empty entry 4538975SN/A return true; 4548975SN/A } 4558975SN/A } else { 45611744Snikos.nikoleris@arm.com return true; 45711744Snikos.nikoleris@arm.com } 4588975SN/A } 4599712SN/A return false; 4609712SN/A} 4619712SN/A 4629712SN/Ainline 4639712SN/Avoid CacheMemory::allocate(const Address& address, AbstractCacheEntry* entry) 46410719SMarco.Balboni@ARM.com{ 46510719SMarco.Balboni@ARM.com assert(address == line_address(address)); 46610719SMarco.Balboni@ARM.com assert(!isTagPresent(address)); 46710719SMarco.Balboni@ARM.com assert(cacheAvail(address)); 46810719SMarco.Balboni@ARM.com DEBUG_EXPR(CACHE_COMP, HighPrio, address); 46910719SMarco.Balboni@ARM.com 47010719SMarco.Balboni@ARM.com // Find the first open slot 47110719SMarco.Balboni@ARM.com Index cacheSet = addressToCacheSet(address); 4728975SN/A for (int i=0; i < m_cache_assoc; i++) { 47310821Sandreas.hansson@arm.com if (m_cache[cacheSet][i] == NULL || 47410402SN/A m_cache[cacheSet][i]->m_Permission == AccessPermission_NotPresent) { 47510402SN/A m_cache[cacheSet][i] = entry; // Init entry 47610402SN/A m_cache[cacheSet][i]->m_Address = address; 47710402SN/A m_cache[cacheSet][i]->m_Permission = AccessPermission_Invalid; 47810888Sandreas.hansson@arm.com 47910888Sandreas.hansson@arm.com m_replacementPolicy_ptr->touch(cacheSet, i, g_eventQueue_ptr->getTime()); 48010888Sandreas.hansson@arm.com 48110888Sandreas.hansson@arm.com return; 48210888Sandreas.hansson@arm.com } 4838975SN/A } 48410656Sandreas.hansson@arm.com ERROR_MSG("Allocate didn't find an available entry"); 48510656Sandreas.hansson@arm.com} 48610656Sandreas.hansson@arm.com 4879715SN/Ainline 4888975SN/Avoid CacheMemory::deallocate(const Address& address) 4899712SN/A{ 4909712SN/A assert(address == line_address(address)); 49110405Sandreas.hansson@arm.com assert(isTagPresent(address)); 4929712SN/A DEBUG_EXPR(CACHE_COMP, HighPrio, address); 4939712SN/A Index cacheSet = addressToCacheSet(address); 4948975SN/A int location = findTagInSet(cacheSet, address); 4958975SN/A if (location != -1){ 4968975SN/A delete m_cache[cacheSet][location]; 4978975SN/A m_cache[cacheSet][location] = NULL; 49810405Sandreas.hansson@arm.com } 4998975SN/A} 50011744Snikos.nikoleris@arm.com 50111744Snikos.nikoleris@arm.com// Returns with the physical address of the conflicting cache line 5028975SN/Ainline 5039712SN/AAddress CacheMemory::cacheProbe(const Address& address) const 50411564Sdavid.guillen@arm.com{ 5059712SN/A assert(address == line_address(address)); 50610405Sandreas.hansson@arm.com assert(!cacheAvail(address)); 50711564Sdavid.guillen@arm.com 5089712SN/A Index cacheSet = addressToCacheSet(address); 5098975SN/A return m_cache[cacheSet][m_replacementPolicy_ptr->getVictim(cacheSet)]->m_Address; 5108975SN/A} 5118975SN/A 51211127Sandreas.hansson@arm.com// looks an address up in the cache 51311127Sandreas.hansson@arm.cominline 51411127Sandreas.hansson@arm.comAbstractCacheEntry& CacheMemory::lookup(const Address& address) 51511127Sandreas.hansson@arm.com{ 51611284Sandreas.hansson@arm.com assert(address == line_address(address)); 51711284Sandreas.hansson@arm.com Index cacheSet = addressToCacheSet(address); 51811284Sandreas.hansson@arm.com int loc = findTagInSet(cacheSet, address); 5199032SN/A assert(loc != -1); 52011127Sandreas.hansson@arm.com return *m_cache[cacheSet][loc]; 52111127Sandreas.hansson@arm.com} 52210402SN/A 52310402SN/A// looks an address up in the cache 52410402SN/Ainline 52511126Sandreas.hansson@arm.comconst AbstractCacheEntry& CacheMemory::lookup(const Address& address) const 52611126Sandreas.hansson@arm.com{ 52711126Sandreas.hansson@arm.com assert(address == line_address(address)); 52811126Sandreas.hansson@arm.com Index cacheSet = addressToCacheSet(address); 52911744Snikos.nikoleris@arm.com int loc = findTagInSet(cacheSet, address); 53011744Snikos.nikoleris@arm.com assert(loc != -1); 53111744Snikos.nikoleris@arm.com return *m_cache[cacheSet][loc]; 53210402SN/A} 53310402SN/A 53410402SN/Ainline 53510402SN/AAccessPermission CacheMemory::getPermission(const Address& address) const 53610402SN/A{ 53710402SN/A assert(address == line_address(address)); 5388975SN/A return lookup(address).m_Permission; 53911127Sandreas.hansson@arm.com} 54011127Sandreas.hansson@arm.com 54111127Sandreas.hansson@arm.cominline 54211127Sandreas.hansson@arm.comvoid CacheMemory::changePermission(const Address& address, AccessPermission new_perm) 54310656Sandreas.hansson@arm.com{ 54411284Sandreas.hansson@arm.com assert(address == line_address(address)); 54510656Sandreas.hansson@arm.com lookup(address).m_Permission = new_perm; 54610656Sandreas.hansson@arm.com assert(getPermission(address) == new_perm); 54710656Sandreas.hansson@arm.com} 54810656Sandreas.hansson@arm.com 5498975SN/A// Sets the most recently used bit for a cache block 5508975SN/Ainline 5518975SN/Avoid CacheMemory::setMRU(const Address& address) 5528975SN/A{ 5538975SN/A Index cacheSet; 55413856Sodanrc@yahoo.com.br 5558975SN/A cacheSet = addressToCacheSet(address); 5568975SN/A m_replacementPolicy_ptr->touch(cacheSet, 5578975SN/A findTagInSet(cacheSet, address), 55810405Sandreas.hansson@arm.com g_eventQueue_ptr->getTime()); 5598975SN/A} 5608975SN/A 5619032SN/Ainline 5628975SN/Avoid CacheMemory::recordCacheContents(CacheRecorder& tr) const 56310656Sandreas.hansson@arm.com{ 56410656Sandreas.hansson@arm.com for (int i = 0; i < m_cache_num_sets; i++) { 56510656Sandreas.hansson@arm.com for (int j = 0; j < m_cache_assoc; j++) { 56610656Sandreas.hansson@arm.com AccessPermission perm = m_cache[i][j]->m_Permission; 56710572Sandreas.hansson@arm.com CacheRequestType request_type = CacheRequestType_NULL; 5689714SN/A if (perm == AccessPermission_Read_Only) { 5699714SN/A if (m_is_instruction_only_cache) { 5709714SN/A request_type = CacheRequestType_IFETCH; 57110656Sandreas.hansson@arm.com } else { 5729714SN/A request_type = CacheRequestType_LD; 57310656Sandreas.hansson@arm.com } 57410656Sandreas.hansson@arm.com } else if (perm == AccessPermission_Read_Write) { 5759714SN/A request_type = CacheRequestType_ST; 57610405Sandreas.hansson@arm.com } 57710405Sandreas.hansson@arm.com 57810405Sandreas.hansson@arm.com if (request_type != CacheRequestType_NULL) { 57910405Sandreas.hansson@arm.com // tr.addRecord(m_chip_ptr->getID(), m_cache[i][j].m_Address, 5809715SN/A // Address(0), request_type, m_replacementPolicy_ptr->getLastAccess(i, j)); 58110572Sandreas.hansson@arm.com } 5829715SN/A } 58311744Snikos.nikoleris@arm.com } 58411744Snikos.nikoleris@arm.com} 5859715SN/A 5869715SN/Ainline 5879716SN/Avoid CacheMemory::print(ostream& out) const 5889716SN/A{ 5899716SN/A out << "Cache dump: " << m_cache_name << endl; 59010572Sandreas.hansson@arm.com for (int i = 0; i < m_cache_num_sets; i++) { 5919716SN/A for (int j = 0; j < m_cache_assoc; j++) { 59211744Snikos.nikoleris@arm.com if (m_cache[i][j] != NULL) { 59311744Snikos.nikoleris@arm.com out << " Index: " << i 5949716SN/A << " way: " << j 5959716SN/A << " entry: " << *m_cache[i][j] << endl; 5968975SN/A } else { 5978975SN/A out << " Index: " << i 59811744Snikos.nikoleris@arm.com << " way: " << j 59911744Snikos.nikoleris@arm.com << " entry: NULL" << endl; 6008975SN/A } 6019712SN/A } 6029712SN/A } 6039712SN/A} 6049712SN/A 6059712SN/Ainline 6068975SN/Avoid CacheMemory::printData(ostream& out) const 6078975SN/A{ 6088975SN/A out << "printData() not supported" << endl; 60910719SMarco.Balboni@ARM.com} 61010719SMarco.Balboni@ARM.com 61110719SMarco.Balboni@ARM.cominline 61210719SMarco.Balboni@ARM.comvoid CacheMemory::getMemoryValue(const Address& addr, char* value, 61310719SMarco.Balboni@ARM.com unsigned int size_in_bytes ){ 61410719SMarco.Balboni@ARM.com AbstractCacheEntry& entry = lookup(line_address(addr)); 61510719SMarco.Balboni@ARM.com unsigned int startByte = addr.getAddress() - line_address(addr).getAddress(); 61610719SMarco.Balboni@ARM.com for(unsigned int i=0; i<size_in_bytes; ++i){ 61710719SMarco.Balboni@ARM.com value[i] = entry.getDataBlk().getByte(i + startByte); 61810719SMarco.Balboni@ARM.com } 61910719SMarco.Balboni@ARM.com} 6208975SN/A 6219714SN/Ainline 6229714SN/Avoid CacheMemory::setMemoryValue(const Address& addr, char* value, 6239714SN/A unsigned int size_in_bytes ){ 6249714SN/A AbstractCacheEntry& entry = lookup(line_address(addr)); 6259714SN/A unsigned int startByte = addr.getAddress() - line_address(addr).getAddress(); 62610402SN/A assert(size_in_bytes > 0); 62710402SN/A for(unsigned int i=0; i<size_in_bytes; ++i){ 62810402SN/A entry.getDataBlk().setByte(i + startByte, value[i]); 62910402SN/A } 63010402SN/A 63110402SN/A // entry = lookup(line_address(addr)); 63210402SN/A} 6339712SN/A 6349712SN/A#endif //CACHEMEMORY_H 6359712SN/A 63610405Sandreas.hansson@arm.com