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