ruby: Added flag to disable mem_vec allocation
[gem5.git] / src / mem / ruby / system / DirectoryMemory.cc
1
2 /*
3 * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are
8 * met: redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer;
10 * redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution;
13 * neither the name of the copyright holders nor the names of its
14 * contributors may be used to endorse or promote products derived from
15 * this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29
30 /*
31 * DirectoryMemory.cc
32 *
33 * Description: See DirectoryMemory.hh
34 *
35 * $Id$
36 *
37 */
38
39 #include "mem/ruby/system/System.hh"
40 #include "mem/ruby/system/DirectoryMemory.hh"
41 #include "mem/ruby/slicc_interface/RubySlicc_Util.hh"
42 #include "mem/gems_common/util.hh"
43
44 int DirectoryMemory::m_num_directories = 0;
45 int DirectoryMemory::m_num_directories_bits = 0;
46 uint64_t DirectoryMemory::m_total_size_bytes = 0;
47
48 DirectoryMemory::DirectoryMemory(const Params *p)
49 : SimObject(p)
50 {
51 m_version = p->version;
52 m_size_bytes = p->size;
53 m_size_bits = log_int(m_size_bytes);
54 m_num_entries = 0;
55 m_use_map = p->use_map;
56 m_map_levels = p->map_levels;
57 }
58
59 void DirectoryMemory::init()
60 {
61 m_num_entries = m_size_bytes / RubySystem::getBlockSizeBytes();
62
63 if (m_use_map) {
64 int entry_bits = log_int(m_num_entries);
65 assert(entry_bits >= m_map_levels);
66 m_sparseMemory = new SparseMemory(entry_bits, m_map_levels);
67 } else {
68 m_entries = new Directory_Entry*[m_num_entries];
69 for (int i=0; i < m_num_entries; i++)
70 m_entries[i] = NULL;
71 m_ram = g_system_ptr->getMemoryVector();
72 }
73
74 m_num_directories++;
75 m_num_directories_bits = log_int(m_num_directories);
76 m_total_size_bytes += m_size_bytes;
77 }
78
79 DirectoryMemory::~DirectoryMemory()
80 {
81 // free up all the directory entries
82 if (m_entries != NULL) {
83 for (uint64 i = 0; i < m_num_entries; i++) {
84 if (m_entries[i] != NULL) {
85 delete m_entries[i];
86 }
87 }
88 delete [] m_entries;
89 } else if (m_use_map) {
90 delete m_sparseMemory;
91 }
92 }
93
94 void DirectoryMemory::printConfig(ostream& out) const
95 {
96 out << "DirectoryMemory module config: " << m_name << endl;
97 out << " version: " << m_version << endl;
98 out << " memory_bits: " << m_size_bits << endl;
99 out << " memory_size_bytes: " << m_size_bytes << endl;
100 out << " memory_size_Kbytes: " << double(m_size_bytes) / (1<<10) << endl;
101 out << " memory_size_Mbytes: " << double(m_size_bytes) / (1<<20) << endl;
102 out << " memory_size_Gbytes: " << double(m_size_bytes) / (1<<30) << endl;
103 }
104
105 // Static method
106 void DirectoryMemory::printGlobalConfig(ostream & out)
107 {
108 out << "DirectoryMemory Global Config: " << endl;
109 out << " number of directory memories: " << m_num_directories << endl;
110 if (m_num_directories > 1) {
111 out << " number of selection bits: " << m_num_directories_bits << endl;
112 out << " selection bits: " << RubySystem::getBlockSizeBits()+m_num_directories_bits-1
113 << "-" << RubySystem::getBlockSizeBits() << endl;
114 }
115 out << " total memory size bytes: " << m_total_size_bytes << endl;
116 out << " total memory bits: " << log_int(m_total_size_bytes) << endl;
117
118 }
119
120 uint64 DirectoryMemory::mapAddressToDirectoryVersion(PhysAddress address)
121 {
122 if (m_num_directories_bits == 0) return 0;
123 uint64 ret = address.bitSelect(RubySystem::getBlockSizeBits(),
124 RubySystem::getBlockSizeBits()+m_num_directories_bits-1);
125 return ret;
126 }
127
128 // Public method
129 bool DirectoryMemory::isPresent(PhysAddress address)
130 {
131 bool ret = (mapAddressToDirectoryVersion(address) == m_version);
132 return ret;
133 }
134
135 uint64 DirectoryMemory::mapAddressToLocalIdx(PhysAddress address)
136 {
137 uint64 ret = address.getAddress()
138 >> (RubySystem::getBlockSizeBits() + m_num_directories_bits);
139 return ret;
140 }
141
142 Directory_Entry& DirectoryMemory::lookup(PhysAddress address)
143 {
144 assert(isPresent(address));
145 Directory_Entry* entry;
146 uint64 idx;
147 DEBUG_EXPR(CACHE_COMP, HighPrio, address);
148
149 if (m_use_map) {
150 if (m_sparseMemory->exist(address)) {
151 entry = m_sparseMemory->lookup(address);
152 assert(entry != NULL);
153 } else {
154 //
155 // Note: SparseMemory internally creates a new Directory Entry
156 //
157 m_sparseMemory->add(address);
158 entry = m_sparseMemory->lookup(address);
159 }
160 } else {
161 idx = mapAddressToLocalIdx(address);
162 assert(idx < m_num_entries);
163 entry = m_entries[idx];
164
165 if (entry == NULL) {
166 entry = new Directory_Entry();
167 entry->getDataBlk().assign(m_ram->getBlockPtr(address));
168 m_entries[idx] = entry;
169 }
170 }
171
172 return (*entry);
173 }
174 /*
175 Directory_Entry& DirectoryMemory::lookup(PhysAddress address)
176 {
177 assert(isPresent(address));
178 Index index = address.memoryModuleIndex();
179
180 if (index < 0 || index > m_size) {
181 WARN_EXPR(address.getAddress());
182 WARN_EXPR(index);
183 WARN_EXPR(m_size);
184 ERROR_MSG("Directory Memory Assertion: accessing memory out of range.");
185 }
186 Directory_Entry* entry = m_entries[index];
187
188 // allocate the directory entry on demand.
189 if (entry == NULL) {
190 entry = new Directory_Entry;
191 entry->getDataBlk().assign(m_ram->getBlockPtr(address));
192
193 // store entry to the table
194 m_entries[index] = entry;
195 }
196
197 return (*entry);
198 }
199 */
200
201 void DirectoryMemory::invalidateBlock(PhysAddress address)
202 {
203
204 if (m_use_map) {
205 assert(m_sparseMemory->exist(address));
206 m_sparseMemory->remove(address);
207 }
208 /*
209 else {
210 assert(isPresent(address));
211
212 Index index = address.memoryModuleIndex();
213
214 if (index < 0 || index > m_size) {
215 ERROR_MSG("Directory Memory Assertion: accessing memory out of range.");
216 }
217
218 if(m_entries[index] != NULL){
219 delete m_entries[index];
220 m_entries[index] = NULL;
221 }
222 }
223 */
224
225
226 }
227
228 void DirectoryMemory::print(ostream& out) const
229 {
230
231 }
232
233 void DirectoryMemory::printStats(ostream& out) const
234 {
235 if (m_use_map) {
236 m_sparseMemory->printStats(out);
237 }
238 }
239
240 DirectoryMemory *
241 RubyDirectoryMemoryParams::create()
242 {
243 return new DirectoryMemory(this);
244 }