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