CacheMemory.cc (11034:a89984ca7d15) CacheMemory.cc (11049:dfb0aa3f0649)
1/*
2 * Copyright (c) 1999-2012 Mark D. Hill and David A. Wood
3 * Copyright (c) 2013 Advanced Micro Devices, Inc.
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

--- 84 unchanged lines hidden (view full) ---

93 for (int i = 0; i < m_cache_num_sets; i++) {
94 for (int j = 0; j < m_cache_assoc; j++) {
95 delete m_cache[i][j];
96 }
97 }
98}
99
100// convert a Address to its location in the cache
1/*
2 * Copyright (c) 1999-2012 Mark D. Hill and David A. Wood
3 * Copyright (c) 2013 Advanced Micro Devices, Inc.
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

--- 84 unchanged lines hidden (view full) ---

93 for (int i = 0; i < m_cache_num_sets; i++) {
94 for (int j = 0; j < m_cache_assoc; j++) {
95 delete m_cache[i][j];
96 }
97 }
98}
99
100// convert a Address to its location in the cache
101int64_t
101int64
102CacheMemory::addressToCacheSet(Addr address) const
103{
104 assert(address == makeLineAddress(address));
105 return bitSelect(address, m_start_index_bit,
106 m_start_index_bit + m_cache_num_set_bits - 1);
107}
108
109// Given a cache index: returns the index of the tag in a set.
110// returns -1 if the tag is not found.
111int
102CacheMemory::addressToCacheSet(Addr address) const
103{
104 assert(address == makeLineAddress(address));
105 return bitSelect(address, m_start_index_bit,
106 m_start_index_bit + m_cache_num_set_bits - 1);
107}
108
109// Given a cache index: returns the index of the tag in a set.
110// returns -1 if the tag is not found.
111int
112CacheMemory::findTagInSet(int64_t cacheSet, Addr tag) const
112CacheMemory::findTagInSet(int64 cacheSet, Addr tag) const
113{
114 assert(tag == makeLineAddress(tag));
115 // search the set for the tags
116 m5::hash_map<Addr, int>::const_iterator it = m_tag_index.find(tag);
117 if (it != m_tag_index.end())
118 if (m_cache[cacheSet][it->second]->m_Permission !=
119 AccessPermission_NotPresent)
120 return it->second;
121 return -1; // Not found
122}
123
124// Given a cache index: returns the index of the tag in a set.
125// returns -1 if the tag is not found.
126int
113{
114 assert(tag == makeLineAddress(tag));
115 // search the set for the tags
116 m5::hash_map<Addr, int>::const_iterator it = m_tag_index.find(tag);
117 if (it != m_tag_index.end())
118 if (m_cache[cacheSet][it->second]->m_Permission !=
119 AccessPermission_NotPresent)
120 return it->second;
121 return -1; // Not found
122}
123
124// Given a cache index: returns the index of the tag in a set.
125// returns -1 if the tag is not found.
126int
127CacheMemory::findTagInSetIgnorePermissions(int64_t cacheSet,
127CacheMemory::findTagInSetIgnorePermissions(int64 cacheSet,
128 Addr tag) const
129{
130 assert(tag == makeLineAddress(tag));
131 // search the set for the tags
132 m5::hash_map<Addr, int>::const_iterator it = m_tag_index.find(tag);
133 if (it != m_tag_index.end())
134 return it->second;
135 return -1; // Not found

--- 17 unchanged lines hidden (view full) ---

153 if (entry == NULL ||
154 entry->m_Permission == AccessPermission_Invalid ||
155 entry->m_Permission == AccessPermission_NotPresent) {
156 return tmp;
157 }
158 return entry->m_Address;
159}
160
128 Addr tag) const
129{
130 assert(tag == makeLineAddress(tag));
131 // search the set for the tags
132 m5::hash_map<Addr, int>::const_iterator it = m_tag_index.find(tag);
133 if (it != m_tag_index.end())
134 return it->second;
135 return -1; // Not found

--- 17 unchanged lines hidden (view full) ---

153 if (entry == NULL ||
154 entry->m_Permission == AccessPermission_Invalid ||
155 entry->m_Permission == AccessPermission_NotPresent) {
156 return tmp;
157 }
158 return entry->m_Address;
159}
160
161bool
162CacheMemory::tryCacheAccess(Addr address, RubyRequestType type,
163 DataBlock*& data_ptr)
164{
165 assert(address == makeLineAddress(address));
166 DPRINTF(RubyCache, "address: %s\n", address);
167 int64 cacheSet = addressToCacheSet(address);
168 int loc = findTagInSet(cacheSet, address);
169 if (loc != -1) {
170 // Do we even have a tag match?
171 AbstractCacheEntry* entry = m_cache[cacheSet][loc];
172 m_replacementPolicy_ptr->touch(cacheSet, loc, curTick());
173 data_ptr = &(entry->getDataBlk());
174
175 if (entry->m_Permission == AccessPermission_Read_Write) {
176 return true;
177 }
178 if ((entry->m_Permission == AccessPermission_Read_Only) &&
179 (type == RubyRequestType_LD || type == RubyRequestType_IFETCH)) {
180 return true;
181 }
182 // The line must not be accessible
183 }
184 data_ptr = NULL;
185 return false;
186}
187
188bool
189CacheMemory::testCacheAccess(Addr address, RubyRequestType type,
190 DataBlock*& data_ptr)
191{
192 assert(address == makeLineAddress(address));
193 DPRINTF(RubyCache, "address: %s\n", address);
194 int64 cacheSet = addressToCacheSet(address);
195 int loc = findTagInSet(cacheSet, address);
196
197 if (loc != -1) {
198 // Do we even have a tag match?
199 AbstractCacheEntry* entry = m_cache[cacheSet][loc];
200 m_replacementPolicy_ptr->touch(cacheSet, loc, curTick());
201 data_ptr = &(entry->getDataBlk());
202
203 return m_cache[cacheSet][loc]->m_Permission !=
204 AccessPermission_NotPresent;
205 }
206
207 data_ptr = NULL;
208 return false;
209}
210
161// tests to see if an address is present in the cache
162bool
163CacheMemory::isTagPresent(Addr address) const
164{
165 assert(address == makeLineAddress(address));
211// tests to see if an address is present in the cache
212bool
213CacheMemory::isTagPresent(Addr address) const
214{
215 assert(address == makeLineAddress(address));
166 int64_t cacheSet = addressToCacheSet(address);
216 int64 cacheSet = addressToCacheSet(address);
167 int loc = findTagInSet(cacheSet, address);
168
169 if (loc == -1) {
170 // We didn't find the tag
171 DPRINTF(RubyCache, "No tag match for address: %s\n", address);
172 return false;
173 }
174 DPRINTF(RubyCache, "address: %s found\n", address);
175 return true;
176}
177
178// Returns true if there is:
179// a) a tag match on this address or there is
180// b) an unused line in the same cache "way"
181bool
182CacheMemory::cacheAvail(Addr address) const
183{
184 assert(address == makeLineAddress(address));
185
217 int loc = findTagInSet(cacheSet, address);
218
219 if (loc == -1) {
220 // We didn't find the tag
221 DPRINTF(RubyCache, "No tag match for address: %s\n", address);
222 return false;
223 }
224 DPRINTF(RubyCache, "address: %s found\n", address);
225 return true;
226}
227
228// Returns true if there is:
229// a) a tag match on this address or there is
230// b) an unused line in the same cache "way"
231bool
232CacheMemory::cacheAvail(Addr address) const
233{
234 assert(address == makeLineAddress(address));
235
186 int64_t cacheSet = addressToCacheSet(address);
236 int64 cacheSet = addressToCacheSet(address);
187
188 for (int i = 0; i < m_cache_assoc; i++) {
189 AbstractCacheEntry* entry = m_cache[cacheSet][i];
190 if (entry != NULL) {
191 if (entry->m_Address == address ||
192 entry->m_Permission == AccessPermission_NotPresent) {
193 // Already in the cache or we found an empty entry
194 return true;
195 }
196 } else {
197 return true;
198 }
199 }
200 return false;
201}
202
203AbstractCacheEntry*
237
238 for (int i = 0; i < m_cache_assoc; i++) {
239 AbstractCacheEntry* entry = m_cache[cacheSet][i];
240 if (entry != NULL) {
241 if (entry->m_Address == address ||
242 entry->m_Permission == AccessPermission_NotPresent) {
243 // Already in the cache or we found an empty entry
244 return true;
245 }
246 } else {
247 return true;
248 }
249 }
250 return false;
251}
252
253AbstractCacheEntry*
204CacheMemory::allocate(Addr address, AbstractCacheEntry *entry, bool touch)
254CacheMemory::allocate(Addr address, AbstractCacheEntry* entry, bool touch)
205{
206 assert(address == makeLineAddress(address));
207 assert(!isTagPresent(address));
208 assert(cacheAvail(address));
209 DPRINTF(RubyCache, "address: %s\n", address);
210
211 // Find the first open slot
255{
256 assert(address == makeLineAddress(address));
257 assert(!isTagPresent(address));
258 assert(cacheAvail(address));
259 DPRINTF(RubyCache, "address: %s\n", address);
260
261 // Find the first open slot
212 int64_t cacheSet = addressToCacheSet(address);
262 int64 cacheSet = addressToCacheSet(address);
213 std::vector<AbstractCacheEntry*> &set = m_cache[cacheSet];
214 for (int i = 0; i < m_cache_assoc; i++) {
215 if (!set[i] || set[i]->m_Permission == AccessPermission_NotPresent) {
216 set[i] = entry; // Init entry
217 set[i]->m_Address = address;
218 set[i]->m_Permission = AccessPermission_Invalid;
219 DPRINTF(RubyCache, "Allocate clearing lock for addr: %x\n",
220 address);
221 set[i]->m_locked = -1;
222 m_tag_index[address] = i;
263 std::vector<AbstractCacheEntry*> &set = m_cache[cacheSet];
264 for (int i = 0; i < m_cache_assoc; i++) {
265 if (!set[i] || set[i]->m_Permission == AccessPermission_NotPresent) {
266 set[i] = entry; // Init entry
267 set[i]->m_Address = address;
268 set[i]->m_Permission = AccessPermission_Invalid;
269 DPRINTF(RubyCache, "Allocate clearing lock for addr: %x\n",
270 address);
271 set[i]->m_locked = -1;
272 m_tag_index[address] = i;
223 entry->setSetIndex(cacheSet);
224 entry->setWayIndex(i);
225
226 if (touch) {
227 m_replacementPolicy_ptr->touch(cacheSet, i, curTick());
228 }
229
230 return entry;
231 }
232 }
233 panic("Allocate didn't find an available entry");
234}
235
236void
237CacheMemory::deallocate(Addr address)
238{
239 assert(address == makeLineAddress(address));
240 assert(isTagPresent(address));
241 DPRINTF(RubyCache, "address: %s\n", address);
273
274 if (touch) {
275 m_replacementPolicy_ptr->touch(cacheSet, i, curTick());
276 }
277
278 return entry;
279 }
280 }
281 panic("Allocate didn't find an available entry");
282}
283
284void
285CacheMemory::deallocate(Addr address)
286{
287 assert(address == makeLineAddress(address));
288 assert(isTagPresent(address));
289 DPRINTF(RubyCache, "address: %s\n", address);
242 int64_t cacheSet = addressToCacheSet(address);
290 int64 cacheSet = addressToCacheSet(address);
243 int loc = findTagInSet(cacheSet, address);
244 if (loc != -1) {
245 delete m_cache[cacheSet][loc];
246 m_cache[cacheSet][loc] = NULL;
247 m_tag_index.erase(address);
248 }
249}
250
251// Returns with the physical address of the conflicting cache line
252Addr
253CacheMemory::cacheProbe(Addr address) const
254{
255 assert(address == makeLineAddress(address));
256 assert(!cacheAvail(address));
257
291 int loc = findTagInSet(cacheSet, address);
292 if (loc != -1) {
293 delete m_cache[cacheSet][loc];
294 m_cache[cacheSet][loc] = NULL;
295 m_tag_index.erase(address);
296 }
297}
298
299// Returns with the physical address of the conflicting cache line
300Addr
301CacheMemory::cacheProbe(Addr address) const
302{
303 assert(address == makeLineAddress(address));
304 assert(!cacheAvail(address));
305
258 int64_t cacheSet = addressToCacheSet(address);
306 int64 cacheSet = addressToCacheSet(address);
259 return m_cache[cacheSet][m_replacementPolicy_ptr->getVictim(cacheSet)]->
260 m_Address;
261}
262
263// looks an address up in the cache
264AbstractCacheEntry*
265CacheMemory::lookup(Addr address)
266{
267 assert(address == makeLineAddress(address));
307 return m_cache[cacheSet][m_replacementPolicy_ptr->getVictim(cacheSet)]->
308 m_Address;
309}
310
311// looks an address up in the cache
312AbstractCacheEntry*
313CacheMemory::lookup(Addr address)
314{
315 assert(address == makeLineAddress(address));
268 int64_t cacheSet = addressToCacheSet(address);
316 int64 cacheSet = addressToCacheSet(address);
269 int loc = findTagInSet(cacheSet, address);
270 if(loc == -1) return NULL;
271 return m_cache[cacheSet][loc];
272}
273
274// looks an address up in the cache
275const AbstractCacheEntry*
276CacheMemory::lookup(Addr address) const
277{
278 assert(address == makeLineAddress(address));
317 int loc = findTagInSet(cacheSet, address);
318 if(loc == -1) return NULL;
319 return m_cache[cacheSet][loc];
320}
321
322// looks an address up in the cache
323const AbstractCacheEntry*
324CacheMemory::lookup(Addr address) const
325{
326 assert(address == makeLineAddress(address));
279 int64_t cacheSet = addressToCacheSet(address);
327 int64 cacheSet = addressToCacheSet(address);
280 int loc = findTagInSet(cacheSet, address);
281 if(loc == -1) return NULL;
282 return m_cache[cacheSet][loc];
283}
284
285// Sets the most recently used bit for a cache block
286void
287CacheMemory::setMRU(Addr address)
288{
328 int loc = findTagInSet(cacheSet, address);
329 if(loc == -1) return NULL;
330 return m_cache[cacheSet][loc];
331}
332
333// Sets the most recently used bit for a cache block
334void
335CacheMemory::setMRU(Addr address)
336{
289 int64_t cacheSet = addressToCacheSet(address);
337 int64 cacheSet = addressToCacheSet(address);
290 int loc = findTagInSet(cacheSet, address);
291
292 if(loc != -1)
293 m_replacementPolicy_ptr->touch(cacheSet, loc, curTick());
294}
295
296void
338 int loc = findTagInSet(cacheSet, address);
339
340 if(loc != -1)
341 m_replacementPolicy_ptr->touch(cacheSet, loc, curTick());
342}
343
344void
297CacheMemory::setMRU(const AbstractCacheEntry *e)
298{
299 uint32_t cacheSet = e->getSetIndex();
300 uint32_t loc = e->getWayIndex();
301 m_replacementPolicy_ptr->touch(cacheSet, loc, curTick());
302}
303
304void
305CacheMemory::recordCacheContents(int cntrl, CacheRecorder* tr) const
306{
345CacheMemory::recordCacheContents(int cntrl, CacheRecorder* tr) const
346{
307 uint64_t warmedUpBlocks = 0;
308 uint64_t totalBlocks M5_VAR_USED = (uint64_t)m_cache_num_sets *
309 (uint64_t)m_cache_assoc;
347 uint64 warmedUpBlocks = 0;
348 uint64 totalBlocks M5_VAR_USED = (uint64)m_cache_num_sets
349 * (uint64)m_cache_assoc;
310
311 for (int i = 0; i < m_cache_num_sets; i++) {
312 for (int j = 0; j < m_cache_assoc; j++) {
313 if (m_cache[i][j] != NULL) {
314 AccessPermission perm = m_cache[i][j]->m_Permission;
315 RubyRequestType request_type = RubyRequestType_NULL;
316 if (perm == AccessPermission_Read_Only) {
317 if (m_is_instruction_only_cache) {

--- 13 unchanged lines hidden (view full) ---

331 warmedUpBlocks++;
332 }
333 }
334 }
335 }
336
337 DPRINTF(RubyCacheTrace, "%s: %lli blocks of %lli total blocks"
338 "recorded %.2f%% \n", name().c_str(), warmedUpBlocks,
350
351 for (int i = 0; i < m_cache_num_sets; i++) {
352 for (int j = 0; j < m_cache_assoc; j++) {
353 if (m_cache[i][j] != NULL) {
354 AccessPermission perm = m_cache[i][j]->m_Permission;
355 RubyRequestType request_type = RubyRequestType_NULL;
356 if (perm == AccessPermission_Read_Only) {
357 if (m_is_instruction_only_cache) {

--- 13 unchanged lines hidden (view full) ---

371 warmedUpBlocks++;
372 }
373 }
374 }
375 }
376
377 DPRINTF(RubyCacheTrace, "%s: %lli blocks of %lli total blocks"
378 "recorded %.2f%% \n", name().c_str(), warmedUpBlocks,
339 totalBlocks, (float(warmedUpBlocks) / float(totalBlocks)) * 100.0);
379 (uint64)m_cache_num_sets * (uint64)m_cache_assoc,
380 (float(warmedUpBlocks)/float(totalBlocks))*100.0);
340}
341
342void
343CacheMemory::print(ostream& out) const
344{
345 out << "Cache dump: " << name() << endl;
346 for (int i = 0; i < m_cache_num_sets; i++) {
347 for (int j = 0; j < m_cache_assoc; j++) {

--- 16 unchanged lines hidden (view full) ---

364 out << "printData() not supported" << endl;
365}
366
367void
368CacheMemory::setLocked(Addr address, int context)
369{
370 DPRINTF(RubyCache, "Setting Lock for addr: %x to %d\n", address, context);
371 assert(address == makeLineAddress(address));
381}
382
383void
384CacheMemory::print(ostream& out) const
385{
386 out << "Cache dump: " << name() << endl;
387 for (int i = 0; i < m_cache_num_sets; i++) {
388 for (int j = 0; j < m_cache_assoc; j++) {

--- 16 unchanged lines hidden (view full) ---

405 out << "printData() not supported" << endl;
406}
407
408void
409CacheMemory::setLocked(Addr address, int context)
410{
411 DPRINTF(RubyCache, "Setting Lock for addr: %x to %d\n", address, context);
412 assert(address == makeLineAddress(address));
372 int64_t cacheSet = addressToCacheSet(address);
413 int64 cacheSet = addressToCacheSet(address);
373 int loc = findTagInSet(cacheSet, address);
374 assert(loc != -1);
414 int loc = findTagInSet(cacheSet, address);
415 assert(loc != -1);
375 m_cache[cacheSet][loc]->setLocked(context);
416 m_cache[cacheSet][loc]->m_locked = context;
376}
377
378void
379CacheMemory::clearLocked(Addr address)
380{
381 DPRINTF(RubyCache, "Clear Lock for addr: %x\n", address);
382 assert(address == makeLineAddress(address));
417}
418
419void
420CacheMemory::clearLocked(Addr address)
421{
422 DPRINTF(RubyCache, "Clear Lock for addr: %x\n", address);
423 assert(address == makeLineAddress(address));
383 int64_t cacheSet = addressToCacheSet(address);
424 int64 cacheSet = addressToCacheSet(address);
384 int loc = findTagInSet(cacheSet, address);
385 assert(loc != -1);
425 int loc = findTagInSet(cacheSet, address);
426 assert(loc != -1);
386 m_cache[cacheSet][loc]->clearLocked();
427 m_cache[cacheSet][loc]->m_locked = -1;
387}
388
389bool
390CacheMemory::isLocked(Addr address, int context)
391{
392 assert(address == makeLineAddress(address));
428}
429
430bool
431CacheMemory::isLocked(Addr address, int context)
432{
433 assert(address == makeLineAddress(address));
393 int64_t cacheSet = addressToCacheSet(address);
434 int64 cacheSet = addressToCacheSet(address);
394 int loc = findTagInSet(cacheSet, address);
395 assert(loc != -1);
396 DPRINTF(RubyCache, "Testing Lock for addr: %llx cur %d con %d\n",
397 address, m_cache[cacheSet][loc]->m_locked, context);
435 int loc = findTagInSet(cacheSet, address);
436 assert(loc != -1);
437 DPRINTF(RubyCache, "Testing Lock for addr: %llx cur %d con %d\n",
438 address, m_cache[cacheSet][loc]->m_locked, context);
398 return m_cache[cacheSet][loc]->isLocked(context);
439 return m_cache[cacheSet][loc]->m_locked == context;
399}
400
401void
402CacheMemory::regStats()
403{
404 m_demand_hits
405 .name(name() + ".demand_hits")
406 .desc("Number of cache demand hits")

--- 141 unchanged lines hidden (view full) ---

548 }
549 } else {
550 assert(false);
551 return true;
552 }
553}
554
555bool
440}
441
442void
443CacheMemory::regStats()
444{
445 m_demand_hits
446 .name(name() + ".demand_hits")
447 .desc("Number of cache demand hits")

--- 141 unchanged lines hidden (view full) ---

589 }
590 } else {
591 assert(false);
592 return true;
593 }
594}
595
596bool
556CacheMemory::isBlockInvalid(int64_t cache_set, int64_t loc)
597CacheMemory::isBlockInvalid(int64 cache_set, int64 loc)
557{
558 return (m_cache[cache_set][loc]->m_Permission == AccessPermission_Invalid);
559}
560
561bool
598{
599 return (m_cache[cache_set][loc]->m_Permission == AccessPermission_Invalid);
600}
601
602bool
562CacheMemory::isBlockNotBusy(int64_t cache_set, int64_t loc)
603CacheMemory::isBlockNotBusy(int64 cache_set, int64 loc)
563{
564 return (m_cache[cache_set][loc]->m_Permission != AccessPermission_Busy);
565}
604{
605 return (m_cache[cache_set][loc]->m_Permission != AccessPermission_Busy);
606}