DirectoryMemory.cc revision 7025
14120Sgblack@eecs.umich.edu
24120Sgblack@eecs.umich.edu/*
37087Snate@binkert.org * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
47087Snate@binkert.org * All rights reserved.
57087Snate@binkert.org *
67087Snate@binkert.org * Redistribution and use in source and binary forms, with or without
77087Snate@binkert.org * modification, are permitted provided that the following conditions are
87087Snate@binkert.org * met: redistributions of source code must retain the above copyright
97087Snate@binkert.org * notice, this list of conditions and the following disclaimer;
107087Snate@binkert.org * redistributions in binary form must reproduce the above copyright
117087Snate@binkert.org * notice, this list of conditions and the following disclaimer in the
127087Snate@binkert.org * documentation and/or other materials provided with the distribution;
137087Snate@binkert.org * neither the name of the copyright holders nor the names of its
147087Snate@binkert.org * contributors may be used to endorse or promote products derived from
154120Sgblack@eecs.umich.edu * this software without specific prior written permission.
164120Sgblack@eecs.umich.edu *
174120Sgblack@eecs.umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
184120Sgblack@eecs.umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
194120Sgblack@eecs.umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
204120Sgblack@eecs.umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
214120Sgblack@eecs.umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
224120Sgblack@eecs.umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
234120Sgblack@eecs.umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
244120Sgblack@eecs.umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
254120Sgblack@eecs.umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
264120Sgblack@eecs.umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
274120Sgblack@eecs.umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
284120Sgblack@eecs.umich.edu */
294120Sgblack@eecs.umich.edu
304120Sgblack@eecs.umich.edu/*
314120Sgblack@eecs.umich.edu * DirectoryMemory.cc
324120Sgblack@eecs.umich.edu *
334120Sgblack@eecs.umich.edu * Description: See DirectoryMemory.hh
344120Sgblack@eecs.umich.edu *
354120Sgblack@eecs.umich.edu * $Id$
364120Sgblack@eecs.umich.edu *
374120Sgblack@eecs.umich.edu */
384120Sgblack@eecs.umich.edu
394120Sgblack@eecs.umich.edu#include "mem/ruby/system/System.hh"
404120Sgblack@eecs.umich.edu#include "mem/ruby/system/DirectoryMemory.hh"
414120Sgblack@eecs.umich.edu#include "mem/ruby/slicc_interface/RubySlicc_Util.hh"
424120Sgblack@eecs.umich.edu#include "mem/gems_common/util.hh"
434202Sbinkertn@umich.edu
445069Sgblack@eecs.umich.eduint DirectoryMemory::m_num_directories = 0;
454202Sbinkertn@umich.eduint DirectoryMemory::m_num_directories_bits = 0;
465659Sgblack@eecs.umich.eduuint64_t DirectoryMemory::m_total_size_bytes = 0;
479022Sgblack@eecs.umich.edu
489023Sgblack@eecs.umich.eduDirectoryMemory::DirectoryMemory(const Params *p)
494601Sgblack@eecs.umich.edu    : SimObject(p)
505124Sgblack@eecs.umich.edu{
517966Sgblack@eecs.umich.edu    m_version = p->version;
525083Sgblack@eecs.umich.edu    m_size_bytes = p->size;
534679Sgblack@eecs.umich.edu    m_size_bits = log_int(m_size_bytes);
546515Sgblack@eecs.umich.edu    m_num_entries = 0;
555083Sgblack@eecs.umich.edu    m_use_map = p->use_map;
564679Sgblack@eecs.umich.edu    m_map_levels = p->map_levels;
574679Sgblack@eecs.umich.edu}
588745Sgblack@eecs.umich.edu
596313Sgblack@eecs.umich.eduvoid DirectoryMemory::init()
608771Sgblack@eecs.umich.edu{
618771Sgblack@eecs.umich.edu  m_num_entries = m_size_bytes / RubySystem::getBlockSizeBytes();
628771Sgblack@eecs.umich.edu
638771Sgblack@eecs.umich.edu  if (m_use_map) {
646365Sgblack@eecs.umich.edu      int entry_bits = log_int(m_num_entries);
655124Sgblack@eecs.umich.edu      assert(entry_bits >= m_map_levels);
668752Sgblack@eecs.umich.edu      m_sparseMemory = new SparseMemory(entry_bits, m_map_levels);
678771Sgblack@eecs.umich.edu  } else {
684202Sbinkertn@umich.edu      m_entries = new Directory_Entry*[m_num_entries];
698771Sgblack@eecs.umich.edu      for (int i=0; i < m_num_entries; i++)
708771Sgblack@eecs.umich.edu          m_entries[i] = NULL;
714997Sgblack@eecs.umich.edu  }
727624Sgblack@eecs.umich.edu
735135Sgblack@eecs.umich.edu  m_ram = g_system_ptr->getMemoryVector();
748753Sgblack@eecs.umich.edu
754997Sgblack@eecs.umich.edu  m_num_directories++;
768745Sgblack@eecs.umich.edu  m_num_directories_bits = log_int(m_num_directories);
776365Sgblack@eecs.umich.edu  m_total_size_bytes += m_size_bytes;
788771Sgblack@eecs.umich.edu}
798740Sgblack@eecs.umich.edu
806365Sgblack@eecs.umich.eduDirectoryMemory::~DirectoryMemory()
818740Sgblack@eecs.umich.edu{
828745Sgblack@eecs.umich.edu  // free up all the directory entries
838752Sgblack@eecs.umich.edu  if (m_entries != NULL) {
848752Sgblack@eecs.umich.edu      for (uint64 i = 0; i < m_num_entries; i++) {
859023Sgblack@eecs.umich.edu          if (m_entries[i] != NULL) {
868335Snate@binkert.org              delete m_entries[i];
874120Sgblack@eecs.umich.edu          }
885069Sgblack@eecs.umich.edu      }
895081Sgblack@eecs.umich.edu      delete [] m_entries;
905081Sgblack@eecs.umich.edu  } else if (m_use_map) {
915081Sgblack@eecs.umich.edu      delete m_sparseMemory;
925081Sgblack@eecs.umich.edu  }
935081Sgblack@eecs.umich.edu}
945081Sgblack@eecs.umich.edu
955081Sgblack@eecs.umich.eduvoid DirectoryMemory::printConfig(ostream& out) const
965081Sgblack@eecs.umich.edu{
975081Sgblack@eecs.umich.edu  out << "DirectoryMemory module config: " << m_name << endl;
985081Sgblack@eecs.umich.edu  out << "  version: " << m_version << endl;
995081Sgblack@eecs.umich.edu  out << "  memory_bits: " << m_size_bits << endl;
1005081Sgblack@eecs.umich.edu  out << "  memory_size_bytes: " << m_size_bytes << endl;
1015081Sgblack@eecs.umich.edu  out << "  memory_size_Kbytes: " << double(m_size_bytes) / (1<<10) << endl;
1025081Sgblack@eecs.umich.edu  out << "  memory_size_Mbytes: " << double(m_size_bytes) / (1<<20) << endl;
1035081Sgblack@eecs.umich.edu  out << "  memory_size_Gbytes: " << double(m_size_bytes) / (1<<30) << endl;
1045081Sgblack@eecs.umich.edu}
1055081Sgblack@eecs.umich.edu
1065081Sgblack@eecs.umich.edu// Static method
1075081Sgblack@eecs.umich.eduvoid DirectoryMemory::printGlobalConfig(ostream & out)
1085081Sgblack@eecs.umich.edu{
1095081Sgblack@eecs.umich.edu  out << "DirectoryMemory Global Config: " << endl;
1105081Sgblack@eecs.umich.edu  out << "  number of directory memories: " << m_num_directories << endl;
1115081Sgblack@eecs.umich.edu  if (m_num_directories > 1) {
1125081Sgblack@eecs.umich.edu    out << "  number of selection bits: " << m_num_directories_bits << endl;
1135081Sgblack@eecs.umich.edu    out << "  selection bits: " << RubySystem::getBlockSizeBits()+m_num_directories_bits-1
1145081Sgblack@eecs.umich.edu        << "-" << RubySystem::getBlockSizeBits() << endl;
1155081Sgblack@eecs.umich.edu  }
1165081Sgblack@eecs.umich.edu  out << "  total memory size bytes: " << m_total_size_bytes << endl;
1175081Sgblack@eecs.umich.edu  out << "  total memory bits: " << log_int(m_total_size_bytes) << endl;
1185081Sgblack@eecs.umich.edu
1195081Sgblack@eecs.umich.edu}
1205081Sgblack@eecs.umich.edu
1215081Sgblack@eecs.umich.eduuint64 DirectoryMemory::mapAddressToDirectoryVersion(PhysAddress address)
1225081Sgblack@eecs.umich.edu{
1235081Sgblack@eecs.umich.edu  if (m_num_directories_bits == 0) return 0;
1245081Sgblack@eecs.umich.edu  uint64 ret = address.bitSelect(RubySystem::getBlockSizeBits(),
1255081Sgblack@eecs.umich.edu                              RubySystem::getBlockSizeBits()+m_num_directories_bits-1);
1265081Sgblack@eecs.umich.edu  return ret;
1275081Sgblack@eecs.umich.edu}
1285081Sgblack@eecs.umich.edu
1295081Sgblack@eecs.umich.edu// Public method
1305081Sgblack@eecs.umich.edubool DirectoryMemory::isPresent(PhysAddress address)
1315081Sgblack@eecs.umich.edu{
1325081Sgblack@eecs.umich.edu  bool ret = (mapAddressToDirectoryVersion(address) == m_version);
1335081Sgblack@eecs.umich.edu  return ret;
1345081Sgblack@eecs.umich.edu}
1355081Sgblack@eecs.umich.edu
1365081Sgblack@eecs.umich.eduuint64 DirectoryMemory::mapAddressToLocalIdx(PhysAddress address)
1375081Sgblack@eecs.umich.edu{
1385081Sgblack@eecs.umich.edu  uint64 ret = address.getAddress()
1395081Sgblack@eecs.umich.edu      >> (RubySystem::getBlockSizeBits() + m_num_directories_bits);
1405081Sgblack@eecs.umich.edu  return ret;
1415081Sgblack@eecs.umich.edu}
1425081Sgblack@eecs.umich.edu
1435081Sgblack@eecs.umich.eduDirectory_Entry& DirectoryMemory::lookup(PhysAddress address)
1445680Sgblack@eecs.umich.edu{
1455081Sgblack@eecs.umich.edu  assert(isPresent(address));
1465933Sgblack@eecs.umich.edu  Directory_Entry* entry;
1475173Sgblack@eecs.umich.edu  uint64 idx;
1485359Sgblack@eecs.umich.edu  DEBUG_EXPR(CACHE_COMP, HighPrio, address);
1495081Sgblack@eecs.umich.edu
1505149Sgblack@eecs.umich.edu  if (m_use_map) {
1515298Sgblack@eecs.umich.edu    if (m_sparseMemory->exist(address)) {
1525081Sgblack@eecs.umich.edu      entry = m_sparseMemory->lookup(address);
1535081Sgblack@eecs.umich.edu      assert(entry != NULL);
1545081Sgblack@eecs.umich.edu    } else {
1555081Sgblack@eecs.umich.edu      //
1565081Sgblack@eecs.umich.edu      // Note: SparseMemory internally creates a new Directory Entry
1575081Sgblack@eecs.umich.edu      //
1585081Sgblack@eecs.umich.edu      m_sparseMemory->add(address);
1595081Sgblack@eecs.umich.edu      entry = m_sparseMemory->lookup(address);
1605081Sgblack@eecs.umich.edu    }
1615081Sgblack@eecs.umich.edu  } else {
1625081Sgblack@eecs.umich.edu    idx = mapAddressToLocalIdx(address);
1635081Sgblack@eecs.umich.edu    assert(idx < m_num_entries);
1645081Sgblack@eecs.umich.edu    entry = m_entries[idx];
1655081Sgblack@eecs.umich.edu
1665081Sgblack@eecs.umich.edu    if (entry == NULL) {
1675081Sgblack@eecs.umich.edu      entry = new Directory_Entry();
1685081Sgblack@eecs.umich.edu      entry->getDataBlk().assign(m_ram->getBlockPtr(address));
1695081Sgblack@eecs.umich.edu      m_entries[idx] = entry;
1705081Sgblack@eecs.umich.edu    }
1715081Sgblack@eecs.umich.edu  }
1725081Sgblack@eecs.umich.edu
1735081Sgblack@eecs.umich.edu  return (*entry);
1745081Sgblack@eecs.umich.edu}
1755081Sgblack@eecs.umich.edu/*
1765081Sgblack@eecs.umich.eduDirectory_Entry& DirectoryMemory::lookup(PhysAddress address)
1775081Sgblack@eecs.umich.edu{
1785081Sgblack@eecs.umich.edu  assert(isPresent(address));
1795081Sgblack@eecs.umich.edu  Index index = address.memoryModuleIndex();
1805081Sgblack@eecs.umich.edu
1815081Sgblack@eecs.umich.edu  if (index < 0 || index > m_size) {
1825081Sgblack@eecs.umich.edu    WARN_EXPR(address.getAddress());
1835081Sgblack@eecs.umich.edu    WARN_EXPR(index);
1845081Sgblack@eecs.umich.edu    WARN_EXPR(m_size);
1855081Sgblack@eecs.umich.edu    ERROR_MSG("Directory Memory Assertion: accessing memory out of range.");
1865081Sgblack@eecs.umich.edu  }
1875081Sgblack@eecs.umich.edu  Directory_Entry* entry = m_entries[index];
1885081Sgblack@eecs.umich.edu
1895081Sgblack@eecs.umich.edu  // allocate the directory entry on demand.
1905081Sgblack@eecs.umich.edu  if (entry == NULL) {
1915081Sgblack@eecs.umich.edu    entry = new Directory_Entry;
1925081Sgblack@eecs.umich.edu    entry->getDataBlk().assign(m_ram->getBlockPtr(address));
1935081Sgblack@eecs.umich.edu
1945081Sgblack@eecs.umich.edu    // store entry to the table
1955081Sgblack@eecs.umich.edu    m_entries[index] = entry;
1965081Sgblack@eecs.umich.edu  }
1975081Sgblack@eecs.umich.edu
1985081Sgblack@eecs.umich.edu  return (*entry);
1995081Sgblack@eecs.umich.edu}
2005081Sgblack@eecs.umich.edu*/
2015081Sgblack@eecs.umich.edu
2025081Sgblack@eecs.umich.eduvoid DirectoryMemory::invalidateBlock(PhysAddress address)
2035081Sgblack@eecs.umich.edu{
2045081Sgblack@eecs.umich.edu
2055081Sgblack@eecs.umich.edu  if (m_use_map) {
2065081Sgblack@eecs.umich.edu    assert(m_sparseMemory->exist(address));
2075081Sgblack@eecs.umich.edu    m_sparseMemory->remove(address);
2085081Sgblack@eecs.umich.edu  }
2095081Sgblack@eecs.umich.edu  /*
2105081Sgblack@eecs.umich.edu  else {
2115081Sgblack@eecs.umich.edu    assert(isPresent(address));
2125081Sgblack@eecs.umich.edu
2135081Sgblack@eecs.umich.edu    Index index = address.memoryModuleIndex();
2145081Sgblack@eecs.umich.edu
2155081Sgblack@eecs.umich.edu    if (index < 0 || index > m_size) {
2165081Sgblack@eecs.umich.edu      ERROR_MSG("Directory Memory Assertion: accessing memory out of range.");
2175081Sgblack@eecs.umich.edu    }
2185081Sgblack@eecs.umich.edu
2195081Sgblack@eecs.umich.edu    if(m_entries[index] != NULL){
2205081Sgblack@eecs.umich.edu      delete m_entries[index];
2215081Sgblack@eecs.umich.edu      m_entries[index] = NULL;
2225081Sgblack@eecs.umich.edu    }
2235081Sgblack@eecs.umich.edu  }
2245081Sgblack@eecs.umich.edu  */
2255081Sgblack@eecs.umich.edu
2265081Sgblack@eecs.umich.edu
2275081Sgblack@eecs.umich.edu}
2285081Sgblack@eecs.umich.edu
2295081Sgblack@eecs.umich.eduvoid DirectoryMemory::print(ostream& out) const
2305081Sgblack@eecs.umich.edu{
2315081Sgblack@eecs.umich.edu
2325081Sgblack@eecs.umich.edu}
2335081Sgblack@eecs.umich.edu
2345081Sgblack@eecs.umich.eduvoid DirectoryMemory::printStats(ostream& out) const
2355081Sgblack@eecs.umich.edu{
2365081Sgblack@eecs.umich.edu    if (m_use_map) {
2375081Sgblack@eecs.umich.edu        m_sparseMemory->printStats(out);
2385081Sgblack@eecs.umich.edu    }
2395081Sgblack@eecs.umich.edu}
2405081Sgblack@eecs.umich.edu
2415081Sgblack@eecs.umich.eduDirectoryMemory *
2425081Sgblack@eecs.umich.eduRubyDirectoryMemoryParams::create()
2435081Sgblack@eecs.umich.edu{
2445081Sgblack@eecs.umich.edu    return new DirectoryMemory(this);
2455081Sgblack@eecs.umich.edu}
2465081Sgblack@eecs.umich.edu