2 * Copyright (c) 2003-2005 The Regents of The University of Michigan
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.
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.
28 * Authors: Erik Hallnor
33 * Definition of BaseCache functions.
36 #include "cpu/base.hh"
38 #include "debug/Cache.hh"
39 #include "mem/cache/base.hh"
40 #include "mem/cache/mshr.hh"
44 BaseCache::CachePort::CachePort(const std::string
&_name
, BaseCache
*_cache
,
45 const std::string
&_label
)
46 : SimpleTimingPort(_name
, _cache
), cache(_cache
),
47 label(_label
), blocked(false), mustSendRetry(false)
52 BaseCache::BaseCache(const Params
*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
),
64 missCount(p
->max_miss_count
),
66 addrRange(p
->addr_range
),
73 BaseCache::CachePort::checkFunctional(PacketPtr pkt
)
75 pkt
->pushLabel(label
);
76 bool done
= SimpleTimingPort::checkFunctional(pkt
);
83 BaseCache::CachePort::deviceBlockSize() const
85 return cache
->getBlockSize();
90 BaseCache::CachePort::recvRetryCommon()
92 assert(waitingOnRetry
);
93 waitingOnRetry
= false;
99 BaseCache::CachePort::setBlocked()
102 DPRINTF(Cache
, "Cache Blocking\n");
104 //Clear the retry flag
105 mustSendRetry
= false;
109 BaseCache::CachePort::clearBlocked()
112 DPRINTF(Cache
, "Cache Unblocking\n");
116 DPRINTF(Cache
, "Cache Sending Retry\n");
117 mustSendRetry
= false;
118 SendRetryEvent
*ev
= new SendRetryEvent(this, true);
119 // @TODO: need to find a better time (next bus cycle?)
120 cache
->schedule(ev
, curTick() + 1);
128 if (!cpuSidePort
|| !memSidePort
)
129 panic("Cache not hooked up on both sides\n");
130 cpuSidePort
->sendRangeChange();
135 BaseCache::regStats()
137 using namespace Stats
;
140 for (int access_idx
= 0; access_idx
< MemCmd::NUM_MEM_CMDS
; ++access_idx
) {
141 MemCmd
cmd(access_idx
);
142 const string
&cstr
= cmd
.toString();
150 .name(name() + "." + cstr
+ "_hits")
151 .desc("number of " + cstr
+ " hits")
152 .flags(total
| nozero
| nonan
)
156 // These macros make it easier to sum the right subset of commands and
157 // to change the subset of commands that are considered "demand" vs
159 #define SUM_DEMAND(s) \
160 (s[MemCmd::ReadReq] + s[MemCmd::WriteReq] + s[MemCmd::ReadExReq])
162 // should writebacks be included here? prior code was inconsistent...
163 #define SUM_NON_DEMAND(s) \
164 (s[MemCmd::SoftPFReq] + s[MemCmd::HardPFReq])
167 .name(name() + ".demand_hits")
168 .desc("number of demand (read+write) hits")
171 demandHits
= SUM_DEMAND(hits
);
174 .name(name() + ".overall_hits")
175 .desc("number of overall hits")
178 overallHits
= demandHits
+ SUM_NON_DEMAND(hits
);
181 for (int access_idx
= 0; access_idx
< MemCmd::NUM_MEM_CMDS
; ++access_idx
) {
182 MemCmd
cmd(access_idx
);
183 const string
&cstr
= cmd
.toString();
191 .name(name() + "." + cstr
+ "_misses")
192 .desc("number of " + cstr
+ " misses")
193 .flags(total
| nozero
| nonan
)
198 .name(name() + ".demand_misses")
199 .desc("number of demand (read+write) misses")
202 demandMisses
= SUM_DEMAND(misses
);
205 .name(name() + ".overall_misses")
206 .desc("number of overall misses")
209 overallMisses
= demandMisses
+ SUM_NON_DEMAND(misses
);
211 // Miss latency statistics
212 for (int access_idx
= 0; access_idx
< MemCmd::NUM_MEM_CMDS
; ++access_idx
) {
213 MemCmd
cmd(access_idx
);
214 const string
&cstr
= cmd
.toString();
216 missLatency
[access_idx
]
217 .init(maxThreadsPerCPU
)
218 .name(name() + "." + cstr
+ "_miss_latency")
219 .desc("number of " + cstr
+ " miss cycles")
220 .flags(total
| nozero
| nonan
)
225 .name(name() + ".demand_miss_latency")
226 .desc("number of demand (read+write) miss cycles")
229 demandMissLatency
= SUM_DEMAND(missLatency
);
232 .name(name() + ".overall_miss_latency")
233 .desc("number of overall miss cycles")
236 overallMissLatency
= demandMissLatency
+ SUM_NON_DEMAND(missLatency
);
239 for (int access_idx
= 0; access_idx
< MemCmd::NUM_MEM_CMDS
; ++access_idx
) {
240 MemCmd
cmd(access_idx
);
241 const string
&cstr
= cmd
.toString();
244 .name(name() + "." + cstr
+ "_accesses")
245 .desc("number of " + cstr
+ " accesses(hits+misses)")
246 .flags(total
| nozero
| nonan
)
249 accesses
[access_idx
] = hits
[access_idx
] + misses
[access_idx
];
253 .name(name() + ".demand_accesses")
254 .desc("number of demand (read+write) accesses")
257 demandAccesses
= demandHits
+ demandMisses
;
260 .name(name() + ".overall_accesses")
261 .desc("number of overall (read+write) accesses")
264 overallAccesses
= overallHits
+ overallMisses
;
266 // miss rate formulas
267 for (int access_idx
= 0; access_idx
< MemCmd::NUM_MEM_CMDS
; ++access_idx
) {
268 MemCmd
cmd(access_idx
);
269 const string
&cstr
= cmd
.toString();
272 .name(name() + "." + cstr
+ "_miss_rate")
273 .desc("miss rate for " + cstr
+ " accesses")
274 .flags(total
| nozero
| nonan
)
277 missRate
[access_idx
] = misses
[access_idx
] / accesses
[access_idx
];
281 .name(name() + ".demand_miss_rate")
282 .desc("miss rate for demand accesses")
285 demandMissRate
= demandMisses
/ demandAccesses
;
288 .name(name() + ".overall_miss_rate")
289 .desc("miss rate for overall accesses")
292 overallMissRate
= overallMisses
/ overallAccesses
;
294 // miss latency formulas
295 for (int access_idx
= 0; access_idx
< MemCmd::NUM_MEM_CMDS
; ++access_idx
) {
296 MemCmd
cmd(access_idx
);
297 const string
&cstr
= cmd
.toString();
299 avgMissLatency
[access_idx
]
300 .name(name() + "." + cstr
+ "_avg_miss_latency")
301 .desc("average " + cstr
+ " miss latency")
302 .flags(total
| nozero
| nonan
)
305 avgMissLatency
[access_idx
] =
306 missLatency
[access_idx
] / misses
[access_idx
];
310 .name(name() + ".demand_avg_miss_latency")
311 .desc("average overall miss latency")
314 demandAvgMissLatency
= demandMissLatency
/ demandMisses
;
316 overallAvgMissLatency
317 .name(name() + ".overall_avg_miss_latency")
318 .desc("average overall miss latency")
321 overallAvgMissLatency
= overallMissLatency
/ overallMisses
;
323 blocked_cycles
.init(NUM_BLOCKED_CAUSES
);
325 .name(name() + ".blocked_cycles")
326 .desc("number of cycles access was blocked")
327 .subname(Blocked_NoMSHRs
, "no_mshrs")
328 .subname(Blocked_NoTargets
, "no_targets")
332 blocked_causes
.init(NUM_BLOCKED_CAUSES
);
334 .name(name() + ".blocked")
335 .desc("number of cycles access was blocked")
336 .subname(Blocked_NoMSHRs
, "no_mshrs")
337 .subname(Blocked_NoTargets
, "no_targets")
341 .name(name() + ".avg_blocked_cycles")
342 .desc("average number of cycles each access was blocked")
343 .subname(Blocked_NoMSHRs
, "no_mshrs")
344 .subname(Blocked_NoTargets
, "no_targets")
347 avg_blocked
= blocked_cycles
/ blocked_causes
;
350 .name(name() + ".fast_writes")
351 .desc("number of fast writes performed")
355 .name(name() + ".cache_copies")
356 .desc("number of cache copies performed")
360 .init(maxThreadsPerCPU
)
361 .name(name() + ".writebacks")
362 .desc("number of writebacks")
367 // MSHR hit statistics
368 for (int access_idx
= 0; access_idx
< MemCmd::NUM_MEM_CMDS
; ++access_idx
) {
369 MemCmd
cmd(access_idx
);
370 const string
&cstr
= cmd
.toString();
372 mshr_hits
[access_idx
]
373 .init(maxThreadsPerCPU
)
374 .name(name() + "." + cstr
+ "_mshr_hits")
375 .desc("number of " + cstr
+ " MSHR hits")
376 .flags(total
| nozero
| nonan
)
381 .name(name() + ".demand_mshr_hits")
382 .desc("number of demand (read+write) MSHR hits")
385 demandMshrHits
= SUM_DEMAND(mshr_hits
);
388 .name(name() + ".overall_mshr_hits")
389 .desc("number of overall MSHR hits")
392 overallMshrHits
= demandMshrHits
+ SUM_NON_DEMAND(mshr_hits
);
394 // MSHR miss statistics
395 for (int access_idx
= 0; access_idx
< MemCmd::NUM_MEM_CMDS
; ++access_idx
) {
396 MemCmd
cmd(access_idx
);
397 const string
&cstr
= cmd
.toString();
399 mshr_misses
[access_idx
]
400 .init(maxThreadsPerCPU
)
401 .name(name() + "." + cstr
+ "_mshr_misses")
402 .desc("number of " + cstr
+ " MSHR misses")
403 .flags(total
| nozero
| nonan
)
408 .name(name() + ".demand_mshr_misses")
409 .desc("number of demand (read+write) MSHR misses")
412 demandMshrMisses
= SUM_DEMAND(mshr_misses
);
415 .name(name() + ".overall_mshr_misses")
416 .desc("number of overall MSHR misses")
419 overallMshrMisses
= demandMshrMisses
+ SUM_NON_DEMAND(mshr_misses
);
421 // MSHR miss latency statistics
422 for (int access_idx
= 0; access_idx
< MemCmd::NUM_MEM_CMDS
; ++access_idx
) {
423 MemCmd
cmd(access_idx
);
424 const string
&cstr
= cmd
.toString();
426 mshr_miss_latency
[access_idx
]
427 .init(maxThreadsPerCPU
)
428 .name(name() + "." + cstr
+ "_mshr_miss_latency")
429 .desc("number of " + cstr
+ " MSHR miss cycles")
430 .flags(total
| nozero
| nonan
)
434 demandMshrMissLatency
435 .name(name() + ".demand_mshr_miss_latency")
436 .desc("number of demand (read+write) MSHR miss cycles")
439 demandMshrMissLatency
= SUM_DEMAND(mshr_miss_latency
);
441 overallMshrMissLatency
442 .name(name() + ".overall_mshr_miss_latency")
443 .desc("number of overall MSHR miss cycles")
446 overallMshrMissLatency
=
447 demandMshrMissLatency
+ SUM_NON_DEMAND(mshr_miss_latency
);
449 // MSHR uncacheable statistics
450 for (int access_idx
= 0; access_idx
< MemCmd::NUM_MEM_CMDS
; ++access_idx
) {
451 MemCmd
cmd(access_idx
);
452 const string
&cstr
= cmd
.toString();
454 mshr_uncacheable
[access_idx
]
455 .init(maxThreadsPerCPU
)
456 .name(name() + "." + cstr
+ "_mshr_uncacheable")
457 .desc("number of " + cstr
+ " MSHR uncacheable")
458 .flags(total
| nozero
| nonan
)
462 overallMshrUncacheable
463 .name(name() + ".overall_mshr_uncacheable_misses")
464 .desc("number of overall MSHR uncacheable misses")
467 overallMshrUncacheable
=
468 SUM_DEMAND(mshr_uncacheable
) + SUM_NON_DEMAND(mshr_uncacheable
);
470 // MSHR miss latency statistics
471 for (int access_idx
= 0; access_idx
< MemCmd::NUM_MEM_CMDS
; ++access_idx
) {
472 MemCmd
cmd(access_idx
);
473 const string
&cstr
= cmd
.toString();
475 mshr_uncacheable_lat
[access_idx
]
476 .init(maxThreadsPerCPU
)
477 .name(name() + "." + cstr
+ "_mshr_uncacheable_latency")
478 .desc("number of " + cstr
+ " MSHR uncacheable cycles")
479 .flags(total
| nozero
| nonan
)
483 overallMshrUncacheableLatency
484 .name(name() + ".overall_mshr_uncacheable_latency")
485 .desc("number of overall MSHR uncacheable cycles")
488 overallMshrUncacheableLatency
=
489 SUM_DEMAND(mshr_uncacheable_lat
) +
490 SUM_NON_DEMAND(mshr_uncacheable_lat
);
493 // MSHR access formulas
494 for (int access_idx
= 0; access_idx
< MemCmd::NUM_MEM_CMDS
; ++access_idx
) {
495 MemCmd
cmd(access_idx
);
496 const string
&cstr
= cmd
.toString();
498 mshrAccesses
[access_idx
]
499 .name(name() + "." + cstr
+ "_mshr_accesses")
500 .desc("number of " + cstr
+ " mshr accesses(hits+misses)")
501 .flags(total
| nozero
| nonan
)
503 mshrAccesses
[access_idx
] =
504 mshr_hits
[access_idx
] + mshr_misses
[access_idx
]
505 + mshr_uncacheable
[access_idx
];
509 .name(name() + ".demand_mshr_accesses")
510 .desc("number of demand (read+write) mshr accesses")
511 .flags(total
| nozero
| nonan
)
513 demandMshrAccesses
= demandMshrHits
+ demandMshrMisses
;
516 .name(name() + ".overall_mshr_accesses")
517 .desc("number of overall (read+write) mshr accesses")
518 .flags(total
| nozero
| nonan
)
520 overallMshrAccesses
= overallMshrHits
+ overallMshrMisses
521 + overallMshrUncacheable
;
524 // MSHR miss rate formulas
525 for (int access_idx
= 0; access_idx
< MemCmd::NUM_MEM_CMDS
; ++access_idx
) {
526 MemCmd
cmd(access_idx
);
527 const string
&cstr
= cmd
.toString();
529 mshrMissRate
[access_idx
]
530 .name(name() + "." + cstr
+ "_mshr_miss_rate")
531 .desc("mshr miss rate for " + cstr
+ " accesses")
532 .flags(total
| nozero
| nonan
)
535 mshrMissRate
[access_idx
] =
536 mshr_misses
[access_idx
] / accesses
[access_idx
];
540 .name(name() + ".demand_mshr_miss_rate")
541 .desc("mshr miss rate for demand accesses")
544 demandMshrMissRate
= demandMshrMisses
/ demandAccesses
;
547 .name(name() + ".overall_mshr_miss_rate")
548 .desc("mshr miss rate for overall accesses")
551 overallMshrMissRate
= overallMshrMisses
/ overallAccesses
;
553 // mshrMiss latency formulas
554 for (int access_idx
= 0; access_idx
< MemCmd::NUM_MEM_CMDS
; ++access_idx
) {
555 MemCmd
cmd(access_idx
);
556 const string
&cstr
= cmd
.toString();
558 avgMshrMissLatency
[access_idx
]
559 .name(name() + "." + cstr
+ "_avg_mshr_miss_latency")
560 .desc("average " + cstr
+ " mshr miss latency")
561 .flags(total
| nozero
| nonan
)
564 avgMshrMissLatency
[access_idx
] =
565 mshr_miss_latency
[access_idx
] / mshr_misses
[access_idx
];
568 demandAvgMshrMissLatency
569 .name(name() + ".demand_avg_mshr_miss_latency")
570 .desc("average overall mshr miss latency")
573 demandAvgMshrMissLatency
= demandMshrMissLatency
/ demandMshrMisses
;
575 overallAvgMshrMissLatency
576 .name(name() + ".overall_avg_mshr_miss_latency")
577 .desc("average overall mshr miss latency")
580 overallAvgMshrMissLatency
= overallMshrMissLatency
/ overallMshrMisses
;
582 // mshrUncacheable latency formulas
583 for (int access_idx
= 0; access_idx
< MemCmd::NUM_MEM_CMDS
; ++access_idx
) {
584 MemCmd
cmd(access_idx
);
585 const string
&cstr
= cmd
.toString();
587 avgMshrUncacheableLatency
[access_idx
]
588 .name(name() + "." + cstr
+ "_avg_mshr_uncacheable_latency")
589 .desc("average " + cstr
+ " mshr uncacheable latency")
590 .flags(total
| nozero
| nonan
)
593 avgMshrUncacheableLatency
[access_idx
] =
594 mshr_uncacheable_lat
[access_idx
] / mshr_uncacheable
[access_idx
];
597 overallAvgMshrUncacheableLatency
598 .name(name() + ".overall_avg_mshr_uncacheable_latency")
599 .desc("average overall mshr uncacheable latency")
602 overallAvgMshrUncacheableLatency
= overallMshrUncacheableLatency
/ overallMshrUncacheable
;
605 .init(maxThreadsPerCPU
)
606 .name(name() + ".mshr_cap_events")
607 .desc("number of times MSHR cap was activated")
611 //software prefetching stats
612 soft_prefetch_mshr_full
613 .init(maxThreadsPerCPU
)
614 .name(name() + ".soft_prefetch_mshr_full")
615 .desc("number of mshr full events for SW prefetching instrutions")
619 mshr_no_allocate_misses
620 .name(name() +".no_allocate_misses")
621 .desc("Number of misses that were no-allocate")
627 BaseCache::drain(Event
*de
)
629 int count
= memSidePort
->drain(de
) + cpuSidePort
->drain(de
);
635 changeState(SimObject::Draining
);
639 changeState(SimObject::Drained
);