sim-ruby: checkpointing fixes and dependent eventq improvements
[gem5.git] / src / mem / ruby / system / DirectoryMemory.cc
index c87be94a230de6f56086ebc7eb69b8f8d53163f6..d2e00ab3b3e7fd8827e175fce585eb6e2b152039 100644 (file)
@@ -1,4 +1,3 @@
-
 /*
  * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
  * All rights reserved.
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-/*
- * DirectoryMemory.cc
- *
- * Description: See DirectoryMemory.hh
- *
- * $Id$
- *
- */
-
-#include "mem/ruby/system/System.hh"
-#include "mem/ruby/system/DirectoryMemory.hh"
+#include "base/intmath.hh"
+#include "debug/RubyCache.hh"
 #include "mem/ruby/slicc_interface/RubySlicc_Util.hh"
-#include "mem/ruby/slicc_interface/AbstractController.hh"
-#include "mem/gems_common/util.hh"
+#include "mem/ruby/system/DirectoryMemory.hh"
+#include "mem/ruby/system/System.hh"
+
+using namespace std;
 
 int DirectoryMemory::m_num_directories = 0;
 int DirectoryMemory::m_num_directories_bits = 0;
-int DirectoryMemory::m_total_size_bytes = 0;
+uint64_t DirectoryMemory::m_total_size_bytes = 0;
+int DirectoryMemory::m_numa_high_bit = 0;
 
-DirectoryMemory::DirectoryMemory(const string & name)
: m_name(name)
+DirectoryMemory::DirectoryMemory(const Params *p)
   : SimObject(p)
 {
+    m_version = p->version;
+    m_size_bytes = p->size;
+    m_size_bits = floorLog2(m_size_bytes);
+    m_num_entries = 0;
+    m_use_map = p->use_map;
+    m_map_levels = p->map_levels;
+    m_numa_high_bit = p->numa_high_bit;
 }
 
-void DirectoryMemory::init(const vector<string> & argv)
+void
+DirectoryMemory::init()
 {
-  m_controller = NULL;
-  for (vector<string>::const_iterator it = argv.begin(); it != argv.end(); it++) {
-    if ( (*it) == "version" )
-      m_version = atoi( (*(++it)).c_str() );
-    else if ( (*it) == "size_mb" ) {
-      m_size_bytes = atoi((*(++it)).c_str()) * static_cast<uint64>(1<<20);
-      m_size_bits = log_int(m_size_bytes);
-    } else if ( (*it) == "controller" ) {
-      m_controller = RubySystem::getController((*(++it)));
+    m_num_entries = m_size_bytes / RubySystem::getBlockSizeBytes();
+
+    if (m_use_map) {
+        m_sparseMemory = new SparseMemory(m_map_levels);
+        g_system_ptr->registerSparseMemory(m_sparseMemory);
     } else {
-      cerr << "DirectoryMemory: Unkown config parameter: " << (*it) << endl;
-      assert(0);
+        m_entries = new AbstractEntry*[m_num_entries];
+        for (int i = 0; i < m_num_entries; i++)
+            m_entries[i] = NULL;
+        m_ram = g_system_ptr->getMemoryVector();
     }
-  }
-  assert(m_controller != NULL);
 
-  m_num_entries = m_size_bytes / RubySystem::getBlockSizeBytes();
-  m_entries = new Directory_Entry*[m_num_entries];
-  for (int i=0; i < m_num_entries; i++)
-    m_entries[i] = NULL;
+    m_num_directories++;
+    m_num_directories_bits = floorLog2(m_num_directories);
+    m_total_size_bytes += m_size_bytes;
 
-  m_ram = g_system_ptr->getMemoryVector();
-
-  m_num_directories++;
-  m_num_directories_bits = log_int(m_num_directories);
-  m_total_size_bytes += m_size_bytes;
+    if (m_numa_high_bit == 0) {
+        m_numa_high_bit = RubySystem::getMemorySizeBits() - 1;
+    }
+    assert(m_numa_high_bit != 0);
 }
 
 DirectoryMemory::~DirectoryMemory()
 {
-  // free up all the directory entries
-  for (int i=0;i<m_num_entries;i++)
-    if (m_entries[i] != NULL)
-      delete m_entries;
-  if (m_entries != NULL)
-    delete [] m_entries;
+    // free up all the directory entries
+    if (m_entries != NULL) {
+        for (uint64 i = 0; i < m_num_entries; i++) {
+            if (m_entries[i] != NULL) {
+                delete m_entries[i];
+            }
+        }
+        delete [] m_entries;
+    } else if (m_use_map) {
+        delete m_sparseMemory;
+    }
 }
 
-void DirectoryMemory::printConfig(ostream& out) const
+void
+DirectoryMemory::printConfig(ostream& out) const
 {
-  out << "DirectoryMemory module config: " << m_name << endl;
-  out << "  controller: " << m_controller->getName() << endl;
-  out << "  version: " << m_version << endl;
-  out << "  memory_bits: " << m_size_bits << endl;
-  out << "  memory_size_bytes: " << m_size_bytes << endl;
-  out << "  memory_size_Kbytes: " << double(m_size_bytes) / (1<<10) << endl;
-  out << "  memory_size_Mbytes: " << double(m_size_bytes) / (1<<20) << endl;
-  out << "  memory_size_Gbytes: " << double(m_size_bytes) / (1<<30) << endl;
+    out << "DirectoryMemory module config: " << m_name << endl
+        << "  version: " << m_version << endl
+        << "  memory_bits: " << m_size_bits << endl
+        << "  memory_size_bytes: " << m_size_bytes << endl
+        << "  memory_size_Kbytes: " << double(m_size_bytes) / (1<<10) << endl
+        << "  memory_size_Mbytes: " << double(m_size_bytes) / (1<<20) << endl
+        << "  memory_size_Gbytes: " << double(m_size_bytes) / (1<<30) << endl;
 }
 
 // Static method
-void DirectoryMemory::printGlobalConfig(ostream & out)
+void
+DirectoryMemory::printGlobalConfig(ostream & out)
 {
-  out << "DirectoryMemory Global Config: " << endl;
-  out << "  number of directory memories: " << m_num_directories << endl;
-  if (m_num_directories > 1) {
-    out << "  number of selection bits: " << m_num_directories_bits << endl;
-    out << "  selection bits: " << RubySystem::getBlockSizeBits()+m_num_directories_bits-1
-        << "-" << RubySystem::getBlockSizeBits() << endl;
-  }
-  out << "  total memory size bytes: " << m_total_size_bytes << endl;
-  out << "  total memory size bits: " << log_int(m_total_size_bytes) << endl;
-
+    out << "DirectoryMemory Global Config: " << endl;
+    out << "  number of directory memories: " << m_num_directories << endl;
+    if (m_num_directories > 1) {
+        out << "  number of selection bits: " << m_num_directories_bits << endl
+            << "  selection bits: " << m_numa_high_bit
+            << "-" << m_numa_high_bit-m_num_directories_bits
+            << endl;
+    }
+    out << "  total memory size bytes: " << m_total_size_bytes << endl;
+    out << "  total memory bits: " << floorLog2(m_total_size_bytes) << endl;
 }
 
-int DirectoryMemory::mapAddressToDirectoryVersion(PhysAddress address)
+uint64
+DirectoryMemory::mapAddressToDirectoryVersion(PhysAddress address)
 {
-  if (m_num_directories_bits == 0) return 0;
-  int ret = address.bitSelect(RubySystem::getBlockSizeBits(),
-                              RubySystem::getBlockSizeBits()+m_num_directories_bits-1);
-  return ret;
+    if (m_num_directories_bits == 0)
+        return 0;
+
+    uint64 ret = address.bitSelect(m_numa_high_bit - m_num_directories_bits + 1,
+                                   m_numa_high_bit);
+    return ret;
 }
 
-// Public method
-bool DirectoryMemory::isPresent(PhysAddress address)
+bool
+DirectoryMemory::isPresent(PhysAddress address)
 {
-  bool ret = (mapAddressToDirectoryVersion(address) == m_version);
-  return ret;
+    bool ret = (mapAddressToDirectoryVersion(address) == m_version);
+    return ret;
 }
 
-int DirectoryMemory::mapAddressToLocalIdx(PhysAddress address)
+uint64
+DirectoryMemory::mapAddressToLocalIdx(PhysAddress address)
 {
-  int ret = address.getAddress() >> (RubySystem::getBlockSizeBits() + m_num_directories_bits);
-  return ret;
+    uint64 ret;
+    if (m_num_directories_bits > 0) {
+        ret = address.bitRemove(m_numa_high_bit - m_num_directories_bits + 1,
+                                m_numa_high_bit);
+    } else {
+        ret = address.getAddress();
+    }
+
+    return ret >> (RubySystem::getBlockSizeBits());
 }
 
-Directory_Entry& DirectoryMemory::lookup(PhysAddress address)
+AbstractEntry*
+DirectoryMemory::lookup(PhysAddress address)
 {
-  assert(isPresent(address));
-  Directory_Entry* entry;
-  int idx = mapAddressToLocalIdx(address);
-  entry = m_entries[idx];
-  if (entry == NULL) {
-    entry = new Directory_Entry;
-    entry->getDataBlk().assign(m_ram->getBlockPtr(address));
-    m_entries[idx] = entry;
-  }
-  return (*entry);
+    assert(isPresent(address));
+    DPRINTF(RubyCache, "Looking up address: %s\n", address);
+
+    if (m_use_map) {
+        return m_sparseMemory->lookup(address);
+    } else {
+        uint64_t idx = mapAddressToLocalIdx(address);
+        assert(idx < m_num_entries);
+        return m_entries[idx];
+    }
 }
-/*
-Directory_Entry& DirectoryMemory::lookup(PhysAddress address)
+
+AbstractEntry*
+DirectoryMemory::allocate(const PhysAddress& address, AbstractEntry* entry)
 {
-  assert(isPresent(address));
-  Index index = address.memoryModuleIndex();
-
-  if (index < 0 || index > m_size) {
-    WARN_EXPR(address.getAddress());
-    WARN_EXPR(index);
-    WARN_EXPR(m_size);
-    ERROR_MSG("Directory Memory Assertion: accessing memory out of range.");
-  }
-  Directory_Entry* entry = m_entries[index];
-
-  // allocate the directory entry on demand.
-  if (entry == NULL) {
-    entry = new Directory_Entry;
-    entry->getDataBlk().assign(m_ram->getBlockPtr(address));
-
-    // store entry to the table
-    m_entries[index] = entry;
-  }
-
-  return (*entry);
+    assert(isPresent(address));
+    uint64 idx;
+    DPRINTF(RubyCache, "Looking up address: %s\n", address);
+
+    if (m_use_map) {
+        m_sparseMemory->add(address, entry);
+        entry->changePermission(AccessPermission_Read_Write);
+    } else {
+        idx = mapAddressToLocalIdx(address);
+        assert(idx < m_num_entries);
+        entry->getDataBlk().assign(m_ram->getBlockPtr(address));
+        entry->changePermission(AccessPermission_Read_Only);
+        m_entries[idx] = entry;
+    }
+
+    return entry;
 }
-*/
 
-void DirectoryMemory::invalidateBlock(PhysAddress address)
+void
+DirectoryMemory::invalidateBlock(PhysAddress address)
 {
-  /*
-  assert(isPresent(address));
+    if (m_use_map) {
+        assert(m_sparseMemory->exist(address));
+        m_sparseMemory->remove(address);
+    }
+#if 0
+    else {
+        assert(isPresent(address));
 
-  Index index = address.memoryModuleIndex();
+        Index index = address.memoryModuleIndex();
 
-  if (index < 0 || index > m_size) {
-    ERROR_MSG("Directory Memory Assertion: accessing memory out of range.");
-  }
+        if (index < 0 || index > m_size) {
+            ERROR_MSG("Directory Memory Assertion: "
+                      "accessing memory out of range.");
+        }
 
-  if(m_entries[index] != NULL){
-    delete m_entries[index];
-    m_entries[index] = NULL;
-  }
-  */
+        if (m_entries[index] != NULL){
+            delete m_entries[index];
+            m_entries[index] = NULL;
+        }
+    }
+#endif
 }
 
-void DirectoryMemory::print(ostream& out) const
+void
+DirectoryMemory::print(ostream& out) const
 {
+}
 
+void
+DirectoryMemory::printStats(ostream& out) const
+{
+    if (m_use_map) {
+        m_sparseMemory->printStats(out);
+    }
 }
 
+DirectoryMemory *
+RubyDirectoryMemoryParams::create()
+{
+    return new DirectoryMemory(this);
+}