DirectoryMemory.cc revision 8688
1955SN/A/*
2955SN/A * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
31762SN/A * All rights reserved.
4955SN/A *
5955SN/A * Redistribution and use in source and binary forms, with or without
6955SN/A * modification, are permitted provided that the following conditions are
7955SN/A * met: redistributions of source code must retain the above copyright
8955SN/A * notice, this list of conditions and the following disclaimer;
9955SN/A * redistributions in binary form must reproduce the above copyright
10955SN/A * notice, this list of conditions and the following disclaimer in the
11955SN/A * documentation and/or other materials provided with the distribution;
12955SN/A * neither the name of the copyright holders nor the names of its
13955SN/A * contributors may be used to endorse or promote products derived from
14955SN/A * this software without specific prior written permission.
15955SN/A *
16955SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17955SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18955SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19955SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20955SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21955SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22955SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23955SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24955SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25955SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26955SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27955SN/A */
282665Ssaidi@eecs.umich.edu
294762Snate@binkert.org#include "base/intmath.hh"
30955SN/A#include "debug/RubyCache.hh"
315522Snate@binkert.org#include "mem/ruby/slicc_interface/RubySlicc_Util.hh"
326143Snate@binkert.org#include "mem/ruby/system/DirectoryMemory.hh"
334762Snate@binkert.org#include "mem/ruby/system/System.hh"
345522Snate@binkert.org
35955SN/Ausing namespace std;
365522Snate@binkert.org
37955SN/Aint DirectoryMemory::m_num_directories = 0;
385522Snate@binkert.orgint DirectoryMemory::m_num_directories_bits = 0;
394202Sbinkertn@umich.eduuint64_t DirectoryMemory::m_total_size_bytes = 0;
405742Snate@binkert.orgint DirectoryMemory::m_numa_high_bit = 0;
41955SN/A
424381Sbinkertn@umich.eduDirectoryMemory::DirectoryMemory(const Params *p)
434381Sbinkertn@umich.edu    : SimObject(p)
44955SN/A{
45955SN/A    m_version = p->version;
46955SN/A    m_size_bytes = p->size;
474202Sbinkertn@umich.edu    m_size_bits = floorLog2(m_size_bytes);
48955SN/A    m_num_entries = 0;
494382Sbinkertn@umich.edu    m_use_map = p->use_map;
504382Sbinkertn@umich.edu    m_map_levels = p->map_levels;
514382Sbinkertn@umich.edu    m_numa_high_bit = p->numa_high_bit;
526654Snate@binkert.org}
535517Snate@binkert.org
547674Snate@binkert.orgvoid
557674Snate@binkert.orgDirectoryMemory::init()
566143Snate@binkert.org{
576143Snate@binkert.org    m_num_entries = m_size_bytes / RubySystem::getBlockSizeBytes();
586143Snate@binkert.org
596143Snate@binkert.org    if (m_use_map) {
606143Snate@binkert.org        m_sparseMemory = new SparseMemory(m_map_levels);
616143Snate@binkert.org        g_system_ptr->registerSparseMemory(m_sparseMemory);
626143Snate@binkert.org    } else {
636143Snate@binkert.org        m_entries = new AbstractEntry*[m_num_entries];
646143Snate@binkert.org        for (int i = 0; i < m_num_entries; i++)
656143Snate@binkert.org            m_entries[i] = NULL;
666143Snate@binkert.org        m_ram = g_system_ptr->getMemoryVector();
676143Snate@binkert.org    }
686143Snate@binkert.org
696143Snate@binkert.org    m_num_directories++;
706143Snate@binkert.org    m_num_directories_bits = floorLog2(m_num_directories);
714762Snate@binkert.org    m_total_size_bytes += m_size_bytes;
726143Snate@binkert.org
736143Snate@binkert.org    if (m_numa_high_bit == 0) {
746143Snate@binkert.org        m_numa_high_bit = RubySystem::getMemorySizeBits() - 1;
756143Snate@binkert.org    }
766143Snate@binkert.org    assert(m_numa_high_bit != 0);
776143Snate@binkert.org}
786143Snate@binkert.org
796143Snate@binkert.orgDirectoryMemory::~DirectoryMemory()
806143Snate@binkert.org{
816143Snate@binkert.org    // free up all the directory entries
826143Snate@binkert.org    if (m_entries != NULL) {
836143Snate@binkert.org        for (uint64 i = 0; i < m_num_entries; i++) {
846143Snate@binkert.org            if (m_entries[i] != NULL) {
856143Snate@binkert.org                delete m_entries[i];
866143Snate@binkert.org            }
876143Snate@binkert.org        }
886143Snate@binkert.org        delete [] m_entries;
896143Snate@binkert.org    } else if (m_use_map) {
906143Snate@binkert.org        delete m_sparseMemory;
916143Snate@binkert.org    }
926143Snate@binkert.org}
937065Snate@binkert.org
946143Snate@binkert.orgvoid
956143Snate@binkert.orgDirectoryMemory::printConfig(ostream& out) const
966143Snate@binkert.org{
976143Snate@binkert.org    out << "DirectoryMemory module config: " << m_name << endl
986143Snate@binkert.org        << "  version: " << m_version << endl
996143Snate@binkert.org        << "  memory_bits: " << m_size_bits << endl
1006143Snate@binkert.org        << "  memory_size_bytes: " << m_size_bytes << endl
1016143Snate@binkert.org        << "  memory_size_Kbytes: " << double(m_size_bytes) / (1<<10) << endl
1026143Snate@binkert.org        << "  memory_size_Mbytes: " << double(m_size_bytes) / (1<<20) << endl
1036143Snate@binkert.org        << "  memory_size_Gbytes: " << double(m_size_bytes) / (1<<30) << endl;
1046143Snate@binkert.org}
1056143Snate@binkert.org
1066143Snate@binkert.org// Static method
1076143Snate@binkert.orgvoid
1086143Snate@binkert.orgDirectoryMemory::printGlobalConfig(ostream & out)
1096143Snate@binkert.org{
1106143Snate@binkert.org    out << "DirectoryMemory Global Config: " << endl;
1116143Snate@binkert.org    out << "  number of directory memories: " << m_num_directories << endl;
1126143Snate@binkert.org    if (m_num_directories > 1) {
1136143Snate@binkert.org        out << "  number of selection bits: " << m_num_directories_bits << endl
1146143Snate@binkert.org            << "  selection bits: " << m_numa_high_bit
1155522Snate@binkert.org            << "-" << m_numa_high_bit-m_num_directories_bits
1166143Snate@binkert.org            << endl;
1176143Snate@binkert.org    }
1186143Snate@binkert.org    out << "  total memory size bytes: " << m_total_size_bytes << endl;
1196143Snate@binkert.org    out << "  total memory bits: " << floorLog2(m_total_size_bytes) << endl;
1206143Snate@binkert.org}
1216143Snate@binkert.org
1226143Snate@binkert.orguint64
1236143Snate@binkert.orgDirectoryMemory::mapAddressToDirectoryVersion(PhysAddress address)
1246143Snate@binkert.org{
1256143Snate@binkert.org    if (m_num_directories_bits == 0)
1265522Snate@binkert.org        return 0;
1275522Snate@binkert.org
1285522Snate@binkert.org    uint64 ret = address.bitSelect(m_numa_high_bit - m_num_directories_bits + 1,
1295522Snate@binkert.org                                   m_numa_high_bit);
1305604Snate@binkert.org    return ret;
1315604Snate@binkert.org}
1326143Snate@binkert.org
1336143Snate@binkert.orgbool
1344762Snate@binkert.orgDirectoryMemory::isPresent(PhysAddress address)
1354762Snate@binkert.org{
1366143Snate@binkert.org    bool ret = (mapAddressToDirectoryVersion(address) == m_version);
1376727Ssteve.reinhardt@amd.com    return ret;
1386727Ssteve.reinhardt@amd.com}
1396727Ssteve.reinhardt@amd.com
1404762Snate@binkert.orguint64
1416143Snate@binkert.orgDirectoryMemory::mapAddressToLocalIdx(PhysAddress address)
1426143Snate@binkert.org{
1436143Snate@binkert.org    uint64 ret;
1446143Snate@binkert.org    if (m_num_directories_bits > 0) {
1456727Ssteve.reinhardt@amd.com        ret = address.bitRemove(m_numa_high_bit - m_num_directories_bits + 1,
1466143Snate@binkert.org                                m_numa_high_bit);
1477674Snate@binkert.org    } else {
1487674Snate@binkert.org        ret = address.getAddress();
1495604Snate@binkert.org    }
1506143Snate@binkert.org
1516143Snate@binkert.org    return ret >> (RubySystem::getBlockSizeBits());
1526143Snate@binkert.org}
1534762Snate@binkert.org
1546143Snate@binkert.orgAbstractEntry*
1554762Snate@binkert.orgDirectoryMemory::lookup(PhysAddress address)
1564762Snate@binkert.org{
1574762Snate@binkert.org    assert(isPresent(address));
1586143Snate@binkert.org    DPRINTF(RubyCache, "Looking up address: %s\n", address);
1596143Snate@binkert.org
1604762Snate@binkert.org    if (m_use_map) {
1616143Snate@binkert.org        return m_sparseMemory->lookup(address);
1626143Snate@binkert.org    } else {
1636143Snate@binkert.org        uint64_t idx = mapAddressToLocalIdx(address);
1646143Snate@binkert.org        assert(idx < m_num_entries);
1654762Snate@binkert.org        return m_entries[idx];
1666143Snate@binkert.org    }
1674762Snate@binkert.org}
1686143Snate@binkert.org
1694762Snate@binkert.orgAbstractEntry*
1706143Snate@binkert.orgDirectoryMemory::allocate(const PhysAddress& address, AbstractEntry* entry)
1716143Snate@binkert.org{
1726143Snate@binkert.org    assert(isPresent(address));
1736143Snate@binkert.org    uint64 idx;
1746143Snate@binkert.org    DPRINTF(RubyCache, "Looking up address: %s\n", address);
1756143Snate@binkert.org
1766143Snate@binkert.org    if (m_use_map) {
1776143Snate@binkert.org        m_sparseMemory->add(address, entry);
1786143Snate@binkert.org        entry->changePermission(AccessPermission_Read_Write);
1796143Snate@binkert.org    } else {
1806143Snate@binkert.org        idx = mapAddressToLocalIdx(address);
1816143Snate@binkert.org        assert(idx < m_num_entries);
1826143Snate@binkert.org        entry->getDataBlk().assign(m_ram->getBlockPtr(address));
183955SN/A        entry->changePermission(AccessPermission_Read_Only);
1845584Snate@binkert.org        m_entries[idx] = entry;
1855584Snate@binkert.org    }
1865584Snate@binkert.org
1875584Snate@binkert.org    return entry;
1886143Snate@binkert.org}
1896143Snate@binkert.org
1906143Snate@binkert.orgvoid
1915584Snate@binkert.orgDirectoryMemory::invalidateBlock(PhysAddress address)
1924382Sbinkertn@umich.edu{
1934202Sbinkertn@umich.edu    if (m_use_map) {
1944382Sbinkertn@umich.edu        assert(m_sparseMemory->exist(address));
1954382Sbinkertn@umich.edu        m_sparseMemory->remove(address);
1964382Sbinkertn@umich.edu    }
1975584Snate@binkert.org#if 0
1984382Sbinkertn@umich.edu    else {
1994382Sbinkertn@umich.edu        assert(isPresent(address));
2004382Sbinkertn@umich.edu
2015192Ssaidi@eecs.umich.edu        Index index = address.memoryModuleIndex();
2025192Ssaidi@eecs.umich.edu
2035799Snate@binkert.org        if (index < 0 || index > m_size) {
2045799Snate@binkert.org            ERROR_MSG("Directory Memory Assertion: "
2055799Snate@binkert.org                      "accessing memory out of range.");
2065192Ssaidi@eecs.umich.edu        }
2075799Snate@binkert.org
2085192Ssaidi@eecs.umich.edu        if (m_entries[index] != NULL){
2095799Snate@binkert.org            delete m_entries[index];
2105799Snate@binkert.org            m_entries[index] = NULL;
2115192Ssaidi@eecs.umich.edu        }
2125192Ssaidi@eecs.umich.edu    }
2135192Ssaidi@eecs.umich.edu#endif
2145799Snate@binkert.org}
2155192Ssaidi@eecs.umich.edu
2165192Ssaidi@eecs.umich.eduvoid
2175192Ssaidi@eecs.umich.eduDirectoryMemory::print(ostream& out) const
2185192Ssaidi@eecs.umich.edu{
2195192Ssaidi@eecs.umich.edu}
2205192Ssaidi@eecs.umich.edu
2214382Sbinkertn@umich.eduvoid
2224382Sbinkertn@umich.eduDirectoryMemory::printStats(ostream& out) const
2234382Sbinkertn@umich.edu{
2242667Sstever@eecs.umich.edu    if (m_use_map) {
2252667Sstever@eecs.umich.edu        m_sparseMemory->printStats(out);
2262667Sstever@eecs.umich.edu    }
2272667Sstever@eecs.umich.edu}
2282667Sstever@eecs.umich.edu
2292667Sstever@eecs.umich.eduDirectoryMemory *
2305742Snate@binkert.orgRubyDirectoryMemoryParams::create()
2315742Snate@binkert.org{
2325742Snate@binkert.org    return new DirectoryMemory(this);
2335793Snate@binkert.org}
2345793Snate@binkert.org