DirectoryMemory.cc revision 7056
12SN/A/* 21762SN/A * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood 32SN/A * All rights reserved. 42SN/A * 52SN/A * Redistribution and use in source and binary forms, with or without 62SN/A * modification, are permitted provided that the following conditions are 72SN/A * met: redistributions of source code must retain the above copyright 82SN/A * notice, this list of conditions and the following disclaimer; 92SN/A * redistributions in binary form must reproduce the above copyright 102SN/A * notice, this list of conditions and the following disclaimer in the 112SN/A * documentation and/or other materials provided with the distribution; 122SN/A * neither the name of the copyright holders nor the names of its 132SN/A * contributors may be used to endorse or promote products derived from 142SN/A * this software without specific prior written permission. 152SN/A * 162SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 172SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 182SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 192SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 202SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 212SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 222SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 232SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 242SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 252SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 262SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 272665Ssaidi@eecs.umich.edu */ 282665Ssaidi@eecs.umich.edu 292665Ssaidi@eecs.umich.edu#include "base/intmath.hh" 302SN/A#include "mem/ruby/slicc_interface/RubySlicc_Util.hh" 312SN/A#include "mem/ruby/system/DirectoryMemory.hh" 322SN/A#include "mem/ruby/system/System.hh" 332SN/A 342SN/Ausing namespace std; 351984SN/A 36857SN/Aint DirectoryMemory::m_num_directories = 0; 375952Ssaidi@eecs.umich.eduint DirectoryMemory::m_num_directories_bits = 0; 381984SN/Auint64_t DirectoryMemory::m_total_size_bytes = 0; 396214Snate@binkert.orgint DirectoryMemory::m_numa_high_bit = 0; 4010905Sandreas.sandberg@arm.com 412SN/ADirectoryMemory::DirectoryMemory(const Params *p) 422SN/A : SimObject(p) 432SN/A{ 441912SN/A m_version = p->version; 4511537Sandreas.sandberg@arm.com m_size_bytes = p->size; 46857SN/A m_size_bits = floorLog2(m_size_bytes); 472SN/A m_num_entries = 0; 481912SN/A m_use_map = p->use_map; 492SN/A m_map_levels = p->map_levels; 502SN/A m_numa_high_bit = p->numa_high_bit; 512SN/A} 521912SN/A 531912SN/Avoid 541912SN/ADirectoryMemory::init() 551912SN/A{ 561912SN/A m_num_entries = m_size_bytes / RubySystem::getBlockSizeBytes(); 571912SN/A 581912SN/A if (m_use_map) { 591912SN/A int entry_bits = floorLog2(m_num_entries); 601912SN/A assert(entry_bits >= m_map_levels); 611912SN/A m_sparseMemory = new SparseMemory(entry_bits, m_map_levels); 621912SN/A } else { 631912SN/A m_entries = new Directory_Entry*[m_num_entries]; 641912SN/A for (int i = 0; i < m_num_entries; i++) 651912SN/A m_entries[i] = NULL; 662SN/A m_ram = g_system_ptr->getMemoryVector(); 672SN/A } 682SN/A 692SN/A m_num_directories++; 702SN/A m_num_directories_bits = floorLog2(m_num_directories); 711984SN/A m_total_size_bytes += m_size_bytes; 722SN/A 732SN/A if (m_numa_high_bit == 0) { 742SN/A m_numa_high_bit = RubySystem::getMemorySizeBits(); 751912SN/A } 761912SN/A assert(m_numa_high_bit != 0); 771912SN/A} 781912SN/A 7910905Sandreas.sandberg@arm.comDirectoryMemory::~DirectoryMemory() 8010905Sandreas.sandberg@arm.com{ 811984SN/A // free up all the directory entries 821984SN/A if (m_entries != NULL) { 831912SN/A for (uint64 i = 0; i < m_num_entries; i++) { 841912SN/A if (m_entries[i] != NULL) { 851912SN/A delete m_entries[i]; 861912SN/A } 871912SN/A } 881912SN/A delete [] m_entries; 891912SN/A } else if (m_use_map) { 9011537Sandreas.sandberg@arm.com delete m_sparseMemory; 9111537Sandreas.sandberg@arm.com } 921912SN/A} 931912SN/A 941912SN/Avoid 951912SN/ADirectoryMemory::printConfig(ostream& out) const 961912SN/A{ 971912SN/A out << "DirectoryMemory module config: " << m_name << endl 981912SN/A << " version: " << m_version << endl 991912SN/A << " memory_bits: " << m_size_bits << endl 1001912SN/A << " memory_size_bytes: " << m_size_bytes << endl 1011912SN/A << " memory_size_Kbytes: " << double(m_size_bytes) / (1<<10) << endl 1021912SN/A << " memory_size_Mbytes: " << double(m_size_bytes) / (1<<20) << endl 1031912SN/A << " memory_size_Gbytes: " << double(m_size_bytes) / (1<<30) << endl; 1041912SN/A} 1051912SN/A 1061912SN/A// Static method 1071158SN/Avoid 1081158SN/ADirectoryMemory::printGlobalConfig(ostream & out) 1092982Sstever@eecs.umich.edu{ 1102982Sstever@eecs.umich.edu out << "DirectoryMemory Global Config: " << endl; 1112982Sstever@eecs.umich.edu out << " number of directory memories: " << m_num_directories << endl; 1122982Sstever@eecs.umich.edu if (m_num_directories > 1) { 1132982Sstever@eecs.umich.edu out << " number of selection bits: " << m_num_directories_bits << endl 1141158SN/A << " selection bits: " << m_numa_high_bit 1151912SN/A << "-" << m_numa_high_bit-m_num_directories_bits 1161912SN/A << endl; 1171912SN/A } 1181912SN/A out << " total memory size bytes: " << m_total_size_bytes << endl; 1191912SN/A out << " total memory bits: " << floorLog2(m_total_size_bytes) << endl; 1201912SN/A} 1211912SN/A 1221912SN/Auint64 1231912SN/ADirectoryMemory::mapAddressToDirectoryVersion(PhysAddress address) 1241912SN/A{ 1251912SN/A if (m_num_directories_bits == 0) 1261912SN/A return 0; 1271912SN/A 1281912SN/A uint64 ret = address.bitSelect(m_numa_high_bit - m_num_directories_bits, 1291158SN/A m_numa_high_bit); 1301158SN/A return ret; 1312982Sstever@eecs.umich.edu} 1321912SN/A 1331912SN/Abool 1341158SN/ADirectoryMemory::isPresent(PhysAddress address) 1351912SN/A{ 1361912SN/A bool ret = (mapAddressToDirectoryVersion(address) == m_version); 1371912SN/A return ret; 1381912SN/A} 1391912SN/A 1401912SN/Auint64 1411912SN/ADirectoryMemory::mapAddressToLocalIdx(PhysAddress address) 1421912SN/A{ 1431158SN/A uint64 ret = address.bitRemove(m_numa_high_bit - m_num_directories_bits, 1441158SN/A m_numa_high_bit) 1451158SN/A >> (RubySystem::getBlockSizeBits()); 1461912SN/A return ret; 1471912SN/A} 1481912SN/A 1491912SN/ADirectory_Entry& 1501912SN/ADirectoryMemory::lookup(PhysAddress address) 1511912SN/A{ 1521912SN/A assert(isPresent(address)); 1531912SN/A Directory_Entry* entry; 1541912SN/A uint64 idx; 1551912SN/A DEBUG_EXPR(CACHE_COMP, HighPrio, address); 1561912SN/A 1571912SN/A if (m_use_map) { 1581912SN/A if (m_sparseMemory->exist(address)) { 1591912SN/A entry = m_sparseMemory->lookup(address); 1601912SN/A assert(entry != NULL); 1611912SN/A } else { 1621912SN/A // Note: SparseMemory internally creates a new Directory Entry 1631912SN/A m_sparseMemory->add(address); 1641912SN/A entry = m_sparseMemory->lookup(address); 1651912SN/A } 1661912SN/A } else { 1671912SN/A idx = mapAddressToLocalIdx(address); 1681912SN/A assert(idx < m_num_entries); 1691912SN/A entry = m_entries[idx]; 1702SN/A 1712SN/A if (entry == NULL) { 1721158SN/A entry = new Directory_Entry(); 1731158SN/A entry->getDataBlk().assign(m_ram->getBlockPtr(address)); 1741158SN/A m_entries[idx] = entry; 1751158SN/A } 1761158SN/A } 1771158SN/A 1782SN/A return *entry; 179} 180 181#if 0 182Directory_Entry& 183DirectoryMemory::lookup(PhysAddress address) 184{ 185 assert(isPresent(address)); 186 Index index = address.memoryModuleIndex(); 187 188 if (index < 0 || index > m_size) { 189 WARN_EXPR(address.getAddress()); 190 WARN_EXPR(index); 191 WARN_EXPR(m_size); 192 ERROR_MSG("Directory Memory Assertion: accessing memory out of range"); 193 } 194 Directory_Entry* entry = m_entries[index]; 195 196 // allocate the directory entry on demand. 197 if (entry == NULL) { 198 entry = new Directory_Entry; 199 entry->getDataBlk().assign(m_ram->getBlockPtr(address)); 200 201 // store entry to the table 202 m_entries[index] = entry; 203 } 204 205 return *entry; 206} 207#endif 208 209void 210DirectoryMemory::invalidateBlock(PhysAddress address) 211{ 212 if (m_use_map) { 213 assert(m_sparseMemory->exist(address)); 214 m_sparseMemory->remove(address); 215 } 216#if 0 217 else { 218 assert(isPresent(address)); 219 220 Index index = address.memoryModuleIndex(); 221 222 if (index < 0 || index > m_size) { 223 ERROR_MSG("Directory Memory Assertion: " 224 "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#endif 233} 234 235void 236DirectoryMemory::print(ostream& out) const 237{ 238} 239 240void 241DirectoryMemory::printStats(ostream& out) const 242{ 243 if (m_use_map) { 244 m_sparseMemory->printStats(out); 245 } 246} 247 248DirectoryMemory * 249RubyDirectoryMemoryParams::create() 250{ 251 return new DirectoryMemory(this); 252} 253