DirectoryMemory.cc revision 7563
112855Sgabeblack@google.com/*
212855Sgabeblack@google.com * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
312855Sgabeblack@google.com * All rights reserved.
412855Sgabeblack@google.com *
512855Sgabeblack@google.com * Redistribution and use in source and binary forms, with or without
612855Sgabeblack@google.com * modification, are permitted provided that the following conditions are
712855Sgabeblack@google.com * met: redistributions of source code must retain the above copyright
812855Sgabeblack@google.com * notice, this list of conditions and the following disclaimer;
912855Sgabeblack@google.com * redistributions in binary form must reproduce the above copyright
1012855Sgabeblack@google.com * notice, this list of conditions and the following disclaimer in the
1112855Sgabeblack@google.com * documentation and/or other materials provided with the distribution;
1212855Sgabeblack@google.com * neither the name of the copyright holders nor the names of its
1312855Sgabeblack@google.com * contributors may be used to endorse or promote products derived from
1412855Sgabeblack@google.com * this software without specific prior written permission.
1512855Sgabeblack@google.com *
1612855Sgabeblack@google.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
1712855Sgabeblack@google.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
1812855Sgabeblack@google.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
1912855Sgabeblack@google.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
2012855Sgabeblack@google.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
2112855Sgabeblack@google.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
2212855Sgabeblack@google.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2312855Sgabeblack@google.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2412855Sgabeblack@google.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2512855Sgabeblack@google.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2612855Sgabeblack@google.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2712855Sgabeblack@google.com */
2812855Sgabeblack@google.com
2912855Sgabeblack@google.com#include "base/intmath.hh"
3012855Sgabeblack@google.com#include "mem/ruby/slicc_interface/RubySlicc_Util.hh"
3112855Sgabeblack@google.com#include "mem/ruby/system/DirectoryMemory.hh"
3212855Sgabeblack@google.com#include "mem/ruby/system/System.hh"
3312855Sgabeblack@google.com
3412855Sgabeblack@google.comusing namespace std;
3512855Sgabeblack@google.com
3612855Sgabeblack@google.comint DirectoryMemory::m_num_directories = 0;
3712855Sgabeblack@google.comint DirectoryMemory::m_num_directories_bits = 0;
3812855Sgabeblack@google.comuint64_t DirectoryMemory::m_total_size_bytes = 0;
3912855Sgabeblack@google.comint DirectoryMemory::m_numa_high_bit = 0;
4012855Sgabeblack@google.com
4112855Sgabeblack@google.comDirectoryMemory::DirectoryMemory(const Params *p)
4212855Sgabeblack@google.com    : SimObject(p)
4312855Sgabeblack@google.com{
4412855Sgabeblack@google.com    m_version = p->version;
4512855Sgabeblack@google.com    m_size_bytes = p->size;
4612855Sgabeblack@google.com    m_size_bits = floorLog2(m_size_bytes);
4712855Sgabeblack@google.com    m_num_entries = 0;
4812855Sgabeblack@google.com    m_use_map = p->use_map;
4912855Sgabeblack@google.com    m_map_levels = p->map_levels;
5012855Sgabeblack@google.com    m_numa_high_bit = p->numa_high_bit;
5112855Sgabeblack@google.com}
5212855Sgabeblack@google.com
5312855Sgabeblack@google.comvoid
5412855Sgabeblack@google.comDirectoryMemory::init()
5512855Sgabeblack@google.com{
5612855Sgabeblack@google.com    m_num_entries = m_size_bytes / RubySystem::getBlockSizeBytes();
5712855Sgabeblack@google.com
5812855Sgabeblack@google.com    if (m_use_map) {
5912855Sgabeblack@google.com        int entry_bits = floorLog2(m_num_entries);
6012855Sgabeblack@google.com        assert(entry_bits >= m_map_levels);
6112855Sgabeblack@google.com        m_sparseMemory = new SparseMemory(entry_bits, m_map_levels);
6212855Sgabeblack@google.com    } else {
6312855Sgabeblack@google.com        m_entries = new Directory_Entry*[m_num_entries];
6412855Sgabeblack@google.com        for (int i = 0; i < m_num_entries; i++)
6512855Sgabeblack@google.com            m_entries[i] = NULL;
6612855Sgabeblack@google.com        m_ram = g_system_ptr->getMemoryVector();
6712855Sgabeblack@google.com    }
6812855Sgabeblack@google.com
6912855Sgabeblack@google.com    m_num_directories++;
7012855Sgabeblack@google.com    m_num_directories_bits = floorLog2(m_num_directories);
7112855Sgabeblack@google.com    m_total_size_bytes += m_size_bytes;
7212855Sgabeblack@google.com
7312855Sgabeblack@google.com    if (m_numa_high_bit == 0) {
7412855Sgabeblack@google.com        m_numa_high_bit = RubySystem::getMemorySizeBits() - 1;
7512855Sgabeblack@google.com    }
7612855Sgabeblack@google.com    assert(m_numa_high_bit != 0);
7712855Sgabeblack@google.com}
7812855Sgabeblack@google.com
7912855Sgabeblack@google.comDirectoryMemory::~DirectoryMemory()
8012855Sgabeblack@google.com{
8112855Sgabeblack@google.com    // free up all the directory entries
8212855Sgabeblack@google.com    if (m_entries != NULL) {
8312855Sgabeblack@google.com        for (uint64 i = 0; i < m_num_entries; i++) {
8412855Sgabeblack@google.com            if (m_entries[i] != NULL) {
8512855Sgabeblack@google.com                delete m_entries[i];
8612855Sgabeblack@google.com            }
8712855Sgabeblack@google.com        }
8812855Sgabeblack@google.com        delete [] m_entries;
8912855Sgabeblack@google.com    } else if (m_use_map) {
9012855Sgabeblack@google.com        delete m_sparseMemory;
9112855Sgabeblack@google.com    }
9212855Sgabeblack@google.com}
9312855Sgabeblack@google.com
9412855Sgabeblack@google.comvoid
9512855Sgabeblack@google.comDirectoryMemory::printConfig(ostream& out) const
9612855Sgabeblack@google.com{
9712855Sgabeblack@google.com    out << "DirectoryMemory module config: " << m_name << endl
9812855Sgabeblack@google.com        << "  version: " << m_version << endl
9912855Sgabeblack@google.com        << "  memory_bits: " << m_size_bits << endl
10012855Sgabeblack@google.com        << "  memory_size_bytes: " << m_size_bytes << endl
10112855Sgabeblack@google.com        << "  memory_size_Kbytes: " << double(m_size_bytes) / (1<<10) << endl
10212855Sgabeblack@google.com        << "  memory_size_Mbytes: " << double(m_size_bytes) / (1<<20) << endl
10312855Sgabeblack@google.com        << "  memory_size_Gbytes: " << double(m_size_bytes) / (1<<30) << endl;
10412855Sgabeblack@google.com}
10512855Sgabeblack@google.com
10612855Sgabeblack@google.com// Static method
10712855Sgabeblack@google.comvoid
10812855Sgabeblack@google.comDirectoryMemory::printGlobalConfig(ostream & out)
10912855Sgabeblack@google.com{
11012855Sgabeblack@google.com    out << "DirectoryMemory Global Config: " << endl;
11112855Sgabeblack@google.com    out << "  number of directory memories: " << m_num_directories << endl;
11212855Sgabeblack@google.com    if (m_num_directories > 1) {
11312855Sgabeblack@google.com        out << "  number of selection bits: " << m_num_directories_bits << endl
11412855Sgabeblack@google.com            << "  selection bits: " << m_numa_high_bit
11512855Sgabeblack@google.com            << "-" << m_numa_high_bit-m_num_directories_bits
11612855Sgabeblack@google.com            << endl;
11712855Sgabeblack@google.com    }
11812855Sgabeblack@google.com    out << "  total memory size bytes: " << m_total_size_bytes << endl;
11912855Sgabeblack@google.com    out << "  total memory bits: " << floorLog2(m_total_size_bytes) << endl;
12012855Sgabeblack@google.com}
12112855Sgabeblack@google.com
12212855Sgabeblack@google.comuint64
12312855Sgabeblack@google.comDirectoryMemory::mapAddressToDirectoryVersion(PhysAddress address)
12412855Sgabeblack@google.com{
12512855Sgabeblack@google.com    if (m_num_directories_bits == 0)
12612855Sgabeblack@google.com        return 0;
12712855Sgabeblack@google.com
12812855Sgabeblack@google.com    uint64 ret = address.bitSelect(m_numa_high_bit - m_num_directories_bits + 1,
12912855Sgabeblack@google.com                                   m_numa_high_bit);
13012855Sgabeblack@google.com    return ret;
13112855Sgabeblack@google.com}
13212855Sgabeblack@google.com
13312855Sgabeblack@google.combool
13412855Sgabeblack@google.comDirectoryMemory::isPresent(PhysAddress address)
13512855Sgabeblack@google.com{
13612855Sgabeblack@google.com    bool ret = (mapAddressToDirectoryVersion(address) == m_version);
13712855Sgabeblack@google.com    return ret;
13812855Sgabeblack@google.com}
13912855Sgabeblack@google.com
14012855Sgabeblack@google.comuint64
14112855Sgabeblack@google.comDirectoryMemory::mapAddressToLocalIdx(PhysAddress address)
14212855Sgabeblack@google.com{
14312855Sgabeblack@google.com    uint64 ret;
14412855Sgabeblack@google.com    if (m_num_directories_bits > 0) {
14512855Sgabeblack@google.com        ret = address.bitRemove(m_numa_high_bit - m_num_directories_bits + 1,
14612855Sgabeblack@google.com                                m_numa_high_bit);
14712855Sgabeblack@google.com    } else {
14812855Sgabeblack@google.com        ret = address.getAddress();
149    }
150
151    return ret >> (RubySystem::getBlockSizeBits());
152}
153
154Directory_Entry&
155DirectoryMemory::lookup(PhysAddress address)
156{
157    assert(isPresent(address));
158    Directory_Entry* entry;
159    uint64 idx;
160    DEBUG_EXPR(CACHE_COMP, HighPrio, address);
161
162    if (m_use_map) {
163        if (m_sparseMemory->exist(address)) {
164            entry = m_sparseMemory->lookup(address);
165            assert(entry != NULL);
166        } else {
167            // Note: SparseMemory internally creates a new Directory Entry
168            m_sparseMemory->add(address);
169            entry = m_sparseMemory->lookup(address);
170        }
171    } else {
172        idx = mapAddressToLocalIdx(address);
173        assert(idx < m_num_entries);
174        entry = m_entries[idx];
175
176        if (entry == NULL) {
177            entry = new Directory_Entry();
178            entry->getDataBlk().assign(m_ram->getBlockPtr(address));
179            m_entries[idx] = entry;
180        }
181    }
182
183    return *entry;
184}
185
186#if 0
187Directory_Entry&
188DirectoryMemory::lookup(PhysAddress address)
189{
190    assert(isPresent(address));
191    Index index = address.memoryModuleIndex();
192
193    if (index < 0 || index > m_size) {
194        WARN_EXPR(address.getAddress());
195        WARN_EXPR(index);
196        WARN_EXPR(m_size);
197        ERROR_MSG("Directory Memory Assertion: accessing memory out of range");
198    }
199    Directory_Entry* entry = m_entries[index];
200
201    // allocate the directory entry on demand.
202    if (entry == NULL) {
203        entry = new Directory_Entry;
204        entry->getDataBlk().assign(m_ram->getBlockPtr(address));
205
206        // store entry to the table
207        m_entries[index] = entry;
208    }
209
210    return *entry;
211}
212#endif
213
214void
215DirectoryMemory::invalidateBlock(PhysAddress address)
216{
217    if (m_use_map) {
218        assert(m_sparseMemory->exist(address));
219        m_sparseMemory->remove(address);
220    }
221#if 0
222    else {
223        assert(isPresent(address));
224
225        Index index = address.memoryModuleIndex();
226
227        if (index < 0 || index > m_size) {
228            ERROR_MSG("Directory Memory Assertion: "
229                      "accessing memory out of range.");
230        }
231
232        if (m_entries[index] != NULL){
233            delete m_entries[index];
234            m_entries[index] = NULL;
235        }
236    }
237#endif
238}
239
240void
241DirectoryMemory::print(ostream& out) const
242{
243}
244
245void
246DirectoryMemory::printStats(ostream& out) const
247{
248    if (m_use_map) {
249        m_sparseMemory->printStats(out);
250    }
251}
252
253DirectoryMemory *
254RubyDirectoryMemoryParams::create()
255{
256    return new DirectoryMemory(this);
257}
258