DirectoryMemory.cc revision 7027
1 2/* 3 * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions are 8 * met: redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer; 10 * redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution; 13 * neither the name of the copyright holders nor the names of its 14 * contributors may be used to endorse or promote products derived from 15 * this software without specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 */ 29 30/* 31 * DirectoryMemory.cc 32 * 33 * Description: See DirectoryMemory.hh 34 * 35 * $Id$ 36 * 37 */ 38 39#include "mem/ruby/system/System.hh" 40#include "mem/ruby/system/DirectoryMemory.hh" 41#include "mem/ruby/slicc_interface/RubySlicc_Util.hh" 42#include "mem/gems_common/util.hh" 43 44int DirectoryMemory::m_num_directories = 0; 45int DirectoryMemory::m_num_directories_bits = 0; 46uint64_t DirectoryMemory::m_total_size_bytes = 0; 47int DirectoryMemory::m_numa_high_bit = 0; 48 49DirectoryMemory::DirectoryMemory(const Params *p) 50 : SimObject(p) 51{ 52 m_version = p->version; 53 m_size_bytes = p->size; 54 m_size_bits = log_int(m_size_bytes); 55 m_num_entries = 0; 56 m_use_map = p->use_map; 57 m_map_levels = p->map_levels; 58 m_numa_high_bit = p->numa_high_bit; 59} 60 61void DirectoryMemory::init() 62{ 63 m_num_entries = m_size_bytes / RubySystem::getBlockSizeBytes(); 64 65 if (m_use_map) { 66 int entry_bits = log_int(m_num_entries); 67 assert(entry_bits >= m_map_levels); 68 m_sparseMemory = new SparseMemory(entry_bits, m_map_levels); 69 } else { 70 m_entries = new Directory_Entry*[m_num_entries]; 71 for (int i=0; i < m_num_entries; i++) 72 m_entries[i] = NULL; 73 m_ram = g_system_ptr->getMemoryVector(); 74 } 75 76 m_num_directories++; 77 m_num_directories_bits = log_int(m_num_directories); 78 m_total_size_bytes += m_size_bytes; 79 80 if (m_numa_high_bit == 0) { 81 m_numa_high_bit = RubySystem::getMemorySizeBits(); 82 } 83 assert(m_numa_high_bit != 0); 84} 85 86DirectoryMemory::~DirectoryMemory() 87{ 88 // free up all the directory entries 89 if (m_entries != NULL) { 90 for (uint64 i = 0; i < m_num_entries; i++) { 91 if (m_entries[i] != NULL) { 92 delete m_entries[i]; 93 } 94 } 95 delete [] m_entries; 96 } else if (m_use_map) { 97 delete m_sparseMemory; 98 } 99} 100 101void DirectoryMemory::printConfig(ostream& out) const 102{ 103 out << "DirectoryMemory module config: " << m_name << endl; 104 out << " version: " << m_version << endl; 105 out << " memory_bits: " << m_size_bits << endl; 106 out << " memory_size_bytes: " << m_size_bytes << endl; 107 out << " memory_size_Kbytes: " << double(m_size_bytes) / (1<<10) << endl; 108 out << " memory_size_Mbytes: " << double(m_size_bytes) / (1<<20) << endl; 109 out << " memory_size_Gbytes: " << double(m_size_bytes) / (1<<30) << endl; 110} 111 112// Static method 113void DirectoryMemory::printGlobalConfig(ostream & out) 114{ 115 out << "DirectoryMemory Global Config: " << endl; 116 out << " number of directory memories: " << m_num_directories << endl; 117 if (m_num_directories > 1) { 118 out << " number of selection bits: " << m_num_directories_bits << endl; 119 out << " selection bits: " << m_numa_high_bit 120 << "-" << m_numa_high_bit-m_num_directories_bits 121 << endl; 122 } 123 out << " total memory size bytes: " << m_total_size_bytes << endl; 124 out << " total memory bits: " << log_int(m_total_size_bytes) << endl; 125 126} 127 128uint64 DirectoryMemory::mapAddressToDirectoryVersion(PhysAddress address) 129{ 130 if (m_num_directories_bits == 0) return 0; 131 uint64 ret = address.bitSelect(m_numa_high_bit - m_num_directories_bits, 132 m_numa_high_bit); 133 return ret; 134} 135 136// Public method 137bool DirectoryMemory::isPresent(PhysAddress address) 138{ 139 bool ret = (mapAddressToDirectoryVersion(address) == m_version); 140 return ret; 141} 142 143uint64 DirectoryMemory::mapAddressToLocalIdx(PhysAddress address) 144{ 145 uint64 ret = address.bitRemove(m_numa_high_bit - m_num_directories_bits, 146 m_numa_high_bit) 147 >> (RubySystem::getBlockSizeBits()); 148 return ret; 149} 150 151Directory_Entry& DirectoryMemory::lookup(PhysAddress address) 152{ 153 assert(isPresent(address)); 154 Directory_Entry* entry; 155 uint64 idx; 156 DEBUG_EXPR(CACHE_COMP, HighPrio, address); 157 158 if (m_use_map) { 159 if (m_sparseMemory->exist(address)) { 160 entry = m_sparseMemory->lookup(address); 161 assert(entry != NULL); 162 } else { 163 // 164 // Note: SparseMemory internally creates a new Directory Entry 165 // 166 m_sparseMemory->add(address); 167 entry = m_sparseMemory->lookup(address); 168 } 169 } else { 170 idx = mapAddressToLocalIdx(address); 171 assert(idx < m_num_entries); 172 entry = m_entries[idx]; 173 174 if (entry == NULL) { 175 entry = new Directory_Entry(); 176 entry->getDataBlk().assign(m_ram->getBlockPtr(address)); 177 m_entries[idx] = entry; 178 } 179 } 180 181 return (*entry); 182} 183/* 184Directory_Entry& DirectoryMemory::lookup(PhysAddress address) 185{ 186 assert(isPresent(address)); 187 Index index = address.memoryModuleIndex(); 188 189 if (index < 0 || index > m_size) { 190 WARN_EXPR(address.getAddress()); 191 WARN_EXPR(index); 192 WARN_EXPR(m_size); 193 ERROR_MSG("Directory Memory Assertion: accessing memory out of range."); 194 } 195 Directory_Entry* entry = m_entries[index]; 196 197 // allocate the directory entry on demand. 198 if (entry == NULL) { 199 entry = new Directory_Entry; 200 entry->getDataBlk().assign(m_ram->getBlockPtr(address)); 201 202 // store entry to the table 203 m_entries[index] = entry; 204 } 205 206 return (*entry); 207} 208*/ 209 210void DirectoryMemory::invalidateBlock(PhysAddress address) 211{ 212 213 if (m_use_map) { 214 assert(m_sparseMemory->exist(address)); 215 m_sparseMemory->remove(address); 216 } 217 /* 218 else { 219 assert(isPresent(address)); 220 221 Index index = address.memoryModuleIndex(); 222 223 if (index < 0 || index > m_size) { 224 ERROR_MSG("Directory Memory Assertion: accessing memory out of range."); 225 } 226 227 if(m_entries[index] != NULL){ 228 delete m_entries[index]; 229 m_entries[index] = NULL; 230 } 231 } 232 */ 233 234 235} 236 237void DirectoryMemory::print(ostream& out) const 238{ 239 240} 241 242void DirectoryMemory::printStats(ostream& out) const 243{ 244 if (m_use_map) { 245 m_sparseMemory->printStats(out); 246 } 247} 248 249DirectoryMemory * 250RubyDirectoryMemoryParams::create() 251{ 252 return new DirectoryMemory(this); 253} 254