DirectoryMemory.cc revision 7055
12381SN/A/* 210342SCurtis.Dunham@arm.com * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood 38949Sandreas.hansson@arm.com * All rights reserved. 48949Sandreas.hansson@arm.com * 58949Sandreas.hansson@arm.com * Redistribution and use in source and binary forms, with or without 68949Sandreas.hansson@arm.com * modification, are permitted provided that the following conditions are 78949Sandreas.hansson@arm.com * met: redistributions of source code must retain the above copyright 88949Sandreas.hansson@arm.com * notice, this list of conditions and the following disclaimer; 98949Sandreas.hansson@arm.com * redistributions in binary form must reproduce the above copyright 108949Sandreas.hansson@arm.com * notice, this list of conditions and the following disclaimer in the 118949Sandreas.hansson@arm.com * documentation and/or other materials provided with the distribution; 128949Sandreas.hansson@arm.com * neither the name of the copyright holders nor the names of its 138949Sandreas.hansson@arm.com * contributors may be used to endorse or promote products derived from 142592SN/A * this software without specific prior written permission. 157636Ssteve.reinhardt@amd.com * 162381SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 172381SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 182381SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 192381SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 202381SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 212381SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 222381SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 232381SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 242381SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 252381SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 262381SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 272381SN/A */ 282381SN/A 292381SN/A#include "mem/gems_common/util.hh" 302381SN/A#include "mem/ruby/slicc_interface/RubySlicc_Util.hh" 312381SN/A#include "mem/ruby/system/DirectoryMemory.hh" 322381SN/A#include "mem/ruby/system/System.hh" 332381SN/A 342381SN/Ausing namespace std; 352381SN/A 362381SN/Aint DirectoryMemory::m_num_directories = 0; 372381SN/Aint DirectoryMemory::m_num_directories_bits = 0; 382381SN/Auint64_t DirectoryMemory::m_total_size_bytes = 0; 392381SN/Aint DirectoryMemory::m_numa_high_bit = 0; 402665Ssaidi@eecs.umich.edu 412665Ssaidi@eecs.umich.eduDirectoryMemory::DirectoryMemory(const Params *p) 422665Ssaidi@eecs.umich.edu : SimObject(p) 432665Ssaidi@eecs.umich.edu{ 449031Sandreas.hansson@arm.com m_version = p->version; 452381SN/A m_size_bytes = p->size; 462381SN/A m_size_bits = log_int(m_size_bytes); 472381SN/A m_num_entries = 0; 482381SN/A m_use_map = p->use_map; 492662Sstever@eecs.umich.edu m_map_levels = p->map_levels; 502381SN/A m_numa_high_bit = p->numa_high_bit; 512381SN/A} 522381SN/A 532381SN/Avoid 542381SN/ADirectoryMemory::init() 558229Snate@binkert.org{ 563348Sbinkertn@umich.edu m_num_entries = m_size_bytes / RubySystem::getBlockSizeBytes(); 573348Sbinkertn@umich.edu 583348Sbinkertn@umich.edu if (m_use_map) { 595735Snate@binkert.org int entry_bits = log_int(m_num_entries); 604024Sbinkertn@umich.edu assert(entry_bits >= m_map_levels); 615735Snate@binkert.org m_sparseMemory = new SparseMemory(entry_bits, m_map_levels); 623940Ssaidi@eecs.umich.edu } else { 635314Sstever@gmail.com m_entries = new Directory_Entry*[m_num_entries]; 646216Snate@binkert.org for (int i = 0; i < m_num_entries; i++) 652392SN/A m_entries[i] = NULL; 664167Sbinkertn@umich.edu m_ram = g_system_ptr->getMemoryVector(); 672394SN/A } 688737Skoansin.tan@gmail.com 693349Sbinkertn@umich.edu m_num_directories++; 702394SN/A m_num_directories_bits = log_int(m_num_directories); 712812Srdreslin@umich.edu m_total_size_bytes += m_size_bytes; 722812Srdreslin@umich.edu 734022Sstever@eecs.umich.edu if (m_numa_high_bit == 0) { 744022Sstever@eecs.umich.edu m_numa_high_bit = RubySystem::getMemorySizeBits(); 755735Snate@binkert.org } 765735Snate@binkert.org assert(m_numa_high_bit != 0); 774022Sstever@eecs.umich.edu} 785735Snate@binkert.org 795735Snate@binkert.orgDirectoryMemory::~DirectoryMemory() 805735Snate@binkert.org{ 814022Sstever@eecs.umich.edu // free up all the directory entries 824022Sstever@eecs.umich.edu if (m_entries != NULL) { 834022Sstever@eecs.umich.edu for (uint64 i = 0; i < m_num_entries; i++) { 844022Sstever@eecs.umich.edu if (m_entries[i] != NULL) { 854473Sstever@eecs.umich.edu delete m_entries[i]; 865319Sstever@gmail.com } 874022Sstever@eecs.umich.edu } 884022Sstever@eecs.umich.edu delete [] m_entries; 894022Sstever@eecs.umich.edu } else if (m_use_map) { 904022Sstever@eecs.umich.edu delete m_sparseMemory; 914022Sstever@eecs.umich.edu } 924022Sstever@eecs.umich.edu} 934022Sstever@eecs.umich.edu 944022Sstever@eecs.umich.eduvoid 954022Sstever@eecs.umich.eduDirectoryMemory::printConfig(ostream& out) const 964022Sstever@eecs.umich.edu{ 977465Ssteve.reinhardt@amd.com out << "DirectoryMemory module config: " << m_name << endl 984628Sstever@eecs.umich.edu << " version: " << m_version << endl 997465Ssteve.reinhardt@amd.com << " memory_bits: " << m_size_bits << endl 1007465Ssteve.reinhardt@amd.com << " memory_size_bytes: " << m_size_bytes << endl 1014022Sstever@eecs.umich.edu << " memory_size_Kbytes: " << double(m_size_bytes) / (1<<10) << endl 1024022Sstever@eecs.umich.edu << " memory_size_Mbytes: " << double(m_size_bytes) / (1<<20) << endl 1034626Sstever@eecs.umich.edu << " memory_size_Gbytes: " << double(m_size_bytes) / (1<<30) << endl; 1044626Sstever@eecs.umich.edu} 1057669Ssteve.reinhardt@amd.com 1064626Sstever@eecs.umich.edu// Static method 1074040Ssaidi@eecs.umich.eduvoid 1084040Ssaidi@eecs.umich.eduDirectoryMemory::printGlobalConfig(ostream & out) 1095650Sgblack@eecs.umich.edu{ 1105650Sgblack@eecs.umich.edu out << "DirectoryMemory Global Config: " << endl; 1114870Sstever@eecs.umich.edu out << " number of directory memories: " << m_num_directories << endl; 1124870Sstever@eecs.umich.edu if (m_num_directories > 1) { 1134870Sstever@eecs.umich.edu out << " number of selection bits: " << m_num_directories_bits << endl 1144870Sstever@eecs.umich.edu << " selection bits: " << m_numa_high_bit 1154870Sstever@eecs.umich.edu << "-" << m_numa_high_bit-m_num_directories_bits 1164870Sstever@eecs.umich.edu << endl; 1178436SBrad.Beckmann@amd.com } 1188436SBrad.Beckmann@amd.com out << " total memory size bytes: " << m_total_size_bytes << endl; 1195314Sstever@gmail.com out << " total memory bits: " << log_int(m_total_size_bytes) << endl; 1205314Sstever@gmail.com} 1218184Ssomayeh@cs.wisc.edu 1228716Snilay@cs.wisc.eduuint64 1234022Sstever@eecs.umich.eduDirectoryMemory::mapAddressToDirectoryVersion(PhysAddress address) 1244022Sstever@eecs.umich.edu{ 1254022Sstever@eecs.umich.edu if (m_num_directories_bits == 0) 1264022Sstever@eecs.umich.edu return 0; 1275735Snate@binkert.org 1285735Snate@binkert.org uint64 ret = address.bitSelect(m_numa_high_bit - m_num_directories_bits, 1295735Snate@binkert.org m_numa_high_bit); 1304022Sstever@eecs.umich.edu return ret; 1314022Sstever@eecs.umich.edu} 1324626Sstever@eecs.umich.edu 1334626Sstever@eecs.umich.edubool 1347465Ssteve.reinhardt@amd.comDirectoryMemory::isPresent(PhysAddress address) 1354022Sstever@eecs.umich.edu{ 1364626Sstever@eecs.umich.edu bool ret = (mapAddressToDirectoryVersion(address) == m_version); 1374626Sstever@eecs.umich.edu return ret; 1384626Sstever@eecs.umich.edu} 1394626Sstever@eecs.umich.edu 1404022Sstever@eecs.umich.eduuint64 1414022Sstever@eecs.umich.eduDirectoryMemory::mapAddressToLocalIdx(PhysAddress address) 1426076Sgblack@eecs.umich.edu{ 1434626Sstever@eecs.umich.edu uint64 ret = address.bitRemove(m_numa_high_bit - m_num_directories_bits, 1444870Sstever@eecs.umich.edu m_numa_high_bit) 1455314Sstever@gmail.com >> (RubySystem::getBlockSizeBits()); 1468184Ssomayeh@cs.wisc.edu return ret; 1474022Sstever@eecs.umich.edu} 1484022Sstever@eecs.umich.edu 1494022Sstever@eecs.umich.eduDirectory_Entry& 1505735Snate@binkert.orgDirectoryMemory::lookup(PhysAddress address) 1515735Snate@binkert.org{ 1525735Snate@binkert.org assert(isPresent(address)); 1535735Snate@binkert.org Directory_Entry* entry; 1545735Snate@binkert.org uint64 idx; 1555735Snate@binkert.org DEBUG_EXPR(CACHE_COMP, HighPrio, address); 1565735Snate@binkert.org 1574022Sstever@eecs.umich.edu if (m_use_map) { 1585735Snate@binkert.org if (m_sparseMemory->exist(address)) { 1595735Snate@binkert.org entry = m_sparseMemory->lookup(address); 1604022Sstever@eecs.umich.edu assert(entry != NULL); 1615735Snate@binkert.org } else { 1624022Sstever@eecs.umich.edu // Note: SparseMemory internally creates a new Directory Entry 1634022Sstever@eecs.umich.edu m_sparseMemory->add(address); 1644022Sstever@eecs.umich.edu entry = m_sparseMemory->lookup(address); 1655735Snate@binkert.org } 1664022Sstever@eecs.umich.edu } else { 1674022Sstever@eecs.umich.edu idx = mapAddressToLocalIdx(address); 1684022Sstever@eecs.umich.edu assert(idx < m_num_entries); 1694022Sstever@eecs.umich.edu entry = m_entries[idx]; 1704022Sstever@eecs.umich.edu 1714022Sstever@eecs.umich.edu if (entry == NULL) { 1725735Snate@binkert.org entry = new Directory_Entry(); 1735735Snate@binkert.org entry->getDataBlk().assign(m_ram->getBlockPtr(address)); 1745735Snate@binkert.org m_entries[idx] = entry; 1754022Sstever@eecs.umich.edu } 1764022Sstever@eecs.umich.edu } 1774022Sstever@eecs.umich.edu 1784022Sstever@eecs.umich.edu return *entry; 1794022Sstever@eecs.umich.edu} 1804022Sstever@eecs.umich.edu 1817465Ssteve.reinhardt@amd.com#if 0 1827465Ssteve.reinhardt@amd.comDirectory_Entry& 1834022Sstever@eecs.umich.eduDirectoryMemory::lookup(PhysAddress address) 1844022Sstever@eecs.umich.edu{ 1854870Sstever@eecs.umich.edu assert(isPresent(address)); 1864022Sstever@eecs.umich.edu Index index = address.memoryModuleIndex(); 1874022Sstever@eecs.umich.edu 1884022Sstever@eecs.umich.edu if (index < 0 || index > m_size) { 1894626Sstever@eecs.umich.edu WARN_EXPR(address.getAddress()); 1906102Sgblack@eecs.umich.edu WARN_EXPR(index); 19110343SCurtis.Dunham@arm.com WARN_EXPR(m_size); 19210343SCurtis.Dunham@arm.com ERROR_MSG("Directory Memory Assertion: accessing memory out of range"); 19310343SCurtis.Dunham@arm.com } 19410343SCurtis.Dunham@arm.com Directory_Entry* entry = m_entries[index]; 1954870Sstever@eecs.umich.edu 1965314Sstever@gmail.com // allocate the directory entry on demand. 1978184Ssomayeh@cs.wisc.edu if (entry == NULL) { 1984022Sstever@eecs.umich.edu entry = new Directory_Entry; 1995735Snate@binkert.org entry->getDataBlk().assign(m_ram->getBlockPtr(address)); 2005735Snate@binkert.org 2015735Snate@binkert.org // store entry to the table 2024022Sstever@eecs.umich.edu m_entries[index] = entry; 2034022Sstever@eecs.umich.edu } 2044022Sstever@eecs.umich.edu 2055735Snate@binkert.org return *entry; 2065735Snate@binkert.org} 2074022Sstever@eecs.umich.edu#endif 2084022Sstever@eecs.umich.edu 2095735Snate@binkert.orgvoid 2105735Snate@binkert.orgDirectoryMemory::invalidateBlock(PhysAddress address) 2115735Snate@binkert.org{ 2124022Sstever@eecs.umich.edu if (m_use_map) { 2135735Snate@binkert.org assert(m_sparseMemory->exist(address)); 2145735Snate@binkert.org m_sparseMemory->remove(address); 2154022Sstever@eecs.umich.edu } 2164022Sstever@eecs.umich.edu#if 0 2172381SN/A else { 2182662Sstever@eecs.umich.edu assert(isPresent(address)); 2192662Sstever@eecs.umich.edu 2202662Sstever@eecs.umich.edu Index index = address.memoryModuleIndex(); 2212662Sstever@eecs.umich.edu 2222662Sstever@eecs.umich.edu if (index < 0 || index > m_size) { 2232381SN/A ERROR_MSG("Directory Memory Assertion: " 2249044SAli.Saidi@ARM.com "accessing memory out of range."); 2252381SN/A } 2262813Srdreslin@umich.edu 2275735Snate@binkert.org if (m_entries[index] != NULL){ 2285735Snate@binkert.org delete m_entries[index]; 2294022Sstever@eecs.umich.edu m_entries[index] = NULL; 2305735Snate@binkert.org } 2315735Snate@binkert.org } 2325735Snate@binkert.org#endif 2335735Snate@binkert.org} 2345735Snate@binkert.org 2355735Snate@binkert.orgvoid 2365735Snate@binkert.orgDirectoryMemory::print(ostream& out) const 2375735Snate@binkert.org{ 2385735Snate@binkert.org} 2395735Snate@binkert.org 2405735Snate@binkert.orgvoid 2415735Snate@binkert.orgDirectoryMemory::printStats(ostream& out) const 2425735Snate@binkert.org{ 2435735Snate@binkert.org if (m_use_map) { 2445735Snate@binkert.org m_sparseMemory->printStats(out); 2455735Snate@binkert.org } 2465735Snate@binkert.org} 2475735Snate@binkert.org 2485735Snate@binkert.orgDirectoryMemory * 2495735Snate@binkert.orgRubyDirectoryMemoryParams::create() 2505735Snate@binkert.org{ 2515735Snate@binkert.org return new DirectoryMemory(this); 2525735Snate@binkert.org} 2535735Snate@binkert.org