MEM: Separate queries for snooping and address ranges
[gem5.git] / src / mem / cache / base.cc
1 /*
2 * Copyright (c) 2003-2005 The Regents of The University of Michigan
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 * Authors: Erik Hallnor
29 */
30
31 /**
32 * @file
33 * Definition of BaseCache functions.
34 */
35
36 #include "cpu/base.hh"
37 #include "cpu/smt.hh"
38 #include "debug/Cache.hh"
39 #include "mem/cache/base.hh"
40 #include "mem/cache/mshr.hh"
41
42 using namespace std;
43
44 BaseCache::CachePort::CachePort(const std::string &_name, BaseCache *_cache,
45 const std::string &_label)
46 : SimpleTimingPort(_name, _cache), cache(_cache),
47 label(_label), otherPort(NULL),
48 blocked(false), mustSendRetry(false)
49 {
50 }
51
52
53 BaseCache::BaseCache(const Params *p)
54 : MemObject(p),
55 mshrQueue("MSHRs", p->mshrs, 4, MSHRQueue_MSHRs),
56 writeBuffer("write buffer", p->write_buffers, p->mshrs+1000,
57 MSHRQueue_WriteBuffer),
58 blkSize(p->block_size),
59 hitLatency(p->latency),
60 numTarget(p->tgts_per_mshr),
61 forwardSnoops(p->forward_snoops),
62 isTopLevel(p->is_top_level),
63 blocked(0),
64 noTargetMSHR(NULL),
65 missCount(p->max_miss_count),
66 drainEvent(NULL),
67 addrRange(p->addr_range),
68 _numCpus(p->num_cpus)
69 {
70 }
71
72 void
73 BaseCache::CachePort::recvRangeChange() const
74 {
75 otherPort->sendRangeChange();
76 }
77
78
79 bool
80 BaseCache::CachePort::checkFunctional(PacketPtr pkt)
81 {
82 pkt->pushLabel(label);
83 bool done = SimpleTimingPort::checkFunctional(pkt);
84 pkt->popLabel();
85 return done;
86 }
87
88
89 unsigned
90 BaseCache::CachePort::deviceBlockSize() const
91 {
92 return cache->getBlockSize();
93 }
94
95
96 bool
97 BaseCache::CachePort::recvRetryCommon()
98 {
99 assert(waitingOnRetry);
100 waitingOnRetry = false;
101 return false;
102 }
103
104
105 void
106 BaseCache::CachePort::setBlocked()
107 {
108 assert(!blocked);
109 DPRINTF(Cache, "Cache Blocking\n");
110 blocked = true;
111 //Clear the retry flag
112 mustSendRetry = false;
113 }
114
115 void
116 BaseCache::CachePort::clearBlocked()
117 {
118 assert(blocked);
119 DPRINTF(Cache, "Cache Unblocking\n");
120 blocked = false;
121 if (mustSendRetry)
122 {
123 DPRINTF(Cache, "Cache Sending Retry\n");
124 mustSendRetry = false;
125 SendRetryEvent *ev = new SendRetryEvent(this, true);
126 // @TODO: need to find a better time (next bus cycle?)
127 cache->schedule(ev, curTick() + 1);
128 }
129 }
130
131
132 void
133 BaseCache::init()
134 {
135 if (!cpuSidePort || !memSidePort)
136 panic("Cache not hooked up on both sides\n");
137 cpuSidePort->sendRangeChange();
138 }
139
140
141 void
142 BaseCache::regStats()
143 {
144 using namespace Stats;
145
146 // Hit statistics
147 for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
148 MemCmd cmd(access_idx);
149 const string &cstr = cmd.toString();
150
151 hits[access_idx]
152 #if FULL_SYSTEM
153 .init(_numCpus + 1)
154 #else
155 .init(_numCpus)
156 #endif
157 .name(name() + "." + cstr + "_hits")
158 .desc("number of " + cstr + " hits")
159 .flags(total | nozero | nonan)
160 ;
161 }
162
163 // These macros make it easier to sum the right subset of commands and
164 // to change the subset of commands that are considered "demand" vs
165 // "non-demand"
166 #define SUM_DEMAND(s) \
167 (s[MemCmd::ReadReq] + s[MemCmd::WriteReq] + s[MemCmd::ReadExReq])
168
169 // should writebacks be included here? prior code was inconsistent...
170 #define SUM_NON_DEMAND(s) \
171 (s[MemCmd::SoftPFReq] + s[MemCmd::HardPFReq])
172
173 demandHits
174 .name(name() + ".demand_hits")
175 .desc("number of demand (read+write) hits")
176 .flags(total)
177 ;
178 demandHits = SUM_DEMAND(hits);
179
180 overallHits
181 .name(name() + ".overall_hits")
182 .desc("number of overall hits")
183 .flags(total)
184 ;
185 overallHits = demandHits + SUM_NON_DEMAND(hits);
186
187 // Miss statistics
188 for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
189 MemCmd cmd(access_idx);
190 const string &cstr = cmd.toString();
191
192 misses[access_idx]
193 #if FULL_SYSTEM
194 .init(_numCpus + 1)
195 #else
196 .init(_numCpus)
197 #endif
198 .name(name() + "." + cstr + "_misses")
199 .desc("number of " + cstr + " misses")
200 .flags(total | nozero | nonan)
201 ;
202 }
203
204 demandMisses
205 .name(name() + ".demand_misses")
206 .desc("number of demand (read+write) misses")
207 .flags(total)
208 ;
209 demandMisses = SUM_DEMAND(misses);
210
211 overallMisses
212 .name(name() + ".overall_misses")
213 .desc("number of overall misses")
214 .flags(total)
215 ;
216 overallMisses = demandMisses + SUM_NON_DEMAND(misses);
217
218 // Miss latency statistics
219 for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
220 MemCmd cmd(access_idx);
221 const string &cstr = cmd.toString();
222
223 missLatency[access_idx]
224 .init(maxThreadsPerCPU)
225 .name(name() + "." + cstr + "_miss_latency")
226 .desc("number of " + cstr + " miss cycles")
227 .flags(total | nozero | nonan)
228 ;
229 }
230
231 demandMissLatency
232 .name(name() + ".demand_miss_latency")
233 .desc("number of demand (read+write) miss cycles")
234 .flags(total)
235 ;
236 demandMissLatency = SUM_DEMAND(missLatency);
237
238 overallMissLatency
239 .name(name() + ".overall_miss_latency")
240 .desc("number of overall miss cycles")
241 .flags(total)
242 ;
243 overallMissLatency = demandMissLatency + SUM_NON_DEMAND(missLatency);
244
245 // access formulas
246 for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
247 MemCmd cmd(access_idx);
248 const string &cstr = cmd.toString();
249
250 accesses[access_idx]
251 .name(name() + "." + cstr + "_accesses")
252 .desc("number of " + cstr + " accesses(hits+misses)")
253 .flags(total | nozero | nonan)
254 ;
255
256 accesses[access_idx] = hits[access_idx] + misses[access_idx];
257 }
258
259 demandAccesses
260 .name(name() + ".demand_accesses")
261 .desc("number of demand (read+write) accesses")
262 .flags(total)
263 ;
264 demandAccesses = demandHits + demandMisses;
265
266 overallAccesses
267 .name(name() + ".overall_accesses")
268 .desc("number of overall (read+write) accesses")
269 .flags(total)
270 ;
271 overallAccesses = overallHits + overallMisses;
272
273 // miss rate formulas
274 for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
275 MemCmd cmd(access_idx);
276 const string &cstr = cmd.toString();
277
278 missRate[access_idx]
279 .name(name() + "." + cstr + "_miss_rate")
280 .desc("miss rate for " + cstr + " accesses")
281 .flags(total | nozero | nonan)
282 ;
283
284 missRate[access_idx] = misses[access_idx] / accesses[access_idx];
285 }
286
287 demandMissRate
288 .name(name() + ".demand_miss_rate")
289 .desc("miss rate for demand accesses")
290 .flags(total)
291 ;
292 demandMissRate = demandMisses / demandAccesses;
293
294 overallMissRate
295 .name(name() + ".overall_miss_rate")
296 .desc("miss rate for overall accesses")
297 .flags(total)
298 ;
299 overallMissRate = overallMisses / overallAccesses;
300
301 // miss latency formulas
302 for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
303 MemCmd cmd(access_idx);
304 const string &cstr = cmd.toString();
305
306 avgMissLatency[access_idx]
307 .name(name() + "." + cstr + "_avg_miss_latency")
308 .desc("average " + cstr + " miss latency")
309 .flags(total | nozero | nonan)
310 ;
311
312 avgMissLatency[access_idx] =
313 missLatency[access_idx] / misses[access_idx];
314 }
315
316 demandAvgMissLatency
317 .name(name() + ".demand_avg_miss_latency")
318 .desc("average overall miss latency")
319 .flags(total)
320 ;
321 demandAvgMissLatency = demandMissLatency / demandMisses;
322
323 overallAvgMissLatency
324 .name(name() + ".overall_avg_miss_latency")
325 .desc("average overall miss latency")
326 .flags(total)
327 ;
328 overallAvgMissLatency = overallMissLatency / overallMisses;
329
330 blocked_cycles.init(NUM_BLOCKED_CAUSES);
331 blocked_cycles
332 .name(name() + ".blocked_cycles")
333 .desc("number of cycles access was blocked")
334 .subname(Blocked_NoMSHRs, "no_mshrs")
335 .subname(Blocked_NoTargets, "no_targets")
336 ;
337
338
339 blocked_causes.init(NUM_BLOCKED_CAUSES);
340 blocked_causes
341 .name(name() + ".blocked")
342 .desc("number of cycles access was blocked")
343 .subname(Blocked_NoMSHRs, "no_mshrs")
344 .subname(Blocked_NoTargets, "no_targets")
345 ;
346
347 avg_blocked
348 .name(name() + ".avg_blocked_cycles")
349 .desc("average number of cycles each access was blocked")
350 .subname(Blocked_NoMSHRs, "no_mshrs")
351 .subname(Blocked_NoTargets, "no_targets")
352 ;
353
354 avg_blocked = blocked_cycles / blocked_causes;
355
356 fastWrites
357 .name(name() + ".fast_writes")
358 .desc("number of fast writes performed")
359 ;
360
361 cacheCopies
362 .name(name() + ".cache_copies")
363 .desc("number of cache copies performed")
364 ;
365
366 writebacks
367 .init(maxThreadsPerCPU)
368 .name(name() + ".writebacks")
369 .desc("number of writebacks")
370 .flags(total)
371 ;
372
373 // MSHR statistics
374 // MSHR hit statistics
375 for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
376 MemCmd cmd(access_idx);
377 const string &cstr = cmd.toString();
378
379 mshr_hits[access_idx]
380 .init(maxThreadsPerCPU)
381 .name(name() + "." + cstr + "_mshr_hits")
382 .desc("number of " + cstr + " MSHR hits")
383 .flags(total | nozero | nonan)
384 ;
385 }
386
387 demandMshrHits
388 .name(name() + ".demand_mshr_hits")
389 .desc("number of demand (read+write) MSHR hits")
390 .flags(total)
391 ;
392 demandMshrHits = SUM_DEMAND(mshr_hits);
393
394 overallMshrHits
395 .name(name() + ".overall_mshr_hits")
396 .desc("number of overall MSHR hits")
397 .flags(total)
398 ;
399 overallMshrHits = demandMshrHits + SUM_NON_DEMAND(mshr_hits);
400
401 // MSHR miss statistics
402 for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
403 MemCmd cmd(access_idx);
404 const string &cstr = cmd.toString();
405
406 mshr_misses[access_idx]
407 .init(maxThreadsPerCPU)
408 .name(name() + "." + cstr + "_mshr_misses")
409 .desc("number of " + cstr + " MSHR misses")
410 .flags(total | nozero | nonan)
411 ;
412 }
413
414 demandMshrMisses
415 .name(name() + ".demand_mshr_misses")
416 .desc("number of demand (read+write) MSHR misses")
417 .flags(total)
418 ;
419 demandMshrMisses = SUM_DEMAND(mshr_misses);
420
421 overallMshrMisses
422 .name(name() + ".overall_mshr_misses")
423 .desc("number of overall MSHR misses")
424 .flags(total)
425 ;
426 overallMshrMisses = demandMshrMisses + SUM_NON_DEMAND(mshr_misses);
427
428 // MSHR miss latency statistics
429 for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
430 MemCmd cmd(access_idx);
431 const string &cstr = cmd.toString();
432
433 mshr_miss_latency[access_idx]
434 .init(maxThreadsPerCPU)
435 .name(name() + "." + cstr + "_mshr_miss_latency")
436 .desc("number of " + cstr + " MSHR miss cycles")
437 .flags(total | nozero | nonan)
438 ;
439 }
440
441 demandMshrMissLatency
442 .name(name() + ".demand_mshr_miss_latency")
443 .desc("number of demand (read+write) MSHR miss cycles")
444 .flags(total)
445 ;
446 demandMshrMissLatency = SUM_DEMAND(mshr_miss_latency);
447
448 overallMshrMissLatency
449 .name(name() + ".overall_mshr_miss_latency")
450 .desc("number of overall MSHR miss cycles")
451 .flags(total)
452 ;
453 overallMshrMissLatency =
454 demandMshrMissLatency + SUM_NON_DEMAND(mshr_miss_latency);
455
456 // MSHR uncacheable statistics
457 for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
458 MemCmd cmd(access_idx);
459 const string &cstr = cmd.toString();
460
461 mshr_uncacheable[access_idx]
462 .init(maxThreadsPerCPU)
463 .name(name() + "." + cstr + "_mshr_uncacheable")
464 .desc("number of " + cstr + " MSHR uncacheable")
465 .flags(total | nozero | nonan)
466 ;
467 }
468
469 overallMshrUncacheable
470 .name(name() + ".overall_mshr_uncacheable_misses")
471 .desc("number of overall MSHR uncacheable misses")
472 .flags(total)
473 ;
474 overallMshrUncacheable =
475 SUM_DEMAND(mshr_uncacheable) + SUM_NON_DEMAND(mshr_uncacheable);
476
477 // MSHR miss latency statistics
478 for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
479 MemCmd cmd(access_idx);
480 const string &cstr = cmd.toString();
481
482 mshr_uncacheable_lat[access_idx]
483 .init(maxThreadsPerCPU)
484 .name(name() + "." + cstr + "_mshr_uncacheable_latency")
485 .desc("number of " + cstr + " MSHR uncacheable cycles")
486 .flags(total | nozero | nonan)
487 ;
488 }
489
490 overallMshrUncacheableLatency
491 .name(name() + ".overall_mshr_uncacheable_latency")
492 .desc("number of overall MSHR uncacheable cycles")
493 .flags(total)
494 ;
495 overallMshrUncacheableLatency =
496 SUM_DEMAND(mshr_uncacheable_lat) +
497 SUM_NON_DEMAND(mshr_uncacheable_lat);
498
499 #if 0
500 // MSHR access formulas
501 for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
502 MemCmd cmd(access_idx);
503 const string &cstr = cmd.toString();
504
505 mshrAccesses[access_idx]
506 .name(name() + "." + cstr + "_mshr_accesses")
507 .desc("number of " + cstr + " mshr accesses(hits+misses)")
508 .flags(total | nozero | nonan)
509 ;
510 mshrAccesses[access_idx] =
511 mshr_hits[access_idx] + mshr_misses[access_idx]
512 + mshr_uncacheable[access_idx];
513 }
514
515 demandMshrAccesses
516 .name(name() + ".demand_mshr_accesses")
517 .desc("number of demand (read+write) mshr accesses")
518 .flags(total | nozero | nonan)
519 ;
520 demandMshrAccesses = demandMshrHits + demandMshrMisses;
521
522 overallMshrAccesses
523 .name(name() + ".overall_mshr_accesses")
524 .desc("number of overall (read+write) mshr accesses")
525 .flags(total | nozero | nonan)
526 ;
527 overallMshrAccesses = overallMshrHits + overallMshrMisses
528 + overallMshrUncacheable;
529 #endif
530
531 // MSHR miss rate formulas
532 for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
533 MemCmd cmd(access_idx);
534 const string &cstr = cmd.toString();
535
536 mshrMissRate[access_idx]
537 .name(name() + "." + cstr + "_mshr_miss_rate")
538 .desc("mshr miss rate for " + cstr + " accesses")
539 .flags(total | nozero | nonan)
540 ;
541
542 mshrMissRate[access_idx] =
543 mshr_misses[access_idx] / accesses[access_idx];
544 }
545
546 demandMshrMissRate
547 .name(name() + ".demand_mshr_miss_rate")
548 .desc("mshr miss rate for demand accesses")
549 .flags(total)
550 ;
551 demandMshrMissRate = demandMshrMisses / demandAccesses;
552
553 overallMshrMissRate
554 .name(name() + ".overall_mshr_miss_rate")
555 .desc("mshr miss rate for overall accesses")
556 .flags(total)
557 ;
558 overallMshrMissRate = overallMshrMisses / overallAccesses;
559
560 // mshrMiss latency formulas
561 for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
562 MemCmd cmd(access_idx);
563 const string &cstr = cmd.toString();
564
565 avgMshrMissLatency[access_idx]
566 .name(name() + "." + cstr + "_avg_mshr_miss_latency")
567 .desc("average " + cstr + " mshr miss latency")
568 .flags(total | nozero | nonan)
569 ;
570
571 avgMshrMissLatency[access_idx] =
572 mshr_miss_latency[access_idx] / mshr_misses[access_idx];
573 }
574
575 demandAvgMshrMissLatency
576 .name(name() + ".demand_avg_mshr_miss_latency")
577 .desc("average overall mshr miss latency")
578 .flags(total)
579 ;
580 demandAvgMshrMissLatency = demandMshrMissLatency / demandMshrMisses;
581
582 overallAvgMshrMissLatency
583 .name(name() + ".overall_avg_mshr_miss_latency")
584 .desc("average overall mshr miss latency")
585 .flags(total)
586 ;
587 overallAvgMshrMissLatency = overallMshrMissLatency / overallMshrMisses;
588
589 // mshrUncacheable latency formulas
590 for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
591 MemCmd cmd(access_idx);
592 const string &cstr = cmd.toString();
593
594 avgMshrUncacheableLatency[access_idx]
595 .name(name() + "." + cstr + "_avg_mshr_uncacheable_latency")
596 .desc("average " + cstr + " mshr uncacheable latency")
597 .flags(total | nozero | nonan)
598 ;
599
600 avgMshrUncacheableLatency[access_idx] =
601 mshr_uncacheable_lat[access_idx] / mshr_uncacheable[access_idx];
602 }
603
604 overallAvgMshrUncacheableLatency
605 .name(name() + ".overall_avg_mshr_uncacheable_latency")
606 .desc("average overall mshr uncacheable latency")
607 .flags(total)
608 ;
609 overallAvgMshrUncacheableLatency = overallMshrUncacheableLatency / overallMshrUncacheable;
610
611 mshr_cap_events
612 .init(maxThreadsPerCPU)
613 .name(name() + ".mshr_cap_events")
614 .desc("number of times MSHR cap was activated")
615 .flags(total)
616 ;
617
618 //software prefetching stats
619 soft_prefetch_mshr_full
620 .init(maxThreadsPerCPU)
621 .name(name() + ".soft_prefetch_mshr_full")
622 .desc("number of mshr full events for SW prefetching instrutions")
623 .flags(total)
624 ;
625
626 mshr_no_allocate_misses
627 .name(name() +".no_allocate_misses")
628 .desc("Number of misses that were no-allocate")
629 ;
630
631 }
632
633 unsigned int
634 BaseCache::drain(Event *de)
635 {
636 int count = memSidePort->drain(de) + cpuSidePort->drain(de);
637
638 // Set status
639 if (count != 0) {
640 drainEvent = de;
641
642 changeState(SimObject::Draining);
643 return count;
644 }
645
646 changeState(SimObject::Drained);
647 return 0;
648 }