DirectoryMemory.cc revision 8688
1955SN/A/* 2955SN/A * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood 31762SN/A * All rights reserved. 4955SN/A * 5955SN/A * Redistribution and use in source and binary forms, with or without 6955SN/A * modification, are permitted provided that the following conditions are 7955SN/A * met: redistributions of source code must retain the above copyright 8955SN/A * notice, this list of conditions and the following disclaimer; 9955SN/A * redistributions in binary form must reproduce the above copyright 10955SN/A * notice, this list of conditions and the following disclaimer in the 11955SN/A * documentation and/or other materials provided with the distribution; 12955SN/A * neither the name of the copyright holders nor the names of its 13955SN/A * contributors may be used to endorse or promote products derived from 14955SN/A * this software without specific prior written permission. 15955SN/A * 16955SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17955SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18955SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19955SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20955SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21955SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22955SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23955SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24955SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25955SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26955SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27955SN/A */ 282665Ssaidi@eecs.umich.edu 294762Snate@binkert.org#include "base/intmath.hh" 30955SN/A#include "debug/RubyCache.hh" 315522Snate@binkert.org#include "mem/ruby/slicc_interface/RubySlicc_Util.hh" 326143Snate@binkert.org#include "mem/ruby/system/DirectoryMemory.hh" 334762Snate@binkert.org#include "mem/ruby/system/System.hh" 345522Snate@binkert.org 35955SN/Ausing namespace std; 365522Snate@binkert.org 37955SN/Aint DirectoryMemory::m_num_directories = 0; 385522Snate@binkert.orgint DirectoryMemory::m_num_directories_bits = 0; 394202Sbinkertn@umich.eduuint64_t DirectoryMemory::m_total_size_bytes = 0; 405742Snate@binkert.orgint DirectoryMemory::m_numa_high_bit = 0; 41955SN/A 424381Sbinkertn@umich.eduDirectoryMemory::DirectoryMemory(const Params *p) 434381Sbinkertn@umich.edu : SimObject(p) 44955SN/A{ 45955SN/A m_version = p->version; 46955SN/A m_size_bytes = p->size; 474202Sbinkertn@umich.edu m_size_bits = floorLog2(m_size_bytes); 48955SN/A m_num_entries = 0; 494382Sbinkertn@umich.edu m_use_map = p->use_map; 504382Sbinkertn@umich.edu m_map_levels = p->map_levels; 514382Sbinkertn@umich.edu m_numa_high_bit = p->numa_high_bit; 526654Snate@binkert.org} 535517Snate@binkert.org 547674Snate@binkert.orgvoid 557674Snate@binkert.orgDirectoryMemory::init() 566143Snate@binkert.org{ 576143Snate@binkert.org m_num_entries = m_size_bytes / RubySystem::getBlockSizeBytes(); 586143Snate@binkert.org 596143Snate@binkert.org if (m_use_map) { 606143Snate@binkert.org m_sparseMemory = new SparseMemory(m_map_levels); 616143Snate@binkert.org g_system_ptr->registerSparseMemory(m_sparseMemory); 626143Snate@binkert.org } else { 636143Snate@binkert.org m_entries = new AbstractEntry*[m_num_entries]; 646143Snate@binkert.org for (int i = 0; i < m_num_entries; i++) 656143Snate@binkert.org m_entries[i] = NULL; 666143Snate@binkert.org m_ram = g_system_ptr->getMemoryVector(); 676143Snate@binkert.org } 686143Snate@binkert.org 696143Snate@binkert.org m_num_directories++; 706143Snate@binkert.org m_num_directories_bits = floorLog2(m_num_directories); 714762Snate@binkert.org m_total_size_bytes += m_size_bytes; 726143Snate@binkert.org 736143Snate@binkert.org if (m_numa_high_bit == 0) { 746143Snate@binkert.org m_numa_high_bit = RubySystem::getMemorySizeBits() - 1; 756143Snate@binkert.org } 766143Snate@binkert.org assert(m_numa_high_bit != 0); 776143Snate@binkert.org} 786143Snate@binkert.org 796143Snate@binkert.orgDirectoryMemory::~DirectoryMemory() 806143Snate@binkert.org{ 816143Snate@binkert.org // free up all the directory entries 826143Snate@binkert.org if (m_entries != NULL) { 836143Snate@binkert.org for (uint64 i = 0; i < m_num_entries; i++) { 846143Snate@binkert.org if (m_entries[i] != NULL) { 856143Snate@binkert.org delete m_entries[i]; 866143Snate@binkert.org } 876143Snate@binkert.org } 886143Snate@binkert.org delete [] m_entries; 896143Snate@binkert.org } else if (m_use_map) { 906143Snate@binkert.org delete m_sparseMemory; 916143Snate@binkert.org } 926143Snate@binkert.org} 937065Snate@binkert.org 946143Snate@binkert.orgvoid 956143Snate@binkert.orgDirectoryMemory::printConfig(ostream& out) const 966143Snate@binkert.org{ 976143Snate@binkert.org out << "DirectoryMemory module config: " << m_name << endl 986143Snate@binkert.org << " version: " << m_version << endl 996143Snate@binkert.org << " memory_bits: " << m_size_bits << endl 1006143Snate@binkert.org << " memory_size_bytes: " << m_size_bytes << endl 1016143Snate@binkert.org << " memory_size_Kbytes: " << double(m_size_bytes) / (1<<10) << endl 1026143Snate@binkert.org << " memory_size_Mbytes: " << double(m_size_bytes) / (1<<20) << endl 1036143Snate@binkert.org << " memory_size_Gbytes: " << double(m_size_bytes) / (1<<30) << endl; 1046143Snate@binkert.org} 1056143Snate@binkert.org 1066143Snate@binkert.org// Static method 1076143Snate@binkert.orgvoid 1086143Snate@binkert.orgDirectoryMemory::printGlobalConfig(ostream & out) 1096143Snate@binkert.org{ 1106143Snate@binkert.org out << "DirectoryMemory Global Config: " << endl; 1116143Snate@binkert.org out << " number of directory memories: " << m_num_directories << endl; 1126143Snate@binkert.org if (m_num_directories > 1) { 1136143Snate@binkert.org out << " number of selection bits: " << m_num_directories_bits << endl 1146143Snate@binkert.org << " selection bits: " << m_numa_high_bit 1155522Snate@binkert.org << "-" << m_numa_high_bit-m_num_directories_bits 1166143Snate@binkert.org << endl; 1176143Snate@binkert.org } 1186143Snate@binkert.org out << " total memory size bytes: " << m_total_size_bytes << endl; 1196143Snate@binkert.org out << " total memory bits: " << floorLog2(m_total_size_bytes) << endl; 1206143Snate@binkert.org} 1216143Snate@binkert.org 1226143Snate@binkert.orguint64 1236143Snate@binkert.orgDirectoryMemory::mapAddressToDirectoryVersion(PhysAddress address) 1246143Snate@binkert.org{ 1256143Snate@binkert.org if (m_num_directories_bits == 0) 1265522Snate@binkert.org return 0; 1275522Snate@binkert.org 1285522Snate@binkert.org uint64 ret = address.bitSelect(m_numa_high_bit - m_num_directories_bits + 1, 1295522Snate@binkert.org m_numa_high_bit); 1305604Snate@binkert.org return ret; 1315604Snate@binkert.org} 1326143Snate@binkert.org 1336143Snate@binkert.orgbool 1344762Snate@binkert.orgDirectoryMemory::isPresent(PhysAddress address) 1354762Snate@binkert.org{ 1366143Snate@binkert.org bool ret = (mapAddressToDirectoryVersion(address) == m_version); 1376727Ssteve.reinhardt@amd.com return ret; 1386727Ssteve.reinhardt@amd.com} 1396727Ssteve.reinhardt@amd.com 1404762Snate@binkert.orguint64 1416143Snate@binkert.orgDirectoryMemory::mapAddressToLocalIdx(PhysAddress address) 1426143Snate@binkert.org{ 1436143Snate@binkert.org uint64 ret; 1446143Snate@binkert.org if (m_num_directories_bits > 0) { 1456727Ssteve.reinhardt@amd.com ret = address.bitRemove(m_numa_high_bit - m_num_directories_bits + 1, 1466143Snate@binkert.org m_numa_high_bit); 1477674Snate@binkert.org } else { 1487674Snate@binkert.org ret = address.getAddress(); 1495604Snate@binkert.org } 1506143Snate@binkert.org 1516143Snate@binkert.org return ret >> (RubySystem::getBlockSizeBits()); 1526143Snate@binkert.org} 1534762Snate@binkert.org 1546143Snate@binkert.orgAbstractEntry* 1554762Snate@binkert.orgDirectoryMemory::lookup(PhysAddress address) 1564762Snate@binkert.org{ 1574762Snate@binkert.org assert(isPresent(address)); 1586143Snate@binkert.org DPRINTF(RubyCache, "Looking up address: %s\n", address); 1596143Snate@binkert.org 1604762Snate@binkert.org if (m_use_map) { 1616143Snate@binkert.org return m_sparseMemory->lookup(address); 1626143Snate@binkert.org } else { 1636143Snate@binkert.org uint64_t idx = mapAddressToLocalIdx(address); 1646143Snate@binkert.org assert(idx < m_num_entries); 1654762Snate@binkert.org return m_entries[idx]; 1666143Snate@binkert.org } 1674762Snate@binkert.org} 1686143Snate@binkert.org 1694762Snate@binkert.orgAbstractEntry* 1706143Snate@binkert.orgDirectoryMemory::allocate(const PhysAddress& address, AbstractEntry* entry) 1716143Snate@binkert.org{ 1726143Snate@binkert.org assert(isPresent(address)); 1736143Snate@binkert.org uint64 idx; 1746143Snate@binkert.org DPRINTF(RubyCache, "Looking up address: %s\n", address); 1756143Snate@binkert.org 1766143Snate@binkert.org if (m_use_map) { 1776143Snate@binkert.org m_sparseMemory->add(address, entry); 1786143Snate@binkert.org entry->changePermission(AccessPermission_Read_Write); 1796143Snate@binkert.org } else { 1806143Snate@binkert.org idx = mapAddressToLocalIdx(address); 1816143Snate@binkert.org assert(idx < m_num_entries); 1826143Snate@binkert.org entry->getDataBlk().assign(m_ram->getBlockPtr(address)); 183955SN/A entry->changePermission(AccessPermission_Read_Only); 1845584Snate@binkert.org m_entries[idx] = entry; 1855584Snate@binkert.org } 1865584Snate@binkert.org 1875584Snate@binkert.org return entry; 1886143Snate@binkert.org} 1896143Snate@binkert.org 1906143Snate@binkert.orgvoid 1915584Snate@binkert.orgDirectoryMemory::invalidateBlock(PhysAddress address) 1924382Sbinkertn@umich.edu{ 1934202Sbinkertn@umich.edu if (m_use_map) { 1944382Sbinkertn@umich.edu assert(m_sparseMemory->exist(address)); 1954382Sbinkertn@umich.edu m_sparseMemory->remove(address); 1964382Sbinkertn@umich.edu } 1975584Snate@binkert.org#if 0 1984382Sbinkertn@umich.edu else { 1994382Sbinkertn@umich.edu assert(isPresent(address)); 2004382Sbinkertn@umich.edu 2015192Ssaidi@eecs.umich.edu Index index = address.memoryModuleIndex(); 2025192Ssaidi@eecs.umich.edu 2035799Snate@binkert.org if (index < 0 || index > m_size) { 2045799Snate@binkert.org ERROR_MSG("Directory Memory Assertion: " 2055799Snate@binkert.org "accessing memory out of range."); 2065192Ssaidi@eecs.umich.edu } 2075799Snate@binkert.org 2085192Ssaidi@eecs.umich.edu if (m_entries[index] != NULL){ 2095799Snate@binkert.org delete m_entries[index]; 2105799Snate@binkert.org m_entries[index] = NULL; 2115192Ssaidi@eecs.umich.edu } 2125192Ssaidi@eecs.umich.edu } 2135192Ssaidi@eecs.umich.edu#endif 2145799Snate@binkert.org} 2155192Ssaidi@eecs.umich.edu 2165192Ssaidi@eecs.umich.eduvoid 2175192Ssaidi@eecs.umich.eduDirectoryMemory::print(ostream& out) const 2185192Ssaidi@eecs.umich.edu{ 2195192Ssaidi@eecs.umich.edu} 2205192Ssaidi@eecs.umich.edu 2214382Sbinkertn@umich.eduvoid 2224382Sbinkertn@umich.eduDirectoryMemory::printStats(ostream& out) const 2234382Sbinkertn@umich.edu{ 2242667Sstever@eecs.umich.edu if (m_use_map) { 2252667Sstever@eecs.umich.edu m_sparseMemory->printStats(out); 2262667Sstever@eecs.umich.edu } 2272667Sstever@eecs.umich.edu} 2282667Sstever@eecs.umich.edu 2292667Sstever@eecs.umich.eduDirectoryMemory * 2305742Snate@binkert.orgRubyDirectoryMemoryParams::create() 2315742Snate@binkert.org{ 2325742Snate@binkert.org return new DirectoryMemory(this); 2335793Snate@binkert.org} 2345793Snate@binkert.org