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