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