CacheMemory.hh revision 6145
15245Sgblack@eecs.umich.edu/*
25245Sgblack@eecs.umich.edu * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
35245Sgblack@eecs.umich.edu * All rights reserved.
45245Sgblack@eecs.umich.edu *
57087Snate@binkert.org * Redistribution and use in source and binary forms, with or without
67087Snate@binkert.org * modification, are permitted provided that the following conditions are
77087Snate@binkert.org * met: redistributions of source code must retain the above copyright
87087Snate@binkert.org * notice, this list of conditions and the following disclaimer;
97087Snate@binkert.org * redistributions in binary form must reproduce the above copyright
107087Snate@binkert.org * notice, this list of conditions and the following disclaimer in the
117087Snate@binkert.org * documentation and/or other materials provided with the distribution;
127087Snate@binkert.org * neither the name of the copyright holders nor the names of its
135245Sgblack@eecs.umich.edu * contributors may be used to endorse or promote products derived from
147087Snate@binkert.org * this software without specific prior written permission.
157087Snate@binkert.org *
167087Snate@binkert.org * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
177087Snate@binkert.org * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
187087Snate@binkert.org * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
197087Snate@binkert.org * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
207087Snate@binkert.org * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
217087Snate@binkert.org * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
225245Sgblack@eecs.umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
237087Snate@binkert.org * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
245245Sgblack@eecs.umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
255245Sgblack@eecs.umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
265245Sgblack@eecs.umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
275245Sgblack@eecs.umich.edu */
285245Sgblack@eecs.umich.edu
295245Sgblack@eecs.umich.edu/*
305245Sgblack@eecs.umich.edu * CacheMemory.h
315245Sgblack@eecs.umich.edu *
325245Sgblack@eecs.umich.edu * Description:
335245Sgblack@eecs.umich.edu *
345245Sgblack@eecs.umich.edu * $Id: CacheMemory.h,v 3.7 2004/06/18 20:15:15 beckmann Exp $
355245Sgblack@eecs.umich.edu *
365245Sgblack@eecs.umich.edu */
375245Sgblack@eecs.umich.edu
385245Sgblack@eecs.umich.edu#ifndef CACHEMEMORY_H
395245Sgblack@eecs.umich.edu#define CACHEMEMORY_H
405245Sgblack@eecs.umich.edu
415245Sgblack@eecs.umich.edu#include "AbstractChip.hh"
425245Sgblack@eecs.umich.edu#include "Global.hh"
435245Sgblack@eecs.umich.edu#include "AccessPermission.hh"
445245Sgblack@eecs.umich.edu#include "Address.hh"
455245Sgblack@eecs.umich.edu#include "CacheRecorder.hh"
465245Sgblack@eecs.umich.edu#include "CacheRequestType.hh"
478229Snate@binkert.org#include "Vector.hh"
486216Snate@binkert.org#include "DataBlock.hh"
495245Sgblack@eecs.umich.edu#include "MachineType.hh"
505245Sgblack@eecs.umich.edu#include "RubySlicc_ComponentMapping.hh"
515245Sgblack@eecs.umich.edu#include "PseudoLRUPolicy.hh"
527901Shestness@cs.utexas.edu#include "LRUPolicy.hh"
538832SAli.Saidi@ARM.com#include <vector>
545245Sgblack@eecs.umich.edu
555245Sgblack@eecs.umich.edutemplate<class ENTRY>
565245Sgblack@eecs.umich.educlass CacheMemory {
575245Sgblack@eecs.umich.edupublic:
585245Sgblack@eecs.umich.edu
595245Sgblack@eecs.umich.edu  // Constructors
605245Sgblack@eecs.umich.edu  CacheMemory(AbstractChip* chip_ptr, int numSetBits, int cacheAssoc, const MachineType machType, const string& description);
615245Sgblack@eecs.umich.edu
627912Shestness@cs.utexas.edu  // Destructor
638922Swilliam.wang@arm.com  ~CacheMemory();
645245Sgblack@eecs.umich.edu
655245Sgblack@eecs.umich.edu  // Public Methods
665245Sgblack@eecs.umich.edu  void printConfig(ostream& out);
678922Swilliam.wang@arm.com
685245Sgblack@eecs.umich.edu  // perform a cache access and see if we hit or not.  Return true on a hit.
695245Sgblack@eecs.umich.edu  bool tryCacheAccess(const Address& address, CacheRequestType type, DataBlock*& data_ptr);
705245Sgblack@eecs.umich.edu
718832SAli.Saidi@ARM.com  // similar to above, but doesn't require full access check
725245Sgblack@eecs.umich.edu  bool testCacheAccess(const Address& address, CacheRequestType type, DataBlock*& data_ptr);
735245Sgblack@eecs.umich.edu
748948Sandreas.hansson@arm.com  // tests to see if an address is present in the cache
758948Sandreas.hansson@arm.com  bool isTagPresent(const Address& address) const;
768948Sandreas.hansson@arm.com
778948Sandreas.hansson@arm.com  // Returns true if there is:
788948Sandreas.hansson@arm.com  //   a) a tag match on this address or there is
798948Sandreas.hansson@arm.com  //   b) an unused line in the same cache "way"
808948Sandreas.hansson@arm.com  bool cacheAvail(const Address& address) const;
815245Sgblack@eecs.umich.edu
828922Swilliam.wang@arm.com  // find an unused entry and sets the tag appropriate for the address
835245Sgblack@eecs.umich.edu  void allocate(const Address& address);
845245Sgblack@eecs.umich.edu
857912Shestness@cs.utexas.edu  // Explicitly free up this address
867912Shestness@cs.utexas.edu  void deallocate(const Address& address);
875245Sgblack@eecs.umich.edu
887912Shestness@cs.utexas.edu  // Returns with the physical address of the conflicting cache line
897912Shestness@cs.utexas.edu  Address cacheProbe(const Address& address) const;
907912Shestness@cs.utexas.edu
917912Shestness@cs.utexas.edu  // looks an address up in the cache
927912Shestness@cs.utexas.edu  ENTRY& lookup(const Address& address);
937912Shestness@cs.utexas.edu  const ENTRY& lookup(const Address& address) const;
947912Shestness@cs.utexas.edu
957912Shestness@cs.utexas.edu  // Get/Set permission of cache block
967912Shestness@cs.utexas.edu  AccessPermission getPermission(const Address& address) const;
977912Shestness@cs.utexas.edu  void changePermission(const Address& address, AccessPermission new_perm);
987912Shestness@cs.utexas.edu
997912Shestness@cs.utexas.edu  // Hook for checkpointing the contents of the cache
1007912Shestness@cs.utexas.edu  void recordCacheContents(CacheRecorder& tr) const;
1017912Shestness@cs.utexas.edu  void setAsInstructionCache(bool is_icache) { m_is_instruction_cache = is_icache; }
1025245Sgblack@eecs.umich.edu
1037912Shestness@cs.utexas.edu  // Set this address to most recently used
1048832SAli.Saidi@ARM.com  void setMRU(const Address& address);
1057912Shestness@cs.utexas.edu
1067912Shestness@cs.utexas.edu  void getMemoryValue(const Address& addr, char* value,
1077912Shestness@cs.utexas.edu                      unsigned int size_in_bytes );
1087912Shestness@cs.utexas.edu  void setMemoryValue(const Address& addr, char* value,
1097912Shestness@cs.utexas.edu                      unsigned int size_in_bytes );
1107912Shestness@cs.utexas.edu
1117912Shestness@cs.utexas.edu  // Print cache contents
1127912Shestness@cs.utexas.edu  void print(ostream& out) const;
1137912Shestness@cs.utexas.edu  void printData(ostream& out) const;
1147912Shestness@cs.utexas.edu
1157912Shestness@cs.utexas.eduprivate:
1167912Shestness@cs.utexas.edu  // Private Methods
1177912Shestness@cs.utexas.edu
1187912Shestness@cs.utexas.edu  // convert a Address to its location in the cache
1197912Shestness@cs.utexas.edu  Index addressToCacheSet(const Address& address) const;
1207912Shestness@cs.utexas.edu
1217912Shestness@cs.utexas.edu  // Given a cache tag: returns the index of the tag in a set.
1227912Shestness@cs.utexas.edu  // returns -1 if the tag is not found.
1237912Shestness@cs.utexas.edu  int findTagInSet(Index line, const Address& tag) const;
1247912Shestness@cs.utexas.edu  int findTagInSetIgnorePermissions(Index cacheSet, const Address& tag) const;
1257912Shestness@cs.utexas.edu
1267912Shestness@cs.utexas.edu  // Private copy constructor and assignment operator
1277912Shestness@cs.utexas.edu  CacheMemory(const CacheMemory& obj);
1287912Shestness@cs.utexas.edu  CacheMemory& operator=(const CacheMemory& obj);
1297912Shestness@cs.utexas.edu
1307912Shestness@cs.utexas.edu  // Data Members (m_prefix)
1317912Shestness@cs.utexas.edu  AbstractChip* m_chip_ptr;
1327912Shestness@cs.utexas.edu  MachineType m_machType;
1337912Shestness@cs.utexas.edu  string m_description;
1347912Shestness@cs.utexas.edu  bool m_is_instruction_cache;
1358953Sgblack@eecs.umich.edu
1367912Shestness@cs.utexas.edu  // The first index is the # of cache lines.
1377912Shestness@cs.utexas.edu  // The second index is the the amount associativity.
1387912Shestness@cs.utexas.edu  Vector<Vector<ENTRY> > m_cache;
1397912Shestness@cs.utexas.edu
1407912Shestness@cs.utexas.edu  AbstractReplacementPolicy *m_replacementPolicy_ptr;
1417912Shestness@cs.utexas.edu
1427912Shestness@cs.utexas.edu  int m_cache_num_sets;
1437912Shestness@cs.utexas.edu  int m_cache_num_set_bits;
1447912Shestness@cs.utexas.edu  int m_cache_assoc;
1457912Shestness@cs.utexas.edu};
1467912Shestness@cs.utexas.edu
1477912Shestness@cs.utexas.edu// Output operator declaration
1487912Shestness@cs.utexas.edu//ostream& operator<<(ostream& out, const CacheMemory<ENTRY>& obj);
1497912Shestness@cs.utexas.edu
1507912Shestness@cs.utexas.edu// ******************* Definitions *******************
1517912Shestness@cs.utexas.edu
1527912Shestness@cs.utexas.edu// Output operator definition
1537912Shestness@cs.utexas.edutemplate<class ENTRY>
1547912Shestness@cs.utexas.eduinline
1557912Shestness@cs.utexas.eduostream& operator<<(ostream& out, const CacheMemory<ENTRY>& obj)
1567912Shestness@cs.utexas.edu{
1577912Shestness@cs.utexas.edu  obj.print(out);
1587912Shestness@cs.utexas.edu  out << flush;
1597912Shestness@cs.utexas.edu  return out;
1607912Shestness@cs.utexas.edu}
1617912Shestness@cs.utexas.edu
1627912Shestness@cs.utexas.edu
1637912Shestness@cs.utexas.edu// ****************************************************************
1647912Shestness@cs.utexas.edu
1657912Shestness@cs.utexas.edutemplate<class ENTRY>
1667912Shestness@cs.utexas.eduinline
1677912Shestness@cs.utexas.eduCacheMemory<ENTRY>::CacheMemory(AbstractChip* chip_ptr, int numSetBits,
1687912Shestness@cs.utexas.edu                                      int cacheAssoc, const MachineType machType, const string& description)
1697912Shestness@cs.utexas.edu
1707912Shestness@cs.utexas.edu{
1717912Shestness@cs.utexas.edu  //cout << "CacheMemory constructor numThreads = " << numThreads << endl;
1728953Sgblack@eecs.umich.edu  m_chip_ptr = chip_ptr;
1738922Swilliam.wang@arm.com  m_machType = machType;
1747912Shestness@cs.utexas.edu  m_description = MachineType_to_string(m_machType)+"_"+description;
1757912Shestness@cs.utexas.edu  m_cache_num_set_bits = numSetBits;
1765245Sgblack@eecs.umich.edu  m_cache_num_sets = 1 << numSetBits;
1775245Sgblack@eecs.umich.edu  m_cache_assoc = cacheAssoc;
1785245Sgblack@eecs.umich.edu  m_is_instruction_cache = false;
1798832SAli.Saidi@ARM.com
1805245Sgblack@eecs.umich.edu  m_cache.setSize(m_cache_num_sets);
1817912Shestness@cs.utexas.edu  if(strcmp(g_REPLACEMENT_POLICY, "PSEDUO_LRU") == 0)
1827912Shestness@cs.utexas.edu    m_replacementPolicy_ptr = new PseudoLRUPolicy(m_cache_num_sets, m_cache_assoc);
1837912Shestness@cs.utexas.edu  else if(strcmp(g_REPLACEMENT_POLICY, "LRU") == 0)
1847912Shestness@cs.utexas.edu    m_replacementPolicy_ptr = new LRUPolicy(m_cache_num_sets, m_cache_assoc);
1855245Sgblack@eecs.umich.edu  else
1865245Sgblack@eecs.umich.edu    assert(false);
1875245Sgblack@eecs.umich.edu  for (int i = 0; i < m_cache_num_sets; i++) {
1885245Sgblack@eecs.umich.edu    m_cache[i].setSize(m_cache_assoc);
1895245Sgblack@eecs.umich.edu    for (int j = 0; j < m_cache_assoc; j++) {
1905245Sgblack@eecs.umich.edu      m_cache[i][j].m_Address.setAddress(0);
1915245Sgblack@eecs.umich.edu      m_cache[i][j].m_Permission = AccessPermission_NotPresent;
1925245Sgblack@eecs.umich.edu    }
1935245Sgblack@eecs.umich.edu  }
1945245Sgblack@eecs.umich.edu
1958832SAli.Saidi@ARM.com
1968832SAli.Saidi@ARM.com  //  cout << "Before setting trans address list size" << endl;
1978832SAli.Saidi@ARM.com  //create a trans address for each SMT thread
1988832SAli.Saidi@ARM.com//   m_trans_address_list.setSize(numThreads);
1998832SAli.Saidi@ARM.com//   for(int i=0; i < numThreads; ++i){
2008832SAli.Saidi@ARM.com//     cout << "Setting list size for list " << i << endl;
2015245Sgblack@eecs.umich.edu//     m_trans_address_list[i].setSize(30);
2027912Shestness@cs.utexas.edu//   }
2038832SAli.Saidi@ARM.com  //cout << "CacheMemory constructor finished" << endl;
2048832SAli.Saidi@ARM.com}
2055245Sgblack@eecs.umich.edu
2065245Sgblack@eecs.umich.edutemplate<class ENTRY>
2075245Sgblack@eecs.umich.eduinline
2085245Sgblack@eecs.umich.eduCacheMemory<ENTRY>::~CacheMemory()
2095245Sgblack@eecs.umich.edu{
210  if(m_replacementPolicy_ptr != NULL)
211    delete m_replacementPolicy_ptr;
212}
213
214template<class ENTRY>
215inline
216void CacheMemory<ENTRY>::printConfig(ostream& out)
217{
218  out << "Cache config: " << m_description << endl;
219  out << "  cache_associativity: " << m_cache_assoc << endl;
220  out << "  num_cache_sets_bits: " << m_cache_num_set_bits << endl;
221  const int cache_num_sets = 1 << m_cache_num_set_bits;
222  out << "  num_cache_sets: " << cache_num_sets << endl;
223  out << "  cache_set_size_bytes: " << cache_num_sets * RubyConfig::dataBlockBytes() << endl;
224  out << "  cache_set_size_Kbytes: "
225      << double(cache_num_sets * RubyConfig::dataBlockBytes()) / (1<<10) << endl;
226  out << "  cache_set_size_Mbytes: "
227      << double(cache_num_sets * RubyConfig::dataBlockBytes()) / (1<<20) << endl;
228  out << "  cache_size_bytes: "
229      << cache_num_sets * RubyConfig::dataBlockBytes() * m_cache_assoc << endl;
230  out << "  cache_size_Kbytes: "
231      << double(cache_num_sets * RubyConfig::dataBlockBytes() * m_cache_assoc) / (1<<10) << endl;
232  out << "  cache_size_Mbytes: "
233      << double(cache_num_sets * RubyConfig::dataBlockBytes() * m_cache_assoc) / (1<<20) << endl;
234}
235
236// PRIVATE METHODS
237
238// convert a Address to its location in the cache
239template<class ENTRY>
240inline
241Index CacheMemory<ENTRY>::addressToCacheSet(const Address& address) const
242{
243  assert(address == line_address(address));
244  Index temp = -1;
245  switch (m_machType) {
246  case MACHINETYPE_L1CACHE_ENUM:
247    temp = map_address_to_L1CacheSet(address, m_cache_num_set_bits);
248    break;
249  case MACHINETYPE_L2CACHE_ENUM:
250    temp = map_address_to_L2CacheSet(address, m_cache_num_set_bits);
251    break;
252  default:
253    ERROR_MSG("Don't recognize m_machType");
254  }
255  assert(temp < m_cache_num_sets);
256  assert(temp >= 0);
257  return temp;
258}
259
260// Given a cache index: returns the index of the tag in a set.
261// returns -1 if the tag is not found.
262template<class ENTRY>
263inline
264int CacheMemory<ENTRY>::findTagInSet(Index cacheSet, const Address& tag) const
265{
266  assert(tag == line_address(tag));
267  // search the set for the tags
268  for (int i=0; i < m_cache_assoc; i++) {
269    if ((m_cache[cacheSet][i].m_Address == tag) &&
270        (m_cache[cacheSet][i].m_Permission != AccessPermission_NotPresent)) {
271      return i;
272    }
273  }
274  return -1; // Not found
275}
276
277// Given a cache index: returns the index of the tag in a set.
278// returns -1 if the tag is not found.
279template<class ENTRY>
280inline
281int CacheMemory<ENTRY>::findTagInSetIgnorePermissions(Index cacheSet, const Address& tag) const
282{
283  assert(tag == line_address(tag));
284  // search the set for the tags
285  for (int i=0; i < m_cache_assoc; i++) {
286    if (m_cache[cacheSet][i].m_Address == tag)
287      return i;
288  }
289  return -1; // Not found
290}
291
292// PUBLIC METHODS
293template<class ENTRY>
294inline
295bool CacheMemory<ENTRY>::tryCacheAccess(const Address& address,
296                                           CacheRequestType type,
297                                           DataBlock*& data_ptr)
298{
299  assert(address == line_address(address));
300  DEBUG_EXPR(CACHE_COMP, HighPrio, address);
301  Index cacheSet = addressToCacheSet(address);
302  int loc = findTagInSet(cacheSet, address);
303  if(loc != -1){ // Do we even have a tag match?
304    ENTRY& entry = m_cache[cacheSet][loc];
305    m_replacementPolicy_ptr->touch(cacheSet, loc, g_eventQueue_ptr->getTime());
306    data_ptr = &(entry.getDataBlk());
307
308    if(entry.m_Permission == AccessPermission_Read_Write) {
309      return true;
310    }
311    if ((entry.m_Permission == AccessPermission_Read_Only) &&
312        (type == CacheRequestType_LD || type == CacheRequestType_IFETCH)) {
313      return true;
314    }
315    // The line must not be accessible
316  }
317  data_ptr = NULL;
318  return false;
319}
320
321template<class ENTRY>
322inline
323bool CacheMemory<ENTRY>::testCacheAccess(const Address& address,
324                                           CacheRequestType type,
325                                           DataBlock*& data_ptr)
326{
327  assert(address == line_address(address));
328  DEBUG_EXPR(CACHE_COMP, HighPrio, address);
329  Index cacheSet = addressToCacheSet(address);
330  int loc = findTagInSet(cacheSet, address);
331  if(loc != -1){ // Do we even have a tag match?
332    ENTRY& entry = m_cache[cacheSet][loc];
333    m_replacementPolicy_ptr->touch(cacheSet, loc, g_eventQueue_ptr->getTime());
334    data_ptr = &(entry.getDataBlk());
335
336    return (m_cache[cacheSet][loc].m_Permission != AccessPermission_NotPresent);
337  }
338  data_ptr = NULL;
339  return false;
340}
341
342// tests to see if an address is present in the cache
343template<class ENTRY>
344inline
345bool CacheMemory<ENTRY>::isTagPresent(const Address& address) const
346{
347  assert(address == line_address(address));
348  Index cacheSet = addressToCacheSet(address);
349  int location = findTagInSet(cacheSet, address);
350
351  if (location == -1) {
352    // We didn't find the tag
353    DEBUG_EXPR(CACHE_COMP, LowPrio, address);
354    DEBUG_MSG(CACHE_COMP, LowPrio, "No tag match");
355    return false;
356  }
357  DEBUG_EXPR(CACHE_COMP, LowPrio, address);
358  DEBUG_MSG(CACHE_COMP, LowPrio, "found");
359  return true;
360}
361
362// Returns true if there is:
363//   a) a tag match on this address or there is
364//   b) an unused line in the same cache "way"
365template<class ENTRY>
366inline
367bool CacheMemory<ENTRY>::cacheAvail(const Address& address) const
368{
369  assert(address == line_address(address));
370
371  Index cacheSet = addressToCacheSet(address);
372
373  for (int i=0; i < m_cache_assoc; i++) {
374    if (m_cache[cacheSet][i].m_Address == address) {
375      // Already in the cache
376      return true;
377    }
378
379    if (m_cache[cacheSet][i].m_Permission == AccessPermission_NotPresent) {
380      // We found an empty entry
381      return true;
382    }
383  }
384  return false;
385}
386
387template<class ENTRY>
388inline
389void CacheMemory<ENTRY>::allocate(const Address& address)
390{
391  assert(address == line_address(address));
392  assert(!isTagPresent(address));
393  assert(cacheAvail(address));
394  DEBUG_EXPR(CACHE_COMP, HighPrio, address);
395
396  // Find the first open slot
397  Index cacheSet = addressToCacheSet(address);
398  for (int i=0; i < m_cache_assoc; i++) {
399    if (m_cache[cacheSet][i].m_Permission == AccessPermission_NotPresent) {
400      m_cache[cacheSet][i] = ENTRY();  // Init entry
401      m_cache[cacheSet][i].m_Address = address;
402      m_cache[cacheSet][i].m_Permission = AccessPermission_Invalid;
403
404      m_replacementPolicy_ptr->touch(cacheSet, i, g_eventQueue_ptr->getTime());
405
406      return;
407    }
408  }
409  ERROR_MSG("Allocate didn't find an available entry");
410}
411
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