DirectoryMemory.cc revision 10301
16145SN/A/* 26145SN/A * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood 36145SN/A * All rights reserved. 46145SN/A * 56145SN/A * Redistribution and use in source and binary forms, with or without 66145SN/A * modification, are permitted provided that the following conditions are 76145SN/A * met: redistributions of source code must retain the above copyright 86145SN/A * notice, this list of conditions and the following disclaimer; 96145SN/A * redistributions in binary form must reproduce the above copyright 106145SN/A * notice, this list of conditions and the following disclaimer in the 116145SN/A * documentation and/or other materials provided with the distribution; 126145SN/A * neither the name of the copyright holders nor the names of its 136145SN/A * contributors may be used to endorse or promote products derived from 146145SN/A * this software without specific prior written permission. 156145SN/A * 166145SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 176145SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 186145SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 196145SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 206145SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 216145SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 226145SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 236145SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 246145SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 256145SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 266145SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 276145SN/A */ 286145SN/A 297056SN/A#include "base/intmath.hh" 308232SN/A#include "debug/RubyCache.hh" 319104SN/A#include "debug/RubyStats.hh" 327039SN/A#include "mem/ruby/slicc_interface/RubySlicc_Util.hh" 3310301Snilay@cs.wisc.edu#include "mem/ruby/structures/DirectoryMemory.hh" 346154SN/A#include "mem/ruby/system/System.hh" 356145SN/A 367055SN/Ausing namespace std; 377055SN/A 386285SN/Aint DirectoryMemory::m_num_directories = 0; 396285SN/Aint DirectoryMemory::m_num_directories_bits = 0; 406861SN/Auint64_t DirectoryMemory::m_total_size_bytes = 0; 417027SN/Aint DirectoryMemory::m_numa_high_bit = 0; 426285SN/A 436876SN/ADirectoryMemory::DirectoryMemory(const Params *p) 446876SN/A : SimObject(p) 456145SN/A{ 466876SN/A m_version = p->version; 476903SN/A m_size_bytes = p->size; 487056SN/A m_size_bits = floorLog2(m_size_bytes); 497025SN/A m_num_entries = 0; 507025SN/A m_use_map = p->use_map; 517025SN/A m_map_levels = p->map_levels; 527027SN/A m_numa_high_bit = p->numa_high_bit; 536285SN/A} 546285SN/A 557039SN/Avoid 567039SN/ADirectoryMemory::init() 576285SN/A{ 587039SN/A m_num_entries = m_size_bytes / RubySystem::getBlockSizeBytes(); 597025SN/A 607039SN/A if (m_use_map) { 617917SN/A m_sparseMemory = new SparseMemory(m_map_levels); 628688SN/A g_system_ptr->registerSparseMemory(m_sparseMemory); 637039SN/A } else { 648644SN/A m_entries = new AbstractEntry*[m_num_entries]; 657039SN/A for (int i = 0; i < m_num_entries; i++) 667039SN/A m_entries[i] = NULL; 677039SN/A m_ram = g_system_ptr->getMemoryVector(); 687039SN/A } 696285SN/A 707039SN/A m_num_directories++; 7110004SN/A m_num_directories_bits = ceilLog2(m_num_directories); 727039SN/A m_total_size_bytes += m_size_bytes; 737027SN/A 747039SN/A if (m_numa_high_bit == 0) { 757563SN/A m_numa_high_bit = RubySystem::getMemorySizeBits() - 1; 767039SN/A } 777039SN/A assert(m_numa_high_bit != 0); 786145SN/A} 796145SN/A 806145SN/ADirectoryMemory::~DirectoryMemory() 816145SN/A{ 827039SN/A // free up all the directory entries 837039SN/A if (m_entries != NULL) { 847039SN/A for (uint64 i = 0; i < m_num_entries; i++) { 857039SN/A if (m_entries[i] != NULL) { 867039SN/A delete m_entries[i]; 877039SN/A } 887039SN/A } 897039SN/A delete [] m_entries; 907039SN/A } else if (m_use_map) { 917039SN/A delete m_sparseMemory; 927039SN/A } 936285SN/A} 946145SN/A 957039SN/Auint64 967039SN/ADirectoryMemory::mapAddressToDirectoryVersion(PhysAddress address) 976285SN/A{ 987039SN/A if (m_num_directories_bits == 0) 997039SN/A return 0; 1007039SN/A 1017563SN/A uint64 ret = address.bitSelect(m_numa_high_bit - m_num_directories_bits + 1, 1027039SN/A m_numa_high_bit); 1037039SN/A return ret; 1046145SN/A} 1056145SN/A 1067039SN/Abool 1077039SN/ADirectoryMemory::isPresent(PhysAddress address) 1086145SN/A{ 1097039SN/A bool ret = (mapAddressToDirectoryVersion(address) == m_version); 1107039SN/A return ret; 1116145SN/A} 1126145SN/A 1137039SN/Auint64 1147039SN/ADirectoryMemory::mapAddressToLocalIdx(PhysAddress address) 1156161SN/A{ 1167563SN/A uint64 ret; 1177563SN/A if (m_num_directories_bits > 0) { 1187563SN/A ret = address.bitRemove(m_numa_high_bit - m_num_directories_bits + 1, 1197563SN/A m_numa_high_bit); 1207563SN/A } else { 1217563SN/A ret = address.getAddress(); 1227563SN/A } 1237563SN/A 1247563SN/A return ret >> (RubySystem::getBlockSizeBits()); 1256161SN/A} 1266161SN/A 1278644SN/AAbstractEntry* 1287039SN/ADirectoryMemory::lookup(PhysAddress address) 1296145SN/A{ 1307039SN/A assert(isPresent(address)); 1318644SN/A DPRINTF(RubyCache, "Looking up address: %s\n", address); 1328644SN/A 1338644SN/A if (m_use_map) { 1348644SN/A return m_sparseMemory->lookup(address); 1358644SN/A } else { 1368644SN/A uint64_t idx = mapAddressToLocalIdx(address); 1378644SN/A assert(idx < m_num_entries); 1388644SN/A return m_entries[idx]; 1398644SN/A } 1408644SN/A} 1418644SN/A 1428644SN/AAbstractEntry* 1438644SN/ADirectoryMemory::allocate(const PhysAddress& address, AbstractEntry* entry) 1448644SN/A{ 1458644SN/A assert(isPresent(address)); 1467039SN/A uint64 idx; 1478436SN/A DPRINTF(RubyCache, "Looking up address: %s\n", address); 1487025SN/A 1497039SN/A if (m_use_map) { 1508644SN/A m_sparseMemory->add(address, entry); 1518644SN/A entry->changePermission(AccessPermission_Read_Write); 1527025SN/A } else { 1537039SN/A idx = mapAddressToLocalIdx(address); 1547039SN/A assert(idx < m_num_entries); 1558644SN/A entry->getDataBlk().assign(m_ram->getBlockPtr(address)); 1568644SN/A entry->changePermission(AccessPermission_Read_Only); 1578644SN/A m_entries[idx] = entry; 1587025SN/A } 1596145SN/A 1608644SN/A return entry; 1616145SN/A} 1626145SN/A 1637039SN/Avoid 1647039SN/ADirectoryMemory::invalidateBlock(PhysAddress address) 1657039SN/A{ 1667039SN/A if (m_use_map) { 1677039SN/A assert(m_sparseMemory->exist(address)); 1687039SN/A m_sparseMemory->remove(address); 1697039SN/A } 1707039SN/A#if 0 1717039SN/A else { 1727039SN/A assert(isPresent(address)); 1737039SN/A 1747039SN/A Index index = address.memoryModuleIndex(); 1757054SN/A 1767039SN/A if (index < 0 || index > m_size) { 1777039SN/A ERROR_MSG("Directory Memory Assertion: " 1787039SN/A "accessing memory out of range."); 1797039SN/A } 1807039SN/A 1817039SN/A if (m_entries[index] != NULL){ 1827039SN/A delete m_entries[index]; 1837039SN/A m_entries[index] = NULL; 1847039SN/A } 1857039SN/A } 1867039SN/A#endif 1876145SN/A} 1886145SN/A 1897039SN/Avoid 1907039SN/ADirectoryMemory::print(ostream& out) const 1917039SN/A{ 1927039SN/A} 1937039SN/A 1947039SN/Avoid 1959856SN/ADirectoryMemory::regStats() 1967025SN/A{ 1977025SN/A if (m_use_map) { 1989856SN/A m_sparseMemory->regStats(name()); 1997025SN/A } 2007025SN/A} 2017025SN/A 2029104SN/Avoid 2039104SN/ADirectoryMemory::recordRequestType(DirectoryRequestType requestType) { 2049104SN/A DPRINTF(RubyStats, "Recorded statistic: %s\n", 2059104SN/A DirectoryRequestType_to_string(requestType)); 2069104SN/A} 2079104SN/A 2086876SN/ADirectoryMemory * 2096876SN/ARubyDirectoryMemoryParams::create() 2106876SN/A{ 2116876SN/A return new DirectoryMemory(this); 2126876SN/A} 213