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 "mem/cache/base_cache.hh"
39 #include "mem/cache/miss/mshr.hh"
43 BaseCache::CachePort::CachePort(const std::string
&_name
, BaseCache
*_cache
)
44 : SimpleTimingPort(_name
, _cache
), cache(_cache
), otherPort(NULL
),
45 blocked(false), mustSendRetry(false)
50 BaseCache::BaseCache(const std::string
&name
, Params
¶ms
)
52 mshrQueue(params
.numMSHRs
, 4, MSHRQueue_MSHRs
),
53 writeBuffer(params
.numWriteBuffers
, params
.numMSHRs
+1000,
54 MSHRQueue_WriteBuffer
),
55 blkSize(params
.blkSize
),
56 hitLatency(params
.hitLatency
),
57 numTarget(params
.numTargets
),
60 missCount(params
.maxMisses
),
67 BaseCache::CachePort::recvStatusChange(Port::Status status
)
69 if (status
== Port::RangeChange
) {
70 otherPort
->sendStatusChange(Port::RangeChange
);
75 BaseCache::CachePort::deviceBlockSize()
77 return cache
->getBlockSize();
82 BaseCache::CachePort::checkAndSendFunctional(PacketPtr pkt
)
85 if (!pkt
->isResponse())
91 BaseCache::CachePort::recvRetryCommon()
93 assert(waitingOnRetry
);
94 waitingOnRetry
= false;
100 BaseCache::CachePort::setBlocked()
103 DPRINTF(Cache
, "Cache Blocking\n");
105 //Clear the retry flag
106 mustSendRetry
= false;
110 BaseCache::CachePort::clearBlocked()
113 DPRINTF(Cache
, "Cache Unblocking\n");
117 DPRINTF(Cache
, "Cache Sending Retry\n");
118 mustSendRetry
= false;
119 SendRetryEvent
*ev
= new SendRetryEvent(this, true);
120 // @TODO: need to find a better time (next bus cycle?)
121 ev
->schedule(curTick
+ 1);
129 if (!cpuSidePort
|| !memSidePort
)
130 panic("Cache not hooked up on both sides\n");
131 cpuSidePort
->sendStatusChange(Port::RangeChange
);
136 BaseCache::regStats()
138 using namespace Stats
;
141 for (int access_idx
= 0; access_idx
< MemCmd::NUM_MEM_CMDS
; ++access_idx
) {
142 MemCmd
cmd(access_idx
);
143 const string
&cstr
= cmd
.toString();
146 .init(maxThreadsPerCPU
)
147 .name(name() + "." + cstr
+ "_hits")
148 .desc("number of " + cstr
+ " hits")
149 .flags(total
| nozero
| nonan
)
153 // These macros make it easier to sum the right subset of commands and
154 // to change the subset of commands that are considered "demand" vs
156 #define SUM_DEMAND(s) \
157 (s[MemCmd::ReadReq] + s[MemCmd::WriteReq] + s[MemCmd::ReadExReq])
159 // should writebacks be included here? prior code was inconsistent...
160 #define SUM_NON_DEMAND(s) \
161 (s[MemCmd::SoftPFReq] + s[MemCmd::HardPFReq])
164 .name(name() + ".demand_hits")
165 .desc("number of demand (read+write) hits")
168 demandHits
= SUM_DEMAND(hits
);
171 .name(name() + ".overall_hits")
172 .desc("number of overall hits")
175 overallHits
= demandHits
+ SUM_NON_DEMAND(hits
);
178 for (int access_idx
= 0; access_idx
< MemCmd::NUM_MEM_CMDS
; ++access_idx
) {
179 MemCmd
cmd(access_idx
);
180 const string
&cstr
= cmd
.toString();
183 .init(maxThreadsPerCPU
)
184 .name(name() + "." + cstr
+ "_misses")
185 .desc("number of " + cstr
+ " misses")
186 .flags(total
| nozero
| nonan
)
191 .name(name() + ".demand_misses")
192 .desc("number of demand (read+write) misses")
195 demandMisses
= SUM_DEMAND(misses
);
198 .name(name() + ".overall_misses")
199 .desc("number of overall misses")
202 overallMisses
= demandMisses
+ SUM_NON_DEMAND(misses
);
204 // Miss latency statistics
205 for (int access_idx
= 0; access_idx
< MemCmd::NUM_MEM_CMDS
; ++access_idx
) {
206 MemCmd
cmd(access_idx
);
207 const string
&cstr
= cmd
.toString();
209 missLatency
[access_idx
]
210 .init(maxThreadsPerCPU
)
211 .name(name() + "." + cstr
+ "_miss_latency")
212 .desc("number of " + cstr
+ " miss cycles")
213 .flags(total
| nozero
| nonan
)
218 .name(name() + ".demand_miss_latency")
219 .desc("number of demand (read+write) miss cycles")
222 demandMissLatency
= SUM_DEMAND(missLatency
);
225 .name(name() + ".overall_miss_latency")
226 .desc("number of overall miss cycles")
229 overallMissLatency
= demandMissLatency
+ SUM_NON_DEMAND(missLatency
);
232 for (int access_idx
= 0; access_idx
< MemCmd::NUM_MEM_CMDS
; ++access_idx
) {
233 MemCmd
cmd(access_idx
);
234 const string
&cstr
= cmd
.toString();
237 .name(name() + "." + cstr
+ "_accesses")
238 .desc("number of " + cstr
+ " accesses(hits+misses)")
239 .flags(total
| nozero
| nonan
)
242 accesses
[access_idx
] = hits
[access_idx
] + misses
[access_idx
];
246 .name(name() + ".demand_accesses")
247 .desc("number of demand (read+write) accesses")
250 demandAccesses
= demandHits
+ demandMisses
;
253 .name(name() + ".overall_accesses")
254 .desc("number of overall (read+write) accesses")
257 overallAccesses
= overallHits
+ overallMisses
;
259 // miss rate formulas
260 for (int access_idx
= 0; access_idx
< MemCmd::NUM_MEM_CMDS
; ++access_idx
) {
261 MemCmd
cmd(access_idx
);
262 const string
&cstr
= cmd
.toString();
265 .name(name() + "." + cstr
+ "_miss_rate")
266 .desc("miss rate for " + cstr
+ " accesses")
267 .flags(total
| nozero
| nonan
)
270 missRate
[access_idx
] = misses
[access_idx
] / accesses
[access_idx
];
274 .name(name() + ".demand_miss_rate")
275 .desc("miss rate for demand accesses")
278 demandMissRate
= demandMisses
/ demandAccesses
;
281 .name(name() + ".overall_miss_rate")
282 .desc("miss rate for overall accesses")
285 overallMissRate
= overallMisses
/ overallAccesses
;
287 // miss latency formulas
288 for (int access_idx
= 0; access_idx
< MemCmd::NUM_MEM_CMDS
; ++access_idx
) {
289 MemCmd
cmd(access_idx
);
290 const string
&cstr
= cmd
.toString();
292 avgMissLatency
[access_idx
]
293 .name(name() + "." + cstr
+ "_avg_miss_latency")
294 .desc("average " + cstr
+ " miss latency")
295 .flags(total
| nozero
| nonan
)
298 avgMissLatency
[access_idx
] =
299 missLatency
[access_idx
] / misses
[access_idx
];
303 .name(name() + ".demand_avg_miss_latency")
304 .desc("average overall miss latency")
307 demandAvgMissLatency
= demandMissLatency
/ demandMisses
;
309 overallAvgMissLatency
310 .name(name() + ".overall_avg_miss_latency")
311 .desc("average overall miss latency")
314 overallAvgMissLatency
= overallMissLatency
/ overallMisses
;
316 blocked_cycles
.init(NUM_BLOCKED_CAUSES
);
318 .name(name() + ".blocked_cycles")
319 .desc("number of cycles access was blocked")
320 .subname(Blocked_NoMSHRs
, "no_mshrs")
321 .subname(Blocked_NoTargets
, "no_targets")
325 blocked_causes
.init(NUM_BLOCKED_CAUSES
);
327 .name(name() + ".blocked")
328 .desc("number of cycles access was blocked")
329 .subname(Blocked_NoMSHRs
, "no_mshrs")
330 .subname(Blocked_NoTargets
, "no_targets")
334 .name(name() + ".avg_blocked_cycles")
335 .desc("average number of cycles each access was blocked")
336 .subname(Blocked_NoMSHRs
, "no_mshrs")
337 .subname(Blocked_NoTargets
, "no_targets")
340 avg_blocked
= blocked_cycles
/ blocked_causes
;
343 .name(name() + ".fast_writes")
344 .desc("number of fast writes performed")
348 .name(name() + ".cache_copies")
349 .desc("number of cache copies performed")
353 .init(maxThreadsPerCPU
)
354 .name(name() + ".writebacks")
355 .desc("number of writebacks")
360 // MSHR hit statistics
361 for (int access_idx
= 0; access_idx
< MemCmd::NUM_MEM_CMDS
; ++access_idx
) {
362 MemCmd
cmd(access_idx
);
363 const string
&cstr
= cmd
.toString();
365 mshr_hits
[access_idx
]
366 .init(maxThreadsPerCPU
)
367 .name(name() + "." + cstr
+ "_mshr_hits")
368 .desc("number of " + cstr
+ " MSHR hits")
369 .flags(total
| nozero
| nonan
)
374 .name(name() + ".demand_mshr_hits")
375 .desc("number of demand (read+write) MSHR hits")
378 demandMshrHits
= SUM_DEMAND(mshr_hits
);
381 .name(name() + ".overall_mshr_hits")
382 .desc("number of overall MSHR hits")
385 overallMshrHits
= demandMshrHits
+ SUM_NON_DEMAND(mshr_hits
);
387 // MSHR miss statistics
388 for (int access_idx
= 0; access_idx
< MemCmd::NUM_MEM_CMDS
; ++access_idx
) {
389 MemCmd
cmd(access_idx
);
390 const string
&cstr
= cmd
.toString();
392 mshr_misses
[access_idx
]
393 .init(maxThreadsPerCPU
)
394 .name(name() + "." + cstr
+ "_mshr_misses")
395 .desc("number of " + cstr
+ " MSHR misses")
396 .flags(total
| nozero
| nonan
)
401 .name(name() + ".demand_mshr_misses")
402 .desc("number of demand (read+write) MSHR misses")
405 demandMshrMisses
= SUM_DEMAND(mshr_misses
);
408 .name(name() + ".overall_mshr_misses")
409 .desc("number of overall MSHR misses")
412 overallMshrMisses
= demandMshrMisses
+ SUM_NON_DEMAND(mshr_misses
);
414 // MSHR miss latency statistics
415 for (int access_idx
= 0; access_idx
< MemCmd::NUM_MEM_CMDS
; ++access_idx
) {
416 MemCmd
cmd(access_idx
);
417 const string
&cstr
= cmd
.toString();
419 mshr_miss_latency
[access_idx
]
420 .init(maxThreadsPerCPU
)
421 .name(name() + "." + cstr
+ "_mshr_miss_latency")
422 .desc("number of " + cstr
+ " MSHR miss cycles")
423 .flags(total
| nozero
| nonan
)
427 demandMshrMissLatency
428 .name(name() + ".demand_mshr_miss_latency")
429 .desc("number of demand (read+write) MSHR miss cycles")
432 demandMshrMissLatency
= SUM_DEMAND(mshr_miss_latency
);
434 overallMshrMissLatency
435 .name(name() + ".overall_mshr_miss_latency")
436 .desc("number of overall MSHR miss cycles")
439 overallMshrMissLatency
=
440 demandMshrMissLatency
+ SUM_NON_DEMAND(mshr_miss_latency
);
442 // MSHR uncacheable statistics
443 for (int access_idx
= 0; access_idx
< MemCmd::NUM_MEM_CMDS
; ++access_idx
) {
444 MemCmd
cmd(access_idx
);
445 const string
&cstr
= cmd
.toString();
447 mshr_uncacheable
[access_idx
]
448 .init(maxThreadsPerCPU
)
449 .name(name() + "." + cstr
+ "_mshr_uncacheable")
450 .desc("number of " + cstr
+ " MSHR uncacheable")
451 .flags(total
| nozero
| nonan
)
455 overallMshrUncacheable
456 .name(name() + ".overall_mshr_uncacheable_misses")
457 .desc("number of overall MSHR uncacheable misses")
460 overallMshrUncacheable
=
461 SUM_DEMAND(mshr_uncacheable
) + SUM_NON_DEMAND(mshr_uncacheable
);
463 // MSHR miss latency statistics
464 for (int access_idx
= 0; access_idx
< MemCmd::NUM_MEM_CMDS
; ++access_idx
) {
465 MemCmd
cmd(access_idx
);
466 const string
&cstr
= cmd
.toString();
468 mshr_uncacheable_lat
[access_idx
]
469 .init(maxThreadsPerCPU
)
470 .name(name() + "." + cstr
+ "_mshr_uncacheable_latency")
471 .desc("number of " + cstr
+ " MSHR uncacheable cycles")
472 .flags(total
| nozero
| nonan
)
476 overallMshrUncacheableLatency
477 .name(name() + ".overall_mshr_uncacheable_latency")
478 .desc("number of overall MSHR uncacheable cycles")
481 overallMshrUncacheableLatency
=
482 SUM_DEMAND(mshr_uncacheable_lat
) +
483 SUM_NON_DEMAND(mshr_uncacheable_lat
);
486 // MSHR access formulas
487 for (int access_idx
= 0; access_idx
< MemCmd::NUM_MEM_CMDS
; ++access_idx
) {
488 MemCmd
cmd(access_idx
);
489 const string
&cstr
= cmd
.toString();
491 mshrAccesses
[access_idx
]
492 .name(name() + "." + cstr
+ "_mshr_accesses")
493 .desc("number of " + cstr
+ " mshr accesses(hits+misses)")
494 .flags(total
| nozero
| nonan
)
496 mshrAccesses
[access_idx
] =
497 mshr_hits
[access_idx
] + mshr_misses
[access_idx
]
498 + mshr_uncacheable
[access_idx
];
502 .name(name() + ".demand_mshr_accesses")
503 .desc("number of demand (read+write) mshr accesses")
504 .flags(total
| nozero
| nonan
)
506 demandMshrAccesses
= demandMshrHits
+ demandMshrMisses
;
509 .name(name() + ".overall_mshr_accesses")
510 .desc("number of overall (read+write) mshr accesses")
511 .flags(total
| nozero
| nonan
)
513 overallMshrAccesses
= overallMshrHits
+ overallMshrMisses
514 + overallMshrUncacheable
;
517 // MSHR miss rate formulas
518 for (int access_idx
= 0; access_idx
< MemCmd::NUM_MEM_CMDS
; ++access_idx
) {
519 MemCmd
cmd(access_idx
);
520 const string
&cstr
= cmd
.toString();
522 mshrMissRate
[access_idx
]
523 .name(name() + "." + cstr
+ "_mshr_miss_rate")
524 .desc("mshr miss rate for " + cstr
+ " accesses")
525 .flags(total
| nozero
| nonan
)
528 mshrMissRate
[access_idx
] =
529 mshr_misses
[access_idx
] / accesses
[access_idx
];
533 .name(name() + ".demand_mshr_miss_rate")
534 .desc("mshr miss rate for demand accesses")
537 demandMshrMissRate
= demandMshrMisses
/ demandAccesses
;
540 .name(name() + ".overall_mshr_miss_rate")
541 .desc("mshr miss rate for overall accesses")
544 overallMshrMissRate
= overallMshrMisses
/ overallAccesses
;
546 // mshrMiss latency formulas
547 for (int access_idx
= 0; access_idx
< MemCmd::NUM_MEM_CMDS
; ++access_idx
) {
548 MemCmd
cmd(access_idx
);
549 const string
&cstr
= cmd
.toString();
551 avgMshrMissLatency
[access_idx
]
552 .name(name() + "." + cstr
+ "_avg_mshr_miss_latency")
553 .desc("average " + cstr
+ " mshr miss latency")
554 .flags(total
| nozero
| nonan
)
557 avgMshrMissLatency
[access_idx
] =
558 mshr_miss_latency
[access_idx
] / mshr_misses
[access_idx
];
561 demandAvgMshrMissLatency
562 .name(name() + ".demand_avg_mshr_miss_latency")
563 .desc("average overall mshr miss latency")
566 demandAvgMshrMissLatency
= demandMshrMissLatency
/ demandMshrMisses
;
568 overallAvgMshrMissLatency
569 .name(name() + ".overall_avg_mshr_miss_latency")
570 .desc("average overall mshr miss latency")
573 overallAvgMshrMissLatency
= overallMshrMissLatency
/ overallMshrMisses
;
575 // mshrUncacheable latency formulas
576 for (int access_idx
= 0; access_idx
< MemCmd::NUM_MEM_CMDS
; ++access_idx
) {
577 MemCmd
cmd(access_idx
);
578 const string
&cstr
= cmd
.toString();
580 avgMshrUncacheableLatency
[access_idx
]
581 .name(name() + "." + cstr
+ "_avg_mshr_uncacheable_latency")
582 .desc("average " + cstr
+ " mshr uncacheable latency")
583 .flags(total
| nozero
| nonan
)
586 avgMshrUncacheableLatency
[access_idx
] =
587 mshr_uncacheable_lat
[access_idx
] / mshr_uncacheable
[access_idx
];
590 overallAvgMshrUncacheableLatency
591 .name(name() + ".overall_avg_mshr_uncacheable_latency")
592 .desc("average overall mshr uncacheable latency")
595 overallAvgMshrUncacheableLatency
= overallMshrUncacheableLatency
/ overallMshrUncacheable
;
598 .init(maxThreadsPerCPU
)
599 .name(name() + ".mshr_cap_events")
600 .desc("number of times MSHR cap was activated")
604 //software prefetching stats
605 soft_prefetch_mshr_full
606 .init(maxThreadsPerCPU
)
607 .name(name() + ".soft_prefetch_mshr_full")
608 .desc("number of mshr full events for SW prefetching instrutions")
612 mshr_no_allocate_misses
613 .name(name() +".no_allocate_misses")
614 .desc("Number of misses that were no-allocate")
620 BaseCache::drain(Event
*de
)
622 int count
= memSidePort
->drain(de
) + cpuSidePort
->drain(de
);
628 changeState(SimObject::Draining
);
632 changeState(SimObject::Drained
);