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.hh"
39 #include "mem/cache/mshr.hh"
43 BaseCache::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)
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
),
63 missCount(p
->max_miss_count
),
65 addrRange(p
->addr_range
)
70 BaseCache::CachePort::recvStatusChange(Port::Status status
)
72 if (status
== Port::RangeChange
) {
73 otherPort
->sendStatusChange(Port::RangeChange
);
79 BaseCache::CachePort::checkFunctional(PacketPtr pkt
)
81 pkt
->pushLabel(label
);
82 bool done
= SimpleTimingPort::checkFunctional(pkt
);
89 BaseCache::CachePort::deviceBlockSize()
91 return cache
->getBlockSize();
96 BaseCache::CachePort::recvRetryCommon()
98 assert(waitingOnRetry
);
99 waitingOnRetry
= false;
105 BaseCache::CachePort::setBlocked()
108 DPRINTF(Cache
, "Cache Blocking\n");
110 //Clear the retry flag
111 mustSendRetry
= false;
115 BaseCache::CachePort::clearBlocked()
118 DPRINTF(Cache
, "Cache Unblocking\n");
122 DPRINTF(Cache
, "Cache Sending Retry\n");
123 mustSendRetry
= false;
124 SendRetryEvent
*ev
= new SendRetryEvent(this, true);
125 // @TODO: need to find a better time (next bus cycle?)
126 schedule(ev
, curTick
+ 1);
134 if (!cpuSidePort
|| !memSidePort
)
135 panic("Cache not hooked up on both sides\n");
136 cpuSidePort
->sendStatusChange(Port::RangeChange
);
141 BaseCache::regStats()
143 using namespace Stats
;
146 for (int access_idx
= 0; access_idx
< MemCmd::NUM_MEM_CMDS
; ++access_idx
) {
147 MemCmd
cmd(access_idx
);
148 const string
&cstr
= cmd
.toString();
151 .init(maxThreadsPerCPU
)
152 .name(name() + "." + cstr
+ "_hits")
153 .desc("number of " + cstr
+ " hits")
154 .flags(total
| nozero
| nonan
)
158 // These macros make it easier to sum the right subset of commands and
159 // to change the subset of commands that are considered "demand" vs
161 #define SUM_DEMAND(s) \
162 (s[MemCmd::ReadReq] + s[MemCmd::WriteReq] + s[MemCmd::ReadExReq])
164 // should writebacks be included here? prior code was inconsistent...
165 #define SUM_NON_DEMAND(s) \
166 (s[MemCmd::SoftPFReq] + s[MemCmd::HardPFReq])
169 .name(name() + ".demand_hits")
170 .desc("number of demand (read+write) hits")
173 demandHits
= SUM_DEMAND(hits
);
176 .name(name() + ".overall_hits")
177 .desc("number of overall hits")
180 overallHits
= demandHits
+ SUM_NON_DEMAND(hits
);
183 for (int access_idx
= 0; access_idx
< MemCmd::NUM_MEM_CMDS
; ++access_idx
) {
184 MemCmd
cmd(access_idx
);
185 const string
&cstr
= cmd
.toString();
188 .init(maxThreadsPerCPU
)
189 .name(name() + "." + cstr
+ "_misses")
190 .desc("number of " + cstr
+ " misses")
191 .flags(total
| nozero
| nonan
)
196 .name(name() + ".demand_misses")
197 .desc("number of demand (read+write) misses")
200 demandMisses
= SUM_DEMAND(misses
);
203 .name(name() + ".overall_misses")
204 .desc("number of overall misses")
207 overallMisses
= demandMisses
+ SUM_NON_DEMAND(misses
);
209 // Miss latency statistics
210 for (int access_idx
= 0; access_idx
< MemCmd::NUM_MEM_CMDS
; ++access_idx
) {
211 MemCmd
cmd(access_idx
);
212 const string
&cstr
= cmd
.toString();
214 missLatency
[access_idx
]
215 .init(maxThreadsPerCPU
)
216 .name(name() + "." + cstr
+ "_miss_latency")
217 .desc("number of " + cstr
+ " miss cycles")
218 .flags(total
| nozero
| nonan
)
223 .name(name() + ".demand_miss_latency")
224 .desc("number of demand (read+write) miss cycles")
227 demandMissLatency
= SUM_DEMAND(missLatency
);
230 .name(name() + ".overall_miss_latency")
231 .desc("number of overall miss cycles")
234 overallMissLatency
= demandMissLatency
+ SUM_NON_DEMAND(missLatency
);
237 for (int access_idx
= 0; access_idx
< MemCmd::NUM_MEM_CMDS
; ++access_idx
) {
238 MemCmd
cmd(access_idx
);
239 const string
&cstr
= cmd
.toString();
242 .name(name() + "." + cstr
+ "_accesses")
243 .desc("number of " + cstr
+ " accesses(hits+misses)")
244 .flags(total
| nozero
| nonan
)
247 accesses
[access_idx
] = hits
[access_idx
] + misses
[access_idx
];
251 .name(name() + ".demand_accesses")
252 .desc("number of demand (read+write) accesses")
255 demandAccesses
= demandHits
+ demandMisses
;
258 .name(name() + ".overall_accesses")
259 .desc("number of overall (read+write) accesses")
262 overallAccesses
= overallHits
+ overallMisses
;
264 // miss rate formulas
265 for (int access_idx
= 0; access_idx
< MemCmd::NUM_MEM_CMDS
; ++access_idx
) {
266 MemCmd
cmd(access_idx
);
267 const string
&cstr
= cmd
.toString();
270 .name(name() + "." + cstr
+ "_miss_rate")
271 .desc("miss rate for " + cstr
+ " accesses")
272 .flags(total
| nozero
| nonan
)
275 missRate
[access_idx
] = misses
[access_idx
] / accesses
[access_idx
];
279 .name(name() + ".demand_miss_rate")
280 .desc("miss rate for demand accesses")
283 demandMissRate
= demandMisses
/ demandAccesses
;
286 .name(name() + ".overall_miss_rate")
287 .desc("miss rate for overall accesses")
290 overallMissRate
= overallMisses
/ overallAccesses
;
292 // miss latency formulas
293 for (int access_idx
= 0; access_idx
< MemCmd::NUM_MEM_CMDS
; ++access_idx
) {
294 MemCmd
cmd(access_idx
);
295 const string
&cstr
= cmd
.toString();
297 avgMissLatency
[access_idx
]
298 .name(name() + "." + cstr
+ "_avg_miss_latency")
299 .desc("average " + cstr
+ " miss latency")
300 .flags(total
| nozero
| nonan
)
303 avgMissLatency
[access_idx
] =
304 missLatency
[access_idx
] / misses
[access_idx
];
308 .name(name() + ".demand_avg_miss_latency")
309 .desc("average overall miss latency")
312 demandAvgMissLatency
= demandMissLatency
/ demandMisses
;
314 overallAvgMissLatency
315 .name(name() + ".overall_avg_miss_latency")
316 .desc("average overall miss latency")
319 overallAvgMissLatency
= overallMissLatency
/ overallMisses
;
321 blocked_cycles
.init(NUM_BLOCKED_CAUSES
);
323 .name(name() + ".blocked_cycles")
324 .desc("number of cycles access was blocked")
325 .subname(Blocked_NoMSHRs
, "no_mshrs")
326 .subname(Blocked_NoTargets
, "no_targets")
330 blocked_causes
.init(NUM_BLOCKED_CAUSES
);
332 .name(name() + ".blocked")
333 .desc("number of cycles access was blocked")
334 .subname(Blocked_NoMSHRs
, "no_mshrs")
335 .subname(Blocked_NoTargets
, "no_targets")
339 .name(name() + ".avg_blocked_cycles")
340 .desc("average number of cycles each access was blocked")
341 .subname(Blocked_NoMSHRs
, "no_mshrs")
342 .subname(Blocked_NoTargets
, "no_targets")
345 avg_blocked
= blocked_cycles
/ blocked_causes
;
348 .name(name() + ".fast_writes")
349 .desc("number of fast writes performed")
353 .name(name() + ".cache_copies")
354 .desc("number of cache copies performed")
358 .init(maxThreadsPerCPU
)
359 .name(name() + ".writebacks")
360 .desc("number of writebacks")
365 // MSHR hit statistics
366 for (int access_idx
= 0; access_idx
< MemCmd::NUM_MEM_CMDS
; ++access_idx
) {
367 MemCmd
cmd(access_idx
);
368 const string
&cstr
= cmd
.toString();
370 mshr_hits
[access_idx
]
371 .init(maxThreadsPerCPU
)
372 .name(name() + "." + cstr
+ "_mshr_hits")
373 .desc("number of " + cstr
+ " MSHR hits")
374 .flags(total
| nozero
| nonan
)
379 .name(name() + ".demand_mshr_hits")
380 .desc("number of demand (read+write) MSHR hits")
383 demandMshrHits
= SUM_DEMAND(mshr_hits
);
386 .name(name() + ".overall_mshr_hits")
387 .desc("number of overall MSHR hits")
390 overallMshrHits
= demandMshrHits
+ SUM_NON_DEMAND(mshr_hits
);
392 // MSHR miss statistics
393 for (int access_idx
= 0; access_idx
< MemCmd::NUM_MEM_CMDS
; ++access_idx
) {
394 MemCmd
cmd(access_idx
);
395 const string
&cstr
= cmd
.toString();
397 mshr_misses
[access_idx
]
398 .init(maxThreadsPerCPU
)
399 .name(name() + "." + cstr
+ "_mshr_misses")
400 .desc("number of " + cstr
+ " MSHR misses")
401 .flags(total
| nozero
| nonan
)
406 .name(name() + ".demand_mshr_misses")
407 .desc("number of demand (read+write) MSHR misses")
410 demandMshrMisses
= SUM_DEMAND(mshr_misses
);
413 .name(name() + ".overall_mshr_misses")
414 .desc("number of overall MSHR misses")
417 overallMshrMisses
= demandMshrMisses
+ SUM_NON_DEMAND(mshr_misses
);
419 // MSHR miss latency statistics
420 for (int access_idx
= 0; access_idx
< MemCmd::NUM_MEM_CMDS
; ++access_idx
) {
421 MemCmd
cmd(access_idx
);
422 const string
&cstr
= cmd
.toString();
424 mshr_miss_latency
[access_idx
]
425 .init(maxThreadsPerCPU
)
426 .name(name() + "." + cstr
+ "_mshr_miss_latency")
427 .desc("number of " + cstr
+ " MSHR miss cycles")
428 .flags(total
| nozero
| nonan
)
432 demandMshrMissLatency
433 .name(name() + ".demand_mshr_miss_latency")
434 .desc("number of demand (read+write) MSHR miss cycles")
437 demandMshrMissLatency
= SUM_DEMAND(mshr_miss_latency
);
439 overallMshrMissLatency
440 .name(name() + ".overall_mshr_miss_latency")
441 .desc("number of overall MSHR miss cycles")
444 overallMshrMissLatency
=
445 demandMshrMissLatency
+ SUM_NON_DEMAND(mshr_miss_latency
);
447 // MSHR uncacheable statistics
448 for (int access_idx
= 0; access_idx
< MemCmd::NUM_MEM_CMDS
; ++access_idx
) {
449 MemCmd
cmd(access_idx
);
450 const string
&cstr
= cmd
.toString();
452 mshr_uncacheable
[access_idx
]
453 .init(maxThreadsPerCPU
)
454 .name(name() + "." + cstr
+ "_mshr_uncacheable")
455 .desc("number of " + cstr
+ " MSHR uncacheable")
456 .flags(total
| nozero
| nonan
)
460 overallMshrUncacheable
461 .name(name() + ".overall_mshr_uncacheable_misses")
462 .desc("number of overall MSHR uncacheable misses")
465 overallMshrUncacheable
=
466 SUM_DEMAND(mshr_uncacheable
) + SUM_NON_DEMAND(mshr_uncacheable
);
468 // MSHR miss latency statistics
469 for (int access_idx
= 0; access_idx
< MemCmd::NUM_MEM_CMDS
; ++access_idx
) {
470 MemCmd
cmd(access_idx
);
471 const string
&cstr
= cmd
.toString();
473 mshr_uncacheable_lat
[access_idx
]
474 .init(maxThreadsPerCPU
)
475 .name(name() + "." + cstr
+ "_mshr_uncacheable_latency")
476 .desc("number of " + cstr
+ " MSHR uncacheable cycles")
477 .flags(total
| nozero
| nonan
)
481 overallMshrUncacheableLatency
482 .name(name() + ".overall_mshr_uncacheable_latency")
483 .desc("number of overall MSHR uncacheable cycles")
486 overallMshrUncacheableLatency
=
487 SUM_DEMAND(mshr_uncacheable_lat
) +
488 SUM_NON_DEMAND(mshr_uncacheable_lat
);
491 // MSHR access formulas
492 for (int access_idx
= 0; access_idx
< MemCmd::NUM_MEM_CMDS
; ++access_idx
) {
493 MemCmd
cmd(access_idx
);
494 const string
&cstr
= cmd
.toString();
496 mshrAccesses
[access_idx
]
497 .name(name() + "." + cstr
+ "_mshr_accesses")
498 .desc("number of " + cstr
+ " mshr accesses(hits+misses)")
499 .flags(total
| nozero
| nonan
)
501 mshrAccesses
[access_idx
] =
502 mshr_hits
[access_idx
] + mshr_misses
[access_idx
]
503 + mshr_uncacheable
[access_idx
];
507 .name(name() + ".demand_mshr_accesses")
508 .desc("number of demand (read+write) mshr accesses")
509 .flags(total
| nozero
| nonan
)
511 demandMshrAccesses
= demandMshrHits
+ demandMshrMisses
;
514 .name(name() + ".overall_mshr_accesses")
515 .desc("number of overall (read+write) mshr accesses")
516 .flags(total
| nozero
| nonan
)
518 overallMshrAccesses
= overallMshrHits
+ overallMshrMisses
519 + overallMshrUncacheable
;
522 // MSHR miss rate formulas
523 for (int access_idx
= 0; access_idx
< MemCmd::NUM_MEM_CMDS
; ++access_idx
) {
524 MemCmd
cmd(access_idx
);
525 const string
&cstr
= cmd
.toString();
527 mshrMissRate
[access_idx
]
528 .name(name() + "." + cstr
+ "_mshr_miss_rate")
529 .desc("mshr miss rate for " + cstr
+ " accesses")
530 .flags(total
| nozero
| nonan
)
533 mshrMissRate
[access_idx
] =
534 mshr_misses
[access_idx
] / accesses
[access_idx
];
538 .name(name() + ".demand_mshr_miss_rate")
539 .desc("mshr miss rate for demand accesses")
542 demandMshrMissRate
= demandMshrMisses
/ demandAccesses
;
545 .name(name() + ".overall_mshr_miss_rate")
546 .desc("mshr miss rate for overall accesses")
549 overallMshrMissRate
= overallMshrMisses
/ overallAccesses
;
551 // mshrMiss latency formulas
552 for (int access_idx
= 0; access_idx
< MemCmd::NUM_MEM_CMDS
; ++access_idx
) {
553 MemCmd
cmd(access_idx
);
554 const string
&cstr
= cmd
.toString();
556 avgMshrMissLatency
[access_idx
]
557 .name(name() + "." + cstr
+ "_avg_mshr_miss_latency")
558 .desc("average " + cstr
+ " mshr miss latency")
559 .flags(total
| nozero
| nonan
)
562 avgMshrMissLatency
[access_idx
] =
563 mshr_miss_latency
[access_idx
] / mshr_misses
[access_idx
];
566 demandAvgMshrMissLatency
567 .name(name() + ".demand_avg_mshr_miss_latency")
568 .desc("average overall mshr miss latency")
571 demandAvgMshrMissLatency
= demandMshrMissLatency
/ demandMshrMisses
;
573 overallAvgMshrMissLatency
574 .name(name() + ".overall_avg_mshr_miss_latency")
575 .desc("average overall mshr miss latency")
578 overallAvgMshrMissLatency
= overallMshrMissLatency
/ overallMshrMisses
;
580 // mshrUncacheable latency formulas
581 for (int access_idx
= 0; access_idx
< MemCmd::NUM_MEM_CMDS
; ++access_idx
) {
582 MemCmd
cmd(access_idx
);
583 const string
&cstr
= cmd
.toString();
585 avgMshrUncacheableLatency
[access_idx
]
586 .name(name() + "." + cstr
+ "_avg_mshr_uncacheable_latency")
587 .desc("average " + cstr
+ " mshr uncacheable latency")
588 .flags(total
| nozero
| nonan
)
591 avgMshrUncacheableLatency
[access_idx
] =
592 mshr_uncacheable_lat
[access_idx
] / mshr_uncacheable
[access_idx
];
595 overallAvgMshrUncacheableLatency
596 .name(name() + ".overall_avg_mshr_uncacheable_latency")
597 .desc("average overall mshr uncacheable latency")
600 overallAvgMshrUncacheableLatency
= overallMshrUncacheableLatency
/ overallMshrUncacheable
;
603 .init(maxThreadsPerCPU
)
604 .name(name() + ".mshr_cap_events")
605 .desc("number of times MSHR cap was activated")
609 //software prefetching stats
610 soft_prefetch_mshr_full
611 .init(maxThreadsPerCPU
)
612 .name(name() + ".soft_prefetch_mshr_full")
613 .desc("number of mshr full events for SW prefetching instrutions")
617 mshr_no_allocate_misses
618 .name(name() +".no_allocate_misses")
619 .desc("Number of misses that were no-allocate")
625 BaseCache::drain(Event
*de
)
627 int count
= memSidePort
->drain(de
) + cpuSidePort
->drain(de
);
633 changeState(SimObject::Draining
);
637 changeState(SimObject::Drained
);