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