DirectoryMemory.cc revision 7055
12381SN/A/*
210342SCurtis.Dunham@arm.com * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
38949Sandreas.hansson@arm.com * All rights reserved.
48949Sandreas.hansson@arm.com *
58949Sandreas.hansson@arm.com * Redistribution and use in source and binary forms, with or without
68949Sandreas.hansson@arm.com * modification, are permitted provided that the following conditions are
78949Sandreas.hansson@arm.com * met: redistributions of source code must retain the above copyright
88949Sandreas.hansson@arm.com * notice, this list of conditions and the following disclaimer;
98949Sandreas.hansson@arm.com * redistributions in binary form must reproduce the above copyright
108949Sandreas.hansson@arm.com * notice, this list of conditions and the following disclaimer in the
118949Sandreas.hansson@arm.com * documentation and/or other materials provided with the distribution;
128949Sandreas.hansson@arm.com * neither the name of the copyright holders nor the names of its
138949Sandreas.hansson@arm.com * contributors may be used to endorse or promote products derived from
142592SN/A * this software without specific prior written permission.
157636Ssteve.reinhardt@amd.com *
162381SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
172381SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
182381SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
192381SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
202381SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
212381SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
222381SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
232381SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
242381SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
252381SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
262381SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
272381SN/A */
282381SN/A
292381SN/A#include "mem/gems_common/util.hh"
302381SN/A#include "mem/ruby/slicc_interface/RubySlicc_Util.hh"
312381SN/A#include "mem/ruby/system/DirectoryMemory.hh"
322381SN/A#include "mem/ruby/system/System.hh"
332381SN/A
342381SN/Ausing namespace std;
352381SN/A
362381SN/Aint DirectoryMemory::m_num_directories = 0;
372381SN/Aint DirectoryMemory::m_num_directories_bits = 0;
382381SN/Auint64_t DirectoryMemory::m_total_size_bytes = 0;
392381SN/Aint DirectoryMemory::m_numa_high_bit = 0;
402665Ssaidi@eecs.umich.edu
412665Ssaidi@eecs.umich.eduDirectoryMemory::DirectoryMemory(const Params *p)
422665Ssaidi@eecs.umich.edu    : SimObject(p)
432665Ssaidi@eecs.umich.edu{
449031Sandreas.hansson@arm.com    m_version = p->version;
452381SN/A    m_size_bytes = p->size;
462381SN/A    m_size_bits = log_int(m_size_bytes);
472381SN/A    m_num_entries = 0;
482381SN/A    m_use_map = p->use_map;
492662Sstever@eecs.umich.edu    m_map_levels = p->map_levels;
502381SN/A    m_numa_high_bit = p->numa_high_bit;
512381SN/A}
522381SN/A
532381SN/Avoid
542381SN/ADirectoryMemory::init()
558229Snate@binkert.org{
563348Sbinkertn@umich.edu    m_num_entries = m_size_bytes / RubySystem::getBlockSizeBytes();
573348Sbinkertn@umich.edu
583348Sbinkertn@umich.edu    if (m_use_map) {
595735Snate@binkert.org        int entry_bits = log_int(m_num_entries);
604024Sbinkertn@umich.edu        assert(entry_bits >= m_map_levels);
615735Snate@binkert.org        m_sparseMemory = new SparseMemory(entry_bits, m_map_levels);
623940Ssaidi@eecs.umich.edu    } else {
635314Sstever@gmail.com        m_entries = new Directory_Entry*[m_num_entries];
646216Snate@binkert.org        for (int i = 0; i < m_num_entries; i++)
652392SN/A            m_entries[i] = NULL;
664167Sbinkertn@umich.edu        m_ram = g_system_ptr->getMemoryVector();
672394SN/A    }
688737Skoansin.tan@gmail.com
693349Sbinkertn@umich.edu    m_num_directories++;
702394SN/A    m_num_directories_bits = log_int(m_num_directories);
712812Srdreslin@umich.edu    m_total_size_bytes += m_size_bytes;
722812Srdreslin@umich.edu
734022Sstever@eecs.umich.edu    if (m_numa_high_bit == 0) {
744022Sstever@eecs.umich.edu        m_numa_high_bit = RubySystem::getMemorySizeBits();
755735Snate@binkert.org    }
765735Snate@binkert.org    assert(m_numa_high_bit != 0);
774022Sstever@eecs.umich.edu}
785735Snate@binkert.org
795735Snate@binkert.orgDirectoryMemory::~DirectoryMemory()
805735Snate@binkert.org{
814022Sstever@eecs.umich.edu    // free up all the directory entries
824022Sstever@eecs.umich.edu    if (m_entries != NULL) {
834022Sstever@eecs.umich.edu        for (uint64 i = 0; i < m_num_entries; i++) {
844022Sstever@eecs.umich.edu            if (m_entries[i] != NULL) {
854473Sstever@eecs.umich.edu                delete m_entries[i];
865319Sstever@gmail.com            }
874022Sstever@eecs.umich.edu        }
884022Sstever@eecs.umich.edu        delete [] m_entries;
894022Sstever@eecs.umich.edu    } else if (m_use_map) {
904022Sstever@eecs.umich.edu        delete m_sparseMemory;
914022Sstever@eecs.umich.edu    }
924022Sstever@eecs.umich.edu}
934022Sstever@eecs.umich.edu
944022Sstever@eecs.umich.eduvoid
954022Sstever@eecs.umich.eduDirectoryMemory::printConfig(ostream& out) const
964022Sstever@eecs.umich.edu{
977465Ssteve.reinhardt@amd.com    out << "DirectoryMemory module config: " << m_name << endl
984628Sstever@eecs.umich.edu        << "  version: " << m_version << endl
997465Ssteve.reinhardt@amd.com        << "  memory_bits: " << m_size_bits << endl
1007465Ssteve.reinhardt@amd.com        << "  memory_size_bytes: " << m_size_bytes << endl
1014022Sstever@eecs.umich.edu        << "  memory_size_Kbytes: " << double(m_size_bytes) / (1<<10) << endl
1024022Sstever@eecs.umich.edu        << "  memory_size_Mbytes: " << double(m_size_bytes) / (1<<20) << endl
1034626Sstever@eecs.umich.edu        << "  memory_size_Gbytes: " << double(m_size_bytes) / (1<<30) << endl;
1044626Sstever@eecs.umich.edu}
1057669Ssteve.reinhardt@amd.com
1064626Sstever@eecs.umich.edu// Static method
1074040Ssaidi@eecs.umich.eduvoid
1084040Ssaidi@eecs.umich.eduDirectoryMemory::printGlobalConfig(ostream & out)
1095650Sgblack@eecs.umich.edu{
1105650Sgblack@eecs.umich.edu    out << "DirectoryMemory Global Config: " << endl;
1114870Sstever@eecs.umich.edu    out << "  number of directory memories: " << m_num_directories << endl;
1124870Sstever@eecs.umich.edu    if (m_num_directories > 1) {
1134870Sstever@eecs.umich.edu        out << "  number of selection bits: " << m_num_directories_bits << endl
1144870Sstever@eecs.umich.edu            << "  selection bits: " << m_numa_high_bit
1154870Sstever@eecs.umich.edu            << "-" << m_numa_high_bit-m_num_directories_bits
1164870Sstever@eecs.umich.edu            << endl;
1178436SBrad.Beckmann@amd.com    }
1188436SBrad.Beckmann@amd.com    out << "  total memory size bytes: " << m_total_size_bytes << endl;
1195314Sstever@gmail.com    out << "  total memory bits: " << log_int(m_total_size_bytes) << endl;
1205314Sstever@gmail.com}
1218184Ssomayeh@cs.wisc.edu
1228716Snilay@cs.wisc.eduuint64
1234022Sstever@eecs.umich.eduDirectoryMemory::mapAddressToDirectoryVersion(PhysAddress address)
1244022Sstever@eecs.umich.edu{
1254022Sstever@eecs.umich.edu    if (m_num_directories_bits == 0)
1264022Sstever@eecs.umich.edu        return 0;
1275735Snate@binkert.org
1285735Snate@binkert.org    uint64 ret = address.bitSelect(m_numa_high_bit - m_num_directories_bits,
1295735Snate@binkert.org                                   m_numa_high_bit);
1304022Sstever@eecs.umich.edu    return ret;
1314022Sstever@eecs.umich.edu}
1324626Sstever@eecs.umich.edu
1334626Sstever@eecs.umich.edubool
1347465Ssteve.reinhardt@amd.comDirectoryMemory::isPresent(PhysAddress address)
1354022Sstever@eecs.umich.edu{
1364626Sstever@eecs.umich.edu    bool ret = (mapAddressToDirectoryVersion(address) == m_version);
1374626Sstever@eecs.umich.edu    return ret;
1384626Sstever@eecs.umich.edu}
1394626Sstever@eecs.umich.edu
1404022Sstever@eecs.umich.eduuint64
1414022Sstever@eecs.umich.eduDirectoryMemory::mapAddressToLocalIdx(PhysAddress address)
1426076Sgblack@eecs.umich.edu{
1434626Sstever@eecs.umich.edu    uint64 ret = address.bitRemove(m_numa_high_bit - m_num_directories_bits,
1444870Sstever@eecs.umich.edu                                   m_numa_high_bit)
1455314Sstever@gmail.com        >> (RubySystem::getBlockSizeBits());
1468184Ssomayeh@cs.wisc.edu    return ret;
1474022Sstever@eecs.umich.edu}
1484022Sstever@eecs.umich.edu
1494022Sstever@eecs.umich.eduDirectory_Entry&
1505735Snate@binkert.orgDirectoryMemory::lookup(PhysAddress address)
1515735Snate@binkert.org{
1525735Snate@binkert.org    assert(isPresent(address));
1535735Snate@binkert.org    Directory_Entry* entry;
1545735Snate@binkert.org    uint64 idx;
1555735Snate@binkert.org    DEBUG_EXPR(CACHE_COMP, HighPrio, address);
1565735Snate@binkert.org
1574022Sstever@eecs.umich.edu    if (m_use_map) {
1585735Snate@binkert.org        if (m_sparseMemory->exist(address)) {
1595735Snate@binkert.org            entry = m_sparseMemory->lookup(address);
1604022Sstever@eecs.umich.edu            assert(entry != NULL);
1615735Snate@binkert.org        } else {
1624022Sstever@eecs.umich.edu            // Note: SparseMemory internally creates a new Directory Entry
1634022Sstever@eecs.umich.edu            m_sparseMemory->add(address);
1644022Sstever@eecs.umich.edu            entry = m_sparseMemory->lookup(address);
1655735Snate@binkert.org        }
1664022Sstever@eecs.umich.edu    } else {
1674022Sstever@eecs.umich.edu        idx = mapAddressToLocalIdx(address);
1684022Sstever@eecs.umich.edu        assert(idx < m_num_entries);
1694022Sstever@eecs.umich.edu        entry = m_entries[idx];
1704022Sstever@eecs.umich.edu
1714022Sstever@eecs.umich.edu        if (entry == NULL) {
1725735Snate@binkert.org            entry = new Directory_Entry();
1735735Snate@binkert.org            entry->getDataBlk().assign(m_ram->getBlockPtr(address));
1745735Snate@binkert.org            m_entries[idx] = entry;
1754022Sstever@eecs.umich.edu        }
1764022Sstever@eecs.umich.edu    }
1774022Sstever@eecs.umich.edu
1784022Sstever@eecs.umich.edu    return *entry;
1794022Sstever@eecs.umich.edu}
1804022Sstever@eecs.umich.edu
1817465Ssteve.reinhardt@amd.com#if 0
1827465Ssteve.reinhardt@amd.comDirectory_Entry&
1834022Sstever@eecs.umich.eduDirectoryMemory::lookup(PhysAddress address)
1844022Sstever@eecs.umich.edu{
1854870Sstever@eecs.umich.edu    assert(isPresent(address));
1864022Sstever@eecs.umich.edu    Index index = address.memoryModuleIndex();
1874022Sstever@eecs.umich.edu
1884022Sstever@eecs.umich.edu    if (index < 0 || index > m_size) {
1894626Sstever@eecs.umich.edu        WARN_EXPR(address.getAddress());
1906102Sgblack@eecs.umich.edu        WARN_EXPR(index);
19110343SCurtis.Dunham@arm.com        WARN_EXPR(m_size);
19210343SCurtis.Dunham@arm.com        ERROR_MSG("Directory Memory Assertion: accessing memory out of range");
19310343SCurtis.Dunham@arm.com    }
19410343SCurtis.Dunham@arm.com    Directory_Entry* entry = m_entries[index];
1954870Sstever@eecs.umich.edu
1965314Sstever@gmail.com    // allocate the directory entry on demand.
1978184Ssomayeh@cs.wisc.edu    if (entry == NULL) {
1984022Sstever@eecs.umich.edu        entry = new Directory_Entry;
1995735Snate@binkert.org        entry->getDataBlk().assign(m_ram->getBlockPtr(address));
2005735Snate@binkert.org
2015735Snate@binkert.org        // store entry to the table
2024022Sstever@eecs.umich.edu        m_entries[index] = entry;
2034022Sstever@eecs.umich.edu    }
2044022Sstever@eecs.umich.edu
2055735Snate@binkert.org    return *entry;
2065735Snate@binkert.org}
2074022Sstever@eecs.umich.edu#endif
2084022Sstever@eecs.umich.edu
2095735Snate@binkert.orgvoid
2105735Snate@binkert.orgDirectoryMemory::invalidateBlock(PhysAddress address)
2115735Snate@binkert.org{
2124022Sstever@eecs.umich.edu    if (m_use_map) {
2135735Snate@binkert.org        assert(m_sparseMemory->exist(address));
2145735Snate@binkert.org        m_sparseMemory->remove(address);
2154022Sstever@eecs.umich.edu    }
2164022Sstever@eecs.umich.edu#if 0
2172381SN/A    else {
2182662Sstever@eecs.umich.edu        assert(isPresent(address));
2192662Sstever@eecs.umich.edu
2202662Sstever@eecs.umich.edu        Index index = address.memoryModuleIndex();
2212662Sstever@eecs.umich.edu
2222662Sstever@eecs.umich.edu        if (index < 0 || index > m_size) {
2232381SN/A            ERROR_MSG("Directory Memory Assertion: "
2249044SAli.Saidi@ARM.com                      "accessing memory out of range.");
2252381SN/A        }
2262813Srdreslin@umich.edu
2275735Snate@binkert.org        if (m_entries[index] != NULL){
2285735Snate@binkert.org            delete m_entries[index];
2294022Sstever@eecs.umich.edu            m_entries[index] = NULL;
2305735Snate@binkert.org        }
2315735Snate@binkert.org    }
2325735Snate@binkert.org#endif
2335735Snate@binkert.org}
2345735Snate@binkert.org
2355735Snate@binkert.orgvoid
2365735Snate@binkert.orgDirectoryMemory::print(ostream& out) const
2375735Snate@binkert.org{
2385735Snate@binkert.org}
2395735Snate@binkert.org
2405735Snate@binkert.orgvoid
2415735Snate@binkert.orgDirectoryMemory::printStats(ostream& out) const
2425735Snate@binkert.org{
2435735Snate@binkert.org    if (m_use_map) {
2445735Snate@binkert.org        m_sparseMemory->printStats(out);
2455735Snate@binkert.org    }
2465735Snate@binkert.org}
2475735Snate@binkert.org
2485735Snate@binkert.orgDirectoryMemory *
2495735Snate@binkert.orgRubyDirectoryMemoryParams::create()
2505735Snate@binkert.org{
2515735Snate@binkert.org    return new DirectoryMemory(this);
2525735Snate@binkert.org}
2535735Snate@binkert.org