CacheMemory.hh revision 6145
12568SN/A/* 210325Sgeoffrey.blake@arm.com * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood 38668Sgeoffrey.blake@arm.com * All rights reserved. 48668Sgeoffrey.blake@arm.com * 58668Sgeoffrey.blake@arm.com * Redistribution and use in source and binary forms, with or without 68668Sgeoffrey.blake@arm.com * modification, are permitted provided that the following conditions are 78668Sgeoffrey.blake@arm.com * met: redistributions of source code must retain the above copyright 88668Sgeoffrey.blake@arm.com * notice, this list of conditions and the following disclaimer; 98668Sgeoffrey.blake@arm.com * redistributions in binary form must reproduce the above copyright 108668Sgeoffrey.blake@arm.com * notice, this list of conditions and the following disclaimer in the 118668Sgeoffrey.blake@arm.com * documentation and/or other materials provided with the distribution; 128668Sgeoffrey.blake@arm.com * neither the name of the copyright holders nor the names of its 138668Sgeoffrey.blake@arm.com * contributors may be used to endorse or promote products derived from 142568SN/A * this software without specific prior written permission. 157636Ssteve.reinhardt@amd.com * 162568SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 172568SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 182568SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 192568SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 202568SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 212568SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 222568SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 232568SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 242568SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 252568SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 262568SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 272568SN/A */ 282568SN/A 292568SN/A/* 302568SN/A * CacheMemory.h 312568SN/A * 322568SN/A * Description: 332568SN/A * 342568SN/A * $Id: CacheMemory.h,v 3.7 2004/06/18 20:15:15 beckmann Exp $ 352568SN/A * 362568SN/A */ 372568SN/A 382568SN/A#ifndef CACHEMEMORY_H 392568SN/A#define CACHEMEMORY_H 402665Ssaidi@eecs.umich.edu 412665Ssaidi@eecs.umich.edu#include "AbstractChip.hh" 422665Ssaidi@eecs.umich.edu#include "Global.hh" 432568SN/A#include "AccessPermission.hh" 442568SN/A#include "Address.hh" 452568SN/A#include "CacheRecorder.hh" 462568SN/A#include "CacheRequestType.hh" 472568SN/A#include "Vector.hh" 482568SN/A#include "DataBlock.hh" 492568SN/A#include "MachineType.hh" 503260Ssaidi@eecs.umich.edu#include "RubySlicc_ComponentMapping.hh" 518229Snate@binkert.org#include "PseudoLRUPolicy.hh" 523260Ssaidi@eecs.umich.edu#include "LRUPolicy.hh" 538229Snate@binkert.org#include <vector> 545314Sstever@gmail.com 552590SN/Atemplate<class ENTRY> 563348Sbinkertn@umich.educlass CacheMemory { 572568SN/Apublic: 582568SN/A 595735Snate@binkert.org // Constructors 605735Snate@binkert.org CacheMemory(AbstractChip* chip_ptr, int numSetBits, int cacheAssoc, const MachineType machType, const string& description); 614022Sstever@eecs.umich.edu 624022Sstever@eecs.umich.edu // Destructor 634022Sstever@eecs.umich.edu ~CacheMemory(); 644022Sstever@eecs.umich.edu 654022Sstever@eecs.umich.edu // Public Methods 664022Sstever@eecs.umich.edu void printConfig(ostream& out); 674022Sstever@eecs.umich.edu 682641Sstever@eecs.umich.edu // perform a cache access and see if we hit or not. Return true on a hit. 694022Sstever@eecs.umich.edu bool tryCacheAccess(const Address& address, CacheRequestType type, DataBlock*& data_ptr); 704022Sstever@eecs.umich.edu 712641Sstever@eecs.umich.edu // similar to above, but doesn't require full access check 724022Sstever@eecs.umich.edu bool testCacheAccess(const Address& address, CacheRequestType type, DataBlock*& data_ptr); 734022Sstever@eecs.umich.edu 744022Sstever@eecs.umich.edu // tests to see if an address is present in the cache 754022Sstever@eecs.umich.edu bool isTagPresent(const Address& address) const; 764473Sstever@eecs.umich.edu 774473Sstever@eecs.umich.edu // Returns true if there is: 785319Sstever@gmail.com // a) a tag match on this address or there is 795319Sstever@gmail.com // b) an unused line in the same cache "way" 805319Sstever@gmail.com bool cacheAvail(const Address& address) const; 814022Sstever@eecs.umich.edu 824626Sstever@eecs.umich.edu // find an unused entry and sets the tag appropriate for the address 834022Sstever@eecs.umich.edu void allocate(const Address& address); 844022Sstever@eecs.umich.edu 854626Sstever@eecs.umich.edu // Explicitly free up this address 864022Sstever@eecs.umich.edu void deallocate(const Address& address); 874628Sstever@eecs.umich.edu 884628Sstever@eecs.umich.edu // Returns with the physical address of the conflicting cache line 894022Sstever@eecs.umich.edu Address cacheProbe(const Address& address) const; 904022Sstever@eecs.umich.edu 914022Sstever@eecs.umich.edu // looks an address up in the cache 924022Sstever@eecs.umich.edu ENTRY& lookup(const Address& address); 934022Sstever@eecs.umich.edu const ENTRY& lookup(const Address& address) const; 944022Sstever@eecs.umich.edu 954022Sstever@eecs.umich.edu // Get/Set permission of cache block 964022Sstever@eecs.umich.edu AccessPermission getPermission(const Address& address) const; 974022Sstever@eecs.umich.edu void changePermission(const Address& address, AccessPermission new_perm); 984022Sstever@eecs.umich.edu 994022Sstever@eecs.umich.edu // Hook for checkpointing the contents of the cache 1004022Sstever@eecs.umich.edu void recordCacheContents(CacheRecorder& tr) const; 10110345SCurtis.Dunham@arm.com void setAsInstructionCache(bool is_icache) { m_is_instruction_cache = is_icache; } 1024626Sstever@eecs.umich.edu 1034626Sstever@eecs.umich.edu // Set this address to most recently used 1044022Sstever@eecs.umich.edu void setMRU(const Address& address); 10510345SCurtis.Dunham@arm.com 1065319Sstever@gmail.com void getMemoryValue(const Address& addr, char* value, 1074022Sstever@eecs.umich.edu unsigned int size_in_bytes ); 1084022Sstever@eecs.umich.edu void setMemoryValue(const Address& addr, char* value, 1097465Ssteve.reinhardt@amd.com unsigned int size_in_bytes ); 1104628Sstever@eecs.umich.edu 1117465Ssteve.reinhardt@amd.com // Print cache contents 1127465Ssteve.reinhardt@amd.com void print(ostream& out) const; 1137465Ssteve.reinhardt@amd.com void printData(ostream& out) const; 1147465Ssteve.reinhardt@amd.com 1154628Sstever@eecs.umich.eduprivate: 1167465Ssteve.reinhardt@amd.com // Private Methods 1177465Ssteve.reinhardt@amd.com 11810325Sgeoffrey.blake@arm.com // convert a Address to its location in the cache 11910325Sgeoffrey.blake@arm.com Index addressToCacheSet(const Address& address) const; 12010325Sgeoffrey.blake@arm.com 1217465Ssteve.reinhardt@amd.com // Given a cache tag: returns the index of the tag in a set. 12210325Sgeoffrey.blake@arm.com // returns -1 if the tag is not found. 12310325Sgeoffrey.blake@arm.com int findTagInSet(Index line, const Address& tag) const; 12410325Sgeoffrey.blake@arm.com int findTagInSetIgnorePermissions(Index cacheSet, const Address& tag) const; 1257465Ssteve.reinhardt@amd.com 1264022Sstever@eecs.umich.edu // Private copy constructor and assignment operator 1274626Sstever@eecs.umich.edu CacheMemory(const CacheMemory& obj); 1284022Sstever@eecs.umich.edu CacheMemory& operator=(const CacheMemory& obj); 1294022Sstever@eecs.umich.edu 1305319Sstever@gmail.com // Data Members (m_prefix) 1314040Ssaidi@eecs.umich.edu AbstractChip* m_chip_ptr; 1325507Sstever@gmail.com MachineType m_machType; 1335507Sstever@gmail.com string m_description; 1346076Sgblack@eecs.umich.edu bool m_is_instruction_cache; 1355507Sstever@gmail.com 1364626Sstever@eecs.umich.edu // The first index is the # of cache lines. 1376076Sgblack@eecs.umich.edu // The second index is the the amount associativity. 1384626Sstever@eecs.umich.edu Vector<Vector<ENTRY> > m_cache; 1394626Sstever@eecs.umich.edu 14010325Sgeoffrey.blake@arm.com AbstractReplacementPolicy *m_replacementPolicy_ptr; 1417669Ssteve.reinhardt@amd.com 1427669Ssteve.reinhardt@amd.com int m_cache_num_sets; 1437669Ssteve.reinhardt@amd.com int m_cache_num_set_bits; 1444626Sstever@eecs.umich.edu int m_cache_assoc; 1456076Sgblack@eecs.umich.edu}; 1464626Sstever@eecs.umich.edu 1474040Ssaidi@eecs.umich.edu// Output operator declaration 1484626Sstever@eecs.umich.edu//ostream& operator<<(ostream& out, const CacheMemory<ENTRY>& obj); 1494040Ssaidi@eecs.umich.edu 1504040Ssaidi@eecs.umich.edu// ******************* Definitions ******************* 1514626Sstever@eecs.umich.edu 1524870Sstever@eecs.umich.edu// Output operator definition 1535650Sgblack@eecs.umich.edutemplate<class ENTRY> 1545650Sgblack@eecs.umich.eduinline 1556063Sgblack@eecs.umich.eduostream& operator<<(ostream& out, const CacheMemory<ENTRY>& obj) 1565650Sgblack@eecs.umich.edu{ 1576063Sgblack@eecs.umich.edu obj.print(out); 1584870Sstever@eecs.umich.edu out << flush; 1594986Ssaidi@eecs.umich.edu return out; 1604870Sstever@eecs.umich.edu} 1615314Sstever@gmail.com 1628436SBrad.Beckmann@amd.com 1638436SBrad.Beckmann@amd.com// **************************************************************** 1648436SBrad.Beckmann@amd.com 1658436SBrad.Beckmann@amd.comtemplate<class ENTRY> 1665314Sstever@gmail.cominline 1678184Ssomayeh@cs.wisc.eduCacheMemory<ENTRY>::CacheMemory(AbstractChip* chip_ptr, int numSetBits, 1688184Ssomayeh@cs.wisc.edu int cacheAssoc, const MachineType machType, const string& description) 1698436SBrad.Beckmann@amd.com 1708716Snilay@cs.wisc.edu{ 1718716Snilay@cs.wisc.edu //cout << "CacheMemory constructor numThreads = " << numThreads << endl; 1728716Snilay@cs.wisc.edu m_chip_ptr = chip_ptr; 1734022Sstever@eecs.umich.edu m_machType = machType; 1742592SN/A m_description = MachineType_to_string(m_machType)+"_"+description; 1753607Srdreslin@umich.edu m_cache_num_set_bits = numSetBits; 17610028SGiacomo.Gabrielli@arm.com m_cache_num_sets = 1 << numSetBits; 17710028SGiacomo.Gabrielli@arm.com m_cache_assoc = cacheAssoc; 1782641Sstever@eecs.umich.edu m_is_instruction_cache = false; 1794626Sstever@eecs.umich.edu 1804626Sstever@eecs.umich.edu m_cache.setSize(m_cache_num_sets); 1814626Sstever@eecs.umich.edu if(strcmp(g_REPLACEMENT_POLICY, "PSEDUO_LRU") == 0) 1824626Sstever@eecs.umich.edu m_replacementPolicy_ptr = new PseudoLRUPolicy(m_cache_num_sets, m_cache_assoc); 1833260Ssaidi@eecs.umich.edu else if(strcmp(g_REPLACEMENT_POLICY, "LRU") == 0) 18410028SGiacomo.Gabrielli@arm.com m_replacementPolicy_ptr = new LRUPolicy(m_cache_num_sets, m_cache_assoc); 18510028SGiacomo.Gabrielli@arm.com else 1864626Sstever@eecs.umich.edu assert(false); 1874626Sstever@eecs.umich.edu for (int i = 0; i < m_cache_num_sets; i++) { 1884626Sstever@eecs.umich.edu m_cache[i].setSize(m_cache_assoc); 1893260Ssaidi@eecs.umich.edu for (int j = 0; j < m_cache_assoc; j++) { 1905314Sstever@gmail.com m_cache[i][j].m_Address.setAddress(0); 1915314Sstever@gmail.com m_cache[i][j].m_Permission = AccessPermission_NotPresent; 1925314Sstever@gmail.com } 1935314Sstever@gmail.com } 1945314Sstever@gmail.com 1955314Sstever@gmail.com 1965314Sstever@gmail.com // cout << "Before setting trans address list size" << endl; 1975314Sstever@gmail.com //create a trans address for each SMT thread 1985314Sstever@gmail.com// m_trans_address_list.setSize(numThreads); 1995314Sstever@gmail.com// for(int i=0; i < numThreads; ++i){ 2005314Sstever@gmail.com// cout << "Setting list size for list " << i << endl; 2014626Sstever@eecs.umich.edu// m_trans_address_list[i].setSize(30); 2024626Sstever@eecs.umich.edu// } 2034626Sstever@eecs.umich.edu //cout << "CacheMemory constructor finished" << endl; 2043260Ssaidi@eecs.umich.edu} 2054626Sstever@eecs.umich.edu 2064626Sstever@eecs.umich.edutemplate<class ENTRY> 2074626Sstever@eecs.umich.eduinline 2085735Snate@binkert.orgCacheMemory<ENTRY>::~CacheMemory() 2094626Sstever@eecs.umich.edu{ 2103260Ssaidi@eecs.umich.edu if(m_replacementPolicy_ptr != NULL) 2118668Sgeoffrey.blake@arm.com delete m_replacementPolicy_ptr; 2128668Sgeoffrey.blake@arm.com} 2138668Sgeoffrey.blake@arm.com 2148668Sgeoffrey.blake@arm.comtemplate<class ENTRY> 2158668Sgeoffrey.blake@arm.cominline 2168668Sgeoffrey.blake@arm.comvoid CacheMemory<ENTRY>::printConfig(ostream& out) 2178668Sgeoffrey.blake@arm.com{ 2188668Sgeoffrey.blake@arm.com out << "Cache config: " << m_description << endl; 2198668Sgeoffrey.blake@arm.com out << " cache_associativity: " << m_cache_assoc << endl; 2208668Sgeoffrey.blake@arm.com out << " num_cache_sets_bits: " << m_cache_num_set_bits << endl; 2218668Sgeoffrey.blake@arm.com const int cache_num_sets = 1 << m_cache_num_set_bits; 2228668Sgeoffrey.blake@arm.com out << " num_cache_sets: " << cache_num_sets << endl; 2238668Sgeoffrey.blake@arm.com out << " cache_set_size_bytes: " << cache_num_sets * RubyConfig::dataBlockBytes() << endl; 2248668Sgeoffrey.blake@arm.com out << " cache_set_size_Kbytes: " 2258668Sgeoffrey.blake@arm.com << double(cache_num_sets * RubyConfig::dataBlockBytes()) / (1<<10) << endl; 2268668Sgeoffrey.blake@arm.com out << " cache_set_size_Mbytes: " 2278668Sgeoffrey.blake@arm.com << double(cache_num_sets * RubyConfig::dataBlockBytes()) / (1<<20) << endl; 2288668Sgeoffrey.blake@arm.com out << " cache_size_bytes: " 2298668Sgeoffrey.blake@arm.com << cache_num_sets * RubyConfig::dataBlockBytes() * m_cache_assoc << endl; 2308668Sgeoffrey.blake@arm.com out << " cache_size_Kbytes: " 2318668Sgeoffrey.blake@arm.com << double(cache_num_sets * RubyConfig::dataBlockBytes() * m_cache_assoc) / (1<<10) << endl; 2328668Sgeoffrey.blake@arm.com out << " cache_size_Mbytes: " 2338668Sgeoffrey.blake@arm.com << double(cache_num_sets * RubyConfig::dataBlockBytes() * m_cache_assoc) / (1<<20) << endl; 2348668Sgeoffrey.blake@arm.com} 2358668Sgeoffrey.blake@arm.com 2368668Sgeoffrey.blake@arm.com// PRIVATE METHODS 2378668Sgeoffrey.blake@arm.com 2388668Sgeoffrey.blake@arm.com// convert a Address to its location in the cache 2398668Sgeoffrey.blake@arm.comtemplate<class ENTRY> 2408668Sgeoffrey.blake@arm.cominline 2418668Sgeoffrey.blake@arm.comIndex CacheMemory<ENTRY>::addressToCacheSet(const Address& address) const 2428668Sgeoffrey.blake@arm.com{ 2438668Sgeoffrey.blake@arm.com assert(address == line_address(address)); 2448668Sgeoffrey.blake@arm.com Index temp = -1; 2458668Sgeoffrey.blake@arm.com switch (m_machType) { 2468668Sgeoffrey.blake@arm.com case MACHINETYPE_L1CACHE_ENUM: 2478668Sgeoffrey.blake@arm.com temp = map_address_to_L1CacheSet(address, m_cache_num_set_bits); 2488668Sgeoffrey.blake@arm.com break; 2498668Sgeoffrey.blake@arm.com case MACHINETYPE_L2CACHE_ENUM: 2508668Sgeoffrey.blake@arm.com temp = map_address_to_L2CacheSet(address, m_cache_num_set_bits); 2518668Sgeoffrey.blake@arm.com break; 2528668Sgeoffrey.blake@arm.com default: 2538668Sgeoffrey.blake@arm.com ERROR_MSG("Don't recognize m_machType"); 2548668Sgeoffrey.blake@arm.com } 2558668Sgeoffrey.blake@arm.com assert(temp < m_cache_num_sets); 2568668Sgeoffrey.blake@arm.com assert(temp >= 0); 2578668Sgeoffrey.blake@arm.com return temp; 2588668Sgeoffrey.blake@arm.com} 2598668Sgeoffrey.blake@arm.com 2608668Sgeoffrey.blake@arm.com// Given a cache index: returns the index of the tag in a set. 2618668Sgeoffrey.blake@arm.com// returns -1 if the tag is not found. 2628668Sgeoffrey.blake@arm.comtemplate<class ENTRY> 2638668Sgeoffrey.blake@arm.cominline 2648668Sgeoffrey.blake@arm.comint CacheMemory<ENTRY>::findTagInSet(Index cacheSet, const Address& tag) const 2658668Sgeoffrey.blake@arm.com{ 2668668Sgeoffrey.blake@arm.com assert(tag == line_address(tag)); 2678668Sgeoffrey.blake@arm.com // search the set for the tags 2688668Sgeoffrey.blake@arm.com for (int i=0; i < m_cache_assoc; i++) { 2698668Sgeoffrey.blake@arm.com if ((m_cache[cacheSet][i].m_Address == tag) && 2708668Sgeoffrey.blake@arm.com (m_cache[cacheSet][i].m_Permission != AccessPermission_NotPresent)) { 2718668Sgeoffrey.blake@arm.com return i; 2728668Sgeoffrey.blake@arm.com } 2738668Sgeoffrey.blake@arm.com } 2748668Sgeoffrey.blake@arm.com return -1; // Not found 2758668Sgeoffrey.blake@arm.com} 2768668Sgeoffrey.blake@arm.com 2778668Sgeoffrey.blake@arm.com// Given a cache index: returns the index of the tag in a set. 2788668Sgeoffrey.blake@arm.com// returns -1 if the tag is not found. 2798668Sgeoffrey.blake@arm.comtemplate<class ENTRY> 2808668Sgeoffrey.blake@arm.cominline 2818668Sgeoffrey.blake@arm.comint CacheMemory<ENTRY>::findTagInSetIgnorePermissions(Index cacheSet, const Address& tag) const 2828668Sgeoffrey.blake@arm.com{ 2838668Sgeoffrey.blake@arm.com assert(tag == line_address(tag)); 2848668Sgeoffrey.blake@arm.com // search the set for the tags 2858668Sgeoffrey.blake@arm.com for (int i=0; i < m_cache_assoc; i++) { 2868668Sgeoffrey.blake@arm.com if (m_cache[cacheSet][i].m_Address == tag) 2878668Sgeoffrey.blake@arm.com return i; 2888668Sgeoffrey.blake@arm.com } 2898668Sgeoffrey.blake@arm.com return -1; // Not found 2908668Sgeoffrey.blake@arm.com} 2918668Sgeoffrey.blake@arm.com 2928668Sgeoffrey.blake@arm.com// PUBLIC METHODS 2938692Ssaidi@eecs.umich.edutemplate<class ENTRY> 2948668Sgeoffrey.blake@arm.cominline 2958668Sgeoffrey.blake@arm.combool CacheMemory<ENTRY>::tryCacheAccess(const Address& address, 2968668Sgeoffrey.blake@arm.com CacheRequestType type, 2978668Sgeoffrey.blake@arm.com DataBlock*& data_ptr) 2988668Sgeoffrey.blake@arm.com{ 2998668Sgeoffrey.blake@arm.com assert(address == line_address(address)); 3008668Sgeoffrey.blake@arm.com DEBUG_EXPR(CACHE_COMP, HighPrio, address); 3018668Sgeoffrey.blake@arm.com Index cacheSet = addressToCacheSet(address); 3028668Sgeoffrey.blake@arm.com int loc = findTagInSet(cacheSet, address); 3033260Ssaidi@eecs.umich.edu if(loc != -1){ // Do we even have a tag match? 3044626Sstever@eecs.umich.edu ENTRY& entry = m_cache[cacheSet][loc]; 3054626Sstever@eecs.umich.edu m_replacementPolicy_ptr->touch(cacheSet, loc, g_eventQueue_ptr->getTime()); 3065735Snate@binkert.org data_ptr = &(entry.getDataBlk()); 3075735Snate@binkert.org 3085735Snate@binkert.org if(entry.m_Permission == AccessPermission_Read_Write) { 3095735Snate@binkert.org return true; 3105735Snate@binkert.org } 3115735Snate@binkert.org if ((entry.m_Permission == AccessPermission_Read_Only) && 3123260Ssaidi@eecs.umich.edu (type == CacheRequestType_LD || type == CacheRequestType_IFETCH)) { 3135314Sstever@gmail.com return true; 3144626Sstever@eecs.umich.edu } 3155314Sstever@gmail.com // The line must not be accessible 3165314Sstever@gmail.com } 3175314Sstever@gmail.com data_ptr = NULL; 3185314Sstever@gmail.com return false; 3192641Sstever@eecs.umich.edu} 3203260Ssaidi@eecs.umich.edu 3215314Sstever@gmail.comtemplate<class ENTRY> 3229542Sandreas.hansson@arm.cominline 3239542Sandreas.hansson@arm.combool CacheMemory<ENTRY>::testCacheAccess(const Address& address, 3249542Sandreas.hansson@arm.com CacheRequestType type, 3259542Sandreas.hansson@arm.com DataBlock*& data_ptr) 3269542Sandreas.hansson@arm.com{ 3279542Sandreas.hansson@arm.com assert(address == line_address(address)); 3289542Sandreas.hansson@arm.com DEBUG_EXPR(CACHE_COMP, HighPrio, address); 3299542Sandreas.hansson@arm.com Index cacheSet = addressToCacheSet(address); 3309542Sandreas.hansson@arm.com int loc = findTagInSet(cacheSet, address); 3319542Sandreas.hansson@arm.com if(loc != -1){ // Do we even have a tag match? 3329542Sandreas.hansson@arm.com ENTRY& entry = m_cache[cacheSet][loc]; 3339542Sandreas.hansson@arm.com m_replacementPolicy_ptr->touch(cacheSet, loc, g_eventQueue_ptr->getTime()); 3349542Sandreas.hansson@arm.com data_ptr = &(entry.getDataBlk()); 3359542Sandreas.hansson@arm.com 3369542Sandreas.hansson@arm.com return (m_cache[cacheSet][loc].m_Permission != AccessPermission_NotPresent); 3379542Sandreas.hansson@arm.com } 3389542Sandreas.hansson@arm.com data_ptr = NULL; 3399542Sandreas.hansson@arm.com return false; 3405735Snate@binkert.org} 3413260Ssaidi@eecs.umich.edu 3425314Sstever@gmail.com// tests to see if an address is present in the cache 3435314Sstever@gmail.comtemplate<class ENTRY> 3443260Ssaidi@eecs.umich.eduinline 3453260Ssaidi@eecs.umich.edubool CacheMemory<ENTRY>::isTagPresent(const Address& address) const 3469663Suri.wiener@arm.com{ 3479663Suri.wiener@arm.com assert(address == line_address(address)); 3489663Suri.wiener@arm.com Index cacheSet = addressToCacheSet(address); 3499663Suri.wiener@arm.com int location = findTagInSet(cacheSet, address); 3509663Suri.wiener@arm.com 3519663Suri.wiener@arm.com if (location == -1) { 3529663Suri.wiener@arm.com // We didn't find the tag 3535735Snate@binkert.org DEBUG_EXPR(CACHE_COMP, LowPrio, address); 3545735Snate@binkert.org DEBUG_MSG(CACHE_COMP, LowPrio, "No tag match"); 3555314Sstever@gmail.com return false; 3565314Sstever@gmail.com } 3575314Sstever@gmail.com DEBUG_EXPR(CACHE_COMP, LowPrio, address); 3585314Sstever@gmail.com DEBUG_MSG(CACHE_COMP, LowPrio, "found"); 3595314Sstever@gmail.com return true; 3605314Sstever@gmail.com} 3615314Sstever@gmail.com 3625314Sstever@gmail.com// Returns true if there is: 3635314Sstever@gmail.com// a) a tag match on this address or there is 3645314Sstever@gmail.com// b) an unused line in the same cache "way" 3655314Sstever@gmail.comtemplate<class ENTRY> 3665314Sstever@gmail.cominline 3675735Snate@binkert.orgbool CacheMemory<ENTRY>::cacheAvail(const Address& address) const 3685314Sstever@gmail.com{ 3695314Sstever@gmail.com assert(address == line_address(address)); 3705314Sstever@gmail.com 3715314Sstever@gmail.com Index cacheSet = addressToCacheSet(address); 3725314Sstever@gmail.com 3735735Snate@binkert.org for (int i=0; i < m_cache_assoc; i++) { 3745314Sstever@gmail.com if (m_cache[cacheSet][i].m_Address == address) { 3755314Sstever@gmail.com // Already in the cache 3765735Snate@binkert.org return true; 3775314Sstever@gmail.com } 3785314Sstever@gmail.com 3795314Sstever@gmail.com if (m_cache[cacheSet][i].m_Permission == AccessPermission_NotPresent) { 3805314Sstever@gmail.com // We found an empty entry 3815314Sstever@gmail.com return true; 3825314Sstever@gmail.com } 3835314Sstever@gmail.com } 3845314Sstever@gmail.com return false; 3855314Sstever@gmail.com} 3865314Sstever@gmail.com 3875314Sstever@gmail.comtemplate<class ENTRY> 3885314Sstever@gmail.cominline 3895314Sstever@gmail.comvoid CacheMemory<ENTRY>::allocate(const Address& address) 3905314Sstever@gmail.com{ 3915314Sstever@gmail.com assert(address == line_address(address)); 3925314Sstever@gmail.com assert(!isTagPresent(address)); 3935314Sstever@gmail.com assert(cacheAvail(address)); 3945314Sstever@gmail.com DEBUG_EXPR(CACHE_COMP, HighPrio, address); 3955314Sstever@gmail.com 3965314Sstever@gmail.com // Find the first open slot 3975314Sstever@gmail.com Index cacheSet = addressToCacheSet(address); 3985314Sstever@gmail.com for (int i=0; i < m_cache_assoc; i++) { 3995314Sstever@gmail.com if (m_cache[cacheSet][i].m_Permission == AccessPermission_NotPresent) { 4005314Sstever@gmail.com m_cache[cacheSet][i] = ENTRY(); // Init entry 4015314Sstever@gmail.com m_cache[cacheSet][i].m_Address = address; 4025314Sstever@gmail.com m_cache[cacheSet][i].m_Permission = AccessPermission_Invalid; 4035314Sstever@gmail.com 4045314Sstever@gmail.com m_replacementPolicy_ptr->touch(cacheSet, i, g_eventQueue_ptr->getTime()); 4055314Sstever@gmail.com 4065314Sstever@gmail.com return; 4075314Sstever@gmail.com } 4085314Sstever@gmail.com } 4095314Sstever@gmail.com ERROR_MSG("Allocate didn't find an available entry"); 4105314Sstever@gmail.com} 4115314Sstever@gmail.com 412template<class ENTRY> 413inline 414void CacheMemory<ENTRY>::deallocate(const Address& address) 415{ 416 assert(address == line_address(address)); 417 assert(isTagPresent(address)); 418 DEBUG_EXPR(CACHE_COMP, HighPrio, address); 419 lookup(address).m_Permission = AccessPermission_NotPresent; 420} 421 422// Returns with the physical address of the conflicting cache line 423template<class ENTRY> 424inline 425Address CacheMemory<ENTRY>::cacheProbe(const Address& address) const 426{ 427 assert(address == line_address(address)); 428 assert(!cacheAvail(address)); 429 430 Index cacheSet = addressToCacheSet(address); 431 return m_cache[cacheSet][m_replacementPolicy_ptr->getVictim(cacheSet)].m_Address; 432} 433 434// looks an address up in the cache 435template<class ENTRY> 436inline 437ENTRY& CacheMemory<ENTRY>::lookup(const Address& address) 438{ 439 assert(address == line_address(address)); 440 Index cacheSet = addressToCacheSet(address); 441 int loc = findTagInSet(cacheSet, address); 442 assert(loc != -1); 443 return m_cache[cacheSet][loc]; 444} 445 446// looks an address up in the cache 447template<class ENTRY> 448inline 449const ENTRY& CacheMemory<ENTRY>::lookup(const Address& address) const 450{ 451 assert(address == line_address(address)); 452 Index cacheSet = addressToCacheSet(address); 453 int loc = findTagInSet(cacheSet, address); 454 assert(loc != -1); 455 return m_cache[cacheSet][loc]; 456} 457 458template<class ENTRY> 459inline 460AccessPermission CacheMemory<ENTRY>::getPermission(const Address& address) const 461{ 462 assert(address == line_address(address)); 463 return lookup(address).m_Permission; 464} 465 466template<class ENTRY> 467inline 468void CacheMemory<ENTRY>::changePermission(const Address& address, AccessPermission new_perm) 469{ 470 assert(address == line_address(address)); 471 lookup(address).m_Permission = new_perm; 472 assert(getPermission(address) == new_perm); 473} 474 475// Sets the most recently used bit for a cache block 476template<class ENTRY> 477inline 478void CacheMemory<ENTRY>::setMRU(const Address& address) 479{ 480 Index cacheSet; 481 482 cacheSet = addressToCacheSet(address); 483 m_replacementPolicy_ptr->touch(cacheSet, 484 findTagInSet(cacheSet, address), 485 g_eventQueue_ptr->getTime()); 486} 487 488template<class ENTRY> 489inline 490void CacheMemory<ENTRY>::recordCacheContents(CacheRecorder& tr) const 491{ 492 for (int i = 0; i < m_cache_num_sets; i++) { 493 for (int j = 0; j < m_cache_assoc; j++) { 494 AccessPermission perm = m_cache[i][j].m_Permission; 495 CacheRequestType request_type = CacheRequestType_NULL; 496 if (perm == AccessPermission_Read_Only) { 497 if (m_is_instruction_cache) { 498 request_type = CacheRequestType_IFETCH; 499 } else { 500 request_type = CacheRequestType_LD; 501 } 502 } else if (perm == AccessPermission_Read_Write) { 503 request_type = CacheRequestType_ST; 504 } 505 506 if (request_type != CacheRequestType_NULL) { 507 tr.addRecord(m_chip_ptr->getID(), m_cache[i][j].m_Address, 508 Address(0), request_type, m_replacementPolicy_ptr->getLastAccess(i, j)); 509 } 510 } 511 } 512} 513 514template<class ENTRY> 515inline 516void CacheMemory<ENTRY>::print(ostream& out) const 517{ 518 out << "Cache dump: " << m_description << endl; 519 for (int i = 0; i < m_cache_num_sets; i++) { 520 for (int j = 0; j < m_cache_assoc; j++) { 521 out << " Index: " << i 522 << " way: " << j 523 << " entry: " << m_cache[i][j] << endl; 524 } 525 } 526} 527 528template<class ENTRY> 529inline 530void CacheMemory<ENTRY>::printData(ostream& out) const 531{ 532 out << "printData() not supported" << endl; 533} 534 535template<class ENTRY> 536void CacheMemory<ENTRY>::getMemoryValue(const Address& addr, char* value, 537 unsigned int size_in_bytes ){ 538 ENTRY entry = lookup(line_address(addr)); 539 unsigned int startByte = addr.getAddress() - line_address(addr).getAddress(); 540 for(unsigned int i=0; i<size_in_bytes; ++i){ 541 value[i] = entry.m_DataBlk.getByte(i + startByte); 542 } 543} 544 545template<class ENTRY> 546void CacheMemory<ENTRY>::setMemoryValue(const Address& addr, char* value, 547 unsigned int size_in_bytes ){ 548 ENTRY& entry = lookup(line_address(addr)); 549 unsigned int startByte = addr.getAddress() - line_address(addr).getAddress(); 550 assert(size_in_bytes > 0); 551 for(unsigned int i=0; i<size_in_bytes; ++i){ 552 entry.m_DataBlk.setByte(i + startByte, value[i]); 553 } 554 555 entry = lookup(line_address(addr)); 556} 557 558#endif //CACHEMEMORY_H 559 560