DirectoryMemory.cc revision 7055
112952Sgabeblack@google.com/*
212952Sgabeblack@google.com * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
312952Sgabeblack@google.com * All rights reserved.
412952Sgabeblack@google.com *
512952Sgabeblack@google.com * Redistribution and use in source and binary forms, with or without
612952Sgabeblack@google.com * modification, are permitted provided that the following conditions are
712952Sgabeblack@google.com * met: redistributions of source code must retain the above copyright
812952Sgabeblack@google.com * notice, this list of conditions and the following disclaimer;
912952Sgabeblack@google.com * redistributions in binary form must reproduce the above copyright
1012952Sgabeblack@google.com * notice, this list of conditions and the following disclaimer in the
1112952Sgabeblack@google.com * documentation and/or other materials provided with the distribution;
1212952Sgabeblack@google.com * neither the name of the copyright holders nor the names of its
1312952Sgabeblack@google.com * contributors may be used to endorse or promote products derived from
1412952Sgabeblack@google.com * this software without specific prior written permission.
1512952Sgabeblack@google.com *
1612952Sgabeblack@google.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
1712952Sgabeblack@google.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
1812952Sgabeblack@google.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
1912952Sgabeblack@google.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
2012952Sgabeblack@google.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
2112952Sgabeblack@google.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
2212952Sgabeblack@google.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2312952Sgabeblack@google.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2412952Sgabeblack@google.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2512952Sgabeblack@google.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2612952Sgabeblack@google.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2712952Sgabeblack@google.com */
2812952Sgabeblack@google.com
2912952Sgabeblack@google.com#include "mem/gems_common/util.hh"
3012952Sgabeblack@google.com#include "mem/ruby/slicc_interface/RubySlicc_Util.hh"
3112957Sgabeblack@google.com#include "mem/ruby/system/DirectoryMemory.hh"
3212957Sgabeblack@google.com#include "mem/ruby/system/System.hh"
3312957Sgabeblack@google.com
3412953Sgabeblack@google.comusing namespace std;
3513102Sgabeblack@google.com
3612998Sgabeblack@google.comint DirectoryMemory::m_num_directories = 0;
3712998Sgabeblack@google.comint DirectoryMemory::m_num_directories_bits = 0;
3812952Sgabeblack@google.comuint64_t DirectoryMemory::m_total_size_bytes = 0;
3912952Sgabeblack@google.comint DirectoryMemory::m_numa_high_bit = 0;
4012952Sgabeblack@google.com
4112952Sgabeblack@google.comDirectoryMemory::DirectoryMemory(const Params *p)
4212957Sgabeblack@google.com    : SimObject(p)
4313063Sgabeblack@google.com{
4412957Sgabeblack@google.com    m_version = p->version;
4513063Sgabeblack@google.com    m_size_bytes = p->size;
4612957Sgabeblack@google.com    m_size_bits = log_int(m_size_bytes);
4712957Sgabeblack@google.com    m_num_entries = 0;
4812957Sgabeblack@google.com    m_use_map = p->use_map;
4912957Sgabeblack@google.com    m_map_levels = p->map_levels;
5012957Sgabeblack@google.com    m_numa_high_bit = p->numa_high_bit;
5112962Sgabeblack@google.com}
5212962Sgabeblack@google.com
5312962Sgabeblack@google.comvoid
5412962Sgabeblack@google.comDirectoryMemory::init()
5512962Sgabeblack@google.com{
5612962Sgabeblack@google.com    m_num_entries = m_size_bytes / RubySystem::getBlockSizeBytes();
5712962Sgabeblack@google.com
5812957Sgabeblack@google.com    if (m_use_map) {
5912957Sgabeblack@google.com        int entry_bits = log_int(m_num_entries);
6012957Sgabeblack@google.com        assert(entry_bits >= m_map_levels);
6112957Sgabeblack@google.com        m_sparseMemory = new SparseMemory(entry_bits, m_map_levels);
6212957Sgabeblack@google.com    } else {
6312957Sgabeblack@google.com        m_entries = new Directory_Entry*[m_num_entries];
6412957Sgabeblack@google.com        for (int i = 0; i < m_num_entries; i++)
6512957Sgabeblack@google.com            m_entries[i] = NULL;
6612957Sgabeblack@google.com        m_ram = g_system_ptr->getMemoryVector();
6712957Sgabeblack@google.com    }
6812957Sgabeblack@google.com
6912957Sgabeblack@google.com    m_num_directories++;
7012957Sgabeblack@google.com    m_num_directories_bits = log_int(m_num_directories);
7112957Sgabeblack@google.com    m_total_size_bytes += m_size_bytes;
7212957Sgabeblack@google.com
7312957Sgabeblack@google.com    if (m_numa_high_bit == 0) {
7412957Sgabeblack@google.com        m_numa_high_bit = RubySystem::getMemorySizeBits();
7512957Sgabeblack@google.com    }
7612957Sgabeblack@google.com    assert(m_numa_high_bit != 0);
7712957Sgabeblack@google.com}
7812957Sgabeblack@google.com
7912957Sgabeblack@google.comDirectoryMemory::~DirectoryMemory()
8012957Sgabeblack@google.com{
8112957Sgabeblack@google.com    // free up all the directory entries
8212957Sgabeblack@google.com    if (m_entries != NULL) {
8312957Sgabeblack@google.com        for (uint64 i = 0; i < m_num_entries; i++) {
8412957Sgabeblack@google.com            if (m_entries[i] != NULL) {
8512957Sgabeblack@google.com                delete m_entries[i];
8612957Sgabeblack@google.com            }
8712957Sgabeblack@google.com        }
8812957Sgabeblack@google.com        delete [] m_entries;
8912957Sgabeblack@google.com    } else if (m_use_map) {
9012957Sgabeblack@google.com        delete m_sparseMemory;
9112959Sgabeblack@google.com    }
9212957Sgabeblack@google.com}
9312957Sgabeblack@google.com
9412957Sgabeblack@google.comvoid
9512957Sgabeblack@google.comDirectoryMemory::printConfig(ostream& out) const
9612957Sgabeblack@google.com{
9712957Sgabeblack@google.com    out << "DirectoryMemory module config: " << m_name << endl
9812957Sgabeblack@google.com        << "  version: " << m_version << endl
9912957Sgabeblack@google.com        << "  memory_bits: " << m_size_bits << endl
10012957Sgabeblack@google.com        << "  memory_size_bytes: " << m_size_bytes << endl
10112957Sgabeblack@google.com        << "  memory_size_Kbytes: " << double(m_size_bytes) / (1<<10) << endl
10212957Sgabeblack@google.com        << "  memory_size_Mbytes: " << double(m_size_bytes) / (1<<20) << endl
10312957Sgabeblack@google.com        << "  memory_size_Gbytes: " << double(m_size_bytes) / (1<<30) << endl;
10412957Sgabeblack@google.com}
10512957Sgabeblack@google.com
10612957Sgabeblack@google.com// Static method
10712957Sgabeblack@google.comvoid
10813075Sgabeblack@google.comDirectoryMemory::printGlobalConfig(ostream & out)
10913075Sgabeblack@google.com{
11013075Sgabeblack@google.com    out << "DirectoryMemory Global Config: " << endl;
11113075Sgabeblack@google.com    out << "  number of directory memories: " << m_num_directories << endl;
11213075Sgabeblack@google.com    if (m_num_directories > 1) {
11313075Sgabeblack@google.com        out << "  number of selection bits: " << m_num_directories_bits << endl
11413075Sgabeblack@google.com            << "  selection bits: " << m_numa_high_bit
11513075Sgabeblack@google.com            << "-" << m_numa_high_bit-m_num_directories_bits
11613075Sgabeblack@google.com            << endl;
11713075Sgabeblack@google.com    }
11813075Sgabeblack@google.com    out << "  total memory size bytes: " << m_total_size_bytes << endl;
11913075Sgabeblack@google.com    out << "  total memory bits: " << log_int(m_total_size_bytes) << endl;
12012957Sgabeblack@google.com}
12112952Sgabeblack@google.com
12212952Sgabeblack@google.comuint64
12312952Sgabeblack@google.comDirectoryMemory::mapAddressToDirectoryVersion(PhysAddress address)
12412995Sgabeblack@google.com{
12512952Sgabeblack@google.com    if (m_num_directories_bits == 0)
12612952Sgabeblack@google.com        return 0;
12712952Sgabeblack@google.com
12812952Sgabeblack@google.com    uint64 ret = address.bitSelect(m_numa_high_bit - m_num_directories_bits,
12912952Sgabeblack@google.com                                   m_numa_high_bit);
13012995Sgabeblack@google.com    return ret;
13112952Sgabeblack@google.com}
13212952Sgabeblack@google.com
13312952Sgabeblack@google.combool
13412952Sgabeblack@google.comDirectoryMemory::isPresent(PhysAddress address)
13512952Sgabeblack@google.com{
13612952Sgabeblack@google.com    bool ret = (mapAddressToDirectoryVersion(address) == m_version);
13712952Sgabeblack@google.com    return ret;
13812952Sgabeblack@google.com}
13912952Sgabeblack@google.com
14012952Sgabeblack@google.comuint64
14112952Sgabeblack@google.comDirectoryMemory::mapAddressToLocalIdx(PhysAddress address)
14212952Sgabeblack@google.com{
14312952Sgabeblack@google.com    uint64 ret = address.bitRemove(m_numa_high_bit - m_num_directories_bits,
14412952Sgabeblack@google.com                                   m_numa_high_bit)
14512952Sgabeblack@google.com        >> (RubySystem::getBlockSizeBits());
14612952Sgabeblack@google.com    return ret;
14712952Sgabeblack@google.com}
14812952Sgabeblack@google.com
14912952Sgabeblack@google.comDirectory_Entry&
15012952Sgabeblack@google.comDirectoryMemory::lookup(PhysAddress address)
15112952Sgabeblack@google.com{
15212952Sgabeblack@google.com    assert(isPresent(address));
15312952Sgabeblack@google.com    Directory_Entry* entry;
15412952Sgabeblack@google.com    uint64 idx;
15512952Sgabeblack@google.com    DEBUG_EXPR(CACHE_COMP, HighPrio, address);
15612952Sgabeblack@google.com
15712952Sgabeblack@google.com    if (m_use_map) {
15812952Sgabeblack@google.com        if (m_sparseMemory->exist(address)) {
15912952Sgabeblack@google.com            entry = m_sparseMemory->lookup(address);
16012952Sgabeblack@google.com            assert(entry != NULL);
16112952Sgabeblack@google.com        } else {
16212952Sgabeblack@google.com            // Note: SparseMemory internally creates a new Directory Entry
16312959Sgabeblack@google.com            m_sparseMemory->add(address);
16412952Sgabeblack@google.com            entry = m_sparseMemory->lookup(address);
16512952Sgabeblack@google.com        }
16612953Sgabeblack@google.com    } else {
16712953Sgabeblack@google.com        idx = mapAddressToLocalIdx(address);
16812953Sgabeblack@google.com        assert(idx < m_num_entries);
16912952Sgabeblack@google.com        entry = m_entries[idx];
17012952Sgabeblack@google.com
17112952Sgabeblack@google.com        if (entry == NULL) {
17212952Sgabeblack@google.com            entry = new Directory_Entry();
17312952Sgabeblack@google.com            entry->getDataBlk().assign(m_ram->getBlockPtr(address));
17412952Sgabeblack@google.com            m_entries[idx] = entry;
17512952Sgabeblack@google.com        }
17612952Sgabeblack@google.com    }
17712952Sgabeblack@google.com
17812952Sgabeblack@google.com    return *entry;
17912952Sgabeblack@google.com}
18012959Sgabeblack@google.com
18112959Sgabeblack@google.com#if 0
18212959Sgabeblack@google.comDirectory_Entry&
18312952Sgabeblack@google.comDirectoryMemory::lookup(PhysAddress address)
18412952Sgabeblack@google.com{
18512952Sgabeblack@google.com    assert(isPresent(address));
18612952Sgabeblack@google.com    Index index = address.memoryModuleIndex();
18712952Sgabeblack@google.com
18812952Sgabeblack@google.com    if (index < 0 || index > m_size) {
18912952Sgabeblack@google.com        WARN_EXPR(address.getAddress());
19012952Sgabeblack@google.com        WARN_EXPR(index);
19112952Sgabeblack@google.com        WARN_EXPR(m_size);
19212999Sgabeblack@google.com        ERROR_MSG("Directory Memory Assertion: accessing memory out of range");
19312999Sgabeblack@google.com    }
19412999Sgabeblack@google.com    Directory_Entry* entry = m_entries[index];
19512999Sgabeblack@google.com
19612999Sgabeblack@google.com    // allocate the directory entry on demand.
19712999Sgabeblack@google.com    if (entry == NULL) {
19812999Sgabeblack@google.com        entry = new Directory_Entry;
19912999Sgabeblack@google.com        entry->getDataBlk().assign(m_ram->getBlockPtr(address));
20012952Sgabeblack@google.com
20112952Sgabeblack@google.com        // store entry to the table
20212952Sgabeblack@google.com        m_entries[index] = entry;
20312952Sgabeblack@google.com    }
20412952Sgabeblack@google.com
20512952Sgabeblack@google.com    return *entry;
20612952Sgabeblack@google.com}
20712952Sgabeblack@google.com#endif
20812952Sgabeblack@google.com
20912952Sgabeblack@google.comvoid
21012952Sgabeblack@google.comDirectoryMemory::invalidateBlock(PhysAddress address)
21112952Sgabeblack@google.com{
21212952Sgabeblack@google.com    if (m_use_map) {
21312952Sgabeblack@google.com        assert(m_sparseMemory->exist(address));
21412952Sgabeblack@google.com        m_sparseMemory->remove(address);
21512952Sgabeblack@google.com    }
21613102Sgabeblack@google.com#if 0
21713102Sgabeblack@google.com    else {
21813102Sgabeblack@google.com        assert(isPresent(address));
21913102Sgabeblack@google.com
22013102Sgabeblack@google.com        Index index = address.memoryModuleIndex();
22113102Sgabeblack@google.com
22212952Sgabeblack@google.com        if (index < 0 || index > m_size) {
22312952Sgabeblack@google.com            ERROR_MSG("Directory Memory Assertion: "
22412952Sgabeblack@google.com                      "accessing memory out of range.");
22512952Sgabeblack@google.com        }
22612952Sgabeblack@google.com
22712952Sgabeblack@google.com        if (m_entries[index] != NULL){
22812952Sgabeblack@google.com            delete m_entries[index];
22912952Sgabeblack@google.com            m_entries[index] = NULL;
23012995Sgabeblack@google.com        }
23112998Sgabeblack@google.com    }
23212995Sgabeblack@google.com#endif
23312995Sgabeblack@google.com}
23412998Sgabeblack@google.com
23512998Sgabeblack@google.comvoid
23612998Sgabeblack@google.comDirectoryMemory::print(ostream& out) const
23712998Sgabeblack@google.com{
23812998Sgabeblack@google.com}
23912998Sgabeblack@google.com
24012952Sgabeblack@google.comvoid
24112952Sgabeblack@google.comDirectoryMemory::printStats(ostream& out) const
24212952Sgabeblack@google.com{
24312952Sgabeblack@google.com    if (m_use_map) {
24412952Sgabeblack@google.com        m_sparseMemory->printStats(out);
24513102Sgabeblack@google.com    }
24613102Sgabeblack@google.com}
24713102Sgabeblack@google.com
24813102Sgabeblack@google.comDirectoryMemory *
24913102Sgabeblack@google.comRubyDirectoryMemoryParams::create()
25013102Sgabeblack@google.com{
25112952Sgabeblack@google.com    return new DirectoryMemory(this);
25212952Sgabeblack@google.com}
25312952Sgabeblack@google.com