1/* 2 * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are 7 * met: redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer; 9 * redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution; 12 * neither the name of the copyright holders nor the names of its 13 * contributors may be used to endorse or promote products derived from 14 * this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29#include "base/intmath.hh" 30#include "debug/RubyCache.hh" 31#include "debug/RubyStats.hh" 32#include "mem/ruby/slicc_interface/RubySlicc_Util.hh" 33#include "mem/ruby/structures/DirectoryMemory.hh" 34#include "mem/ruby/system/System.hh" 35 36using namespace std; 37 38int DirectoryMemory::m_num_directories = 0; 39int DirectoryMemory::m_num_directories_bits = 0; 40uint64_t DirectoryMemory::m_total_size_bytes = 0; 41int DirectoryMemory::m_numa_high_bit = 0; 42 43DirectoryMemory::DirectoryMemory(const Params *p) 44 : SimObject(p) 45{ 46 m_version = p->version; 47 m_size_bytes = p->size; 48 m_size_bits = floorLog2(m_size_bytes); 49 m_num_entries = 0;
|
50 m_use_map = p->use_map;
51 m_map_levels = p->map_levels;
|
50 m_numa_high_bit = p->numa_high_bit; 51} 52 53void 54DirectoryMemory::init() 55{ 56 m_num_entries = m_size_bytes / RubySystem::getBlockSizeBytes();
|
57 m_entries = new AbstractEntry*[m_num_entries]; 58 for (int i = 0; i < m_num_entries; i++) 59 m_entries[i] = NULL; 60 m_ram = g_system_ptr->getMemoryVector(); |
61
|
60 if (m_use_map) {
61 m_sparseMemory = new SparseMemory(m_map_levels);
62 g_system_ptr->registerSparseMemory(m_sparseMemory);
63 } else {
64 m_entries = new AbstractEntry*[m_num_entries];
65 for (int i = 0; i < m_num_entries; i++)
66 m_entries[i] = NULL;
67 m_ram = g_system_ptr->getMemoryVector();
68 }
69
|
62 m_num_directories++; 63 m_num_directories_bits = ceilLog2(m_num_directories); 64 m_total_size_bytes += m_size_bytes; 65 66 if (m_numa_high_bit == 0) { 67 m_numa_high_bit = RubySystem::getMemorySizeBits() - 1; 68 } 69 assert(m_numa_high_bit != 0); 70} 71 72DirectoryMemory::~DirectoryMemory() 73{ 74 // free up all the directory entries
|
83 if (m_entries != NULL) {
84 for (uint64 i = 0; i < m_num_entries; i++) {
85 if (m_entries[i] != NULL) {
86 delete m_entries[i];
87 }
|
75 for (uint64 i = 0; i < m_num_entries; i++) { 76 if (m_entries[i] != NULL) { 77 delete m_entries[i]; |
78 }
|
89 delete [] m_entries;
90 } else if (m_use_map) {
91 delete m_sparseMemory;
|
79 }
|
80 delete [] m_entries; |
81} 82 83uint64 84DirectoryMemory::mapAddressToDirectoryVersion(PhysAddress address) 85{ 86 if (m_num_directories_bits == 0) 87 return 0; 88 89 uint64 ret = address.bitSelect(m_numa_high_bit - m_num_directories_bits + 1, 90 m_numa_high_bit); 91 return ret; 92} 93 94bool 95DirectoryMemory::isPresent(PhysAddress address) 96{ 97 bool ret = (mapAddressToDirectoryVersion(address) == m_version); 98 return ret; 99} 100 101uint64 102DirectoryMemory::mapAddressToLocalIdx(PhysAddress address) 103{ 104 uint64 ret; 105 if (m_num_directories_bits > 0) { 106 ret = address.bitRemove(m_numa_high_bit - m_num_directories_bits + 1, 107 m_numa_high_bit); 108 } else { 109 ret = address.getAddress(); 110 } 111 112 return ret >> (RubySystem::getBlockSizeBits()); 113} 114 115AbstractEntry* 116DirectoryMemory::lookup(PhysAddress address) 117{ 118 assert(isPresent(address)); 119 DPRINTF(RubyCache, "Looking up address: %s\n", address); 120
|
133 if (m_use_map) {
134 return m_sparseMemory->lookup(address);
135 } else {
136 uint64_t idx = mapAddressToLocalIdx(address);
137 assert(idx < m_num_entries);
138 return m_entries[idx];
139 }
|
121 uint64_t idx = mapAddressToLocalIdx(address); 122 assert(idx < m_num_entries); 123 return m_entries[idx]; |
124} 125 126AbstractEntry* 127DirectoryMemory::allocate(const PhysAddress& address, AbstractEntry* entry) 128{ 129 assert(isPresent(address)); 130 uint64 idx; 131 DPRINTF(RubyCache, "Looking up address: %s\n", address); 132
|
149 if (m_use_map) {
150 m_sparseMemory->add(address, entry);
151 entry->changePermission(AccessPermission_Read_Write);
152 } else {
153 idx = mapAddressToLocalIdx(address);
154 assert(idx < m_num_entries);
155 entry->getDataBlk().assign(m_ram->getBlockPtr(address));
156 entry->changePermission(AccessPermission_Read_Only);
157 m_entries[idx] = entry;
158 }
|
133 idx = mapAddressToLocalIdx(address); 134 assert(idx < m_num_entries); 135 entry->getDataBlk().assign(m_ram->getBlockPtr(address)); 136 entry->changePermission(AccessPermission_Read_Only); 137 m_entries[idx] = entry; |
138 139 return entry; 140} 141 142void
|
164DirectoryMemory::invalidateBlock(PhysAddress address)
165{
166 if (m_use_map) {
167 assert(m_sparseMemory->exist(address));
168 m_sparseMemory->remove(address);
169 }
170#if 0
171 else {
172 assert(isPresent(address));
173
174 int64 index = address.memoryModuleIndex();
175
176 if (index < 0 || index > m_size) {
177 ERROR_MSG("Directory Memory Assertion: "
178 "accessing memory out of range.");
179 }
180
181 if (m_entries[index] != NULL){
182 delete m_entries[index];
183 m_entries[index] = NULL;
184 }
185 }
186#endif
187}
188
189void
|
143DirectoryMemory::print(ostream& out) const 144{ 145} 146 147void
|
195DirectoryMemory::regStats()
196{
197 if (m_use_map) {
198 m_sparseMemory->regStats(name());
199 }
200}
201
202void
|
148DirectoryMemory::recordRequestType(DirectoryRequestType requestType) { 149 DPRINTF(RubyStats, "Recorded statistic: %s\n", 150 DirectoryRequestType_to_string(requestType)); 151} 152 153DirectoryMemory * 154RubyDirectoryMemoryParams::create() 155{ 156 return new DirectoryMemory(this); 157}
|