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 std::vector
<Range
<Addr
> > filter_ranges
)
46 : SimpleTimingPort(_name
, _cache
), cache(_cache
),
47 label(_label
), otherPort(NULL
),
48 blocked(false), mustSendRetry(false), filterRanges(filter_ranges
)
53 BaseCache::BaseCache(const Params
*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
),
63 missCount(p
->max_miss_count
),
69 BaseCache::CachePort::recvStatusChange(Port::Status status
)
71 if (status
== Port::RangeChange
) {
72 otherPort
->sendStatusChange(Port::RangeChange
);
78 BaseCache::CachePort::checkFunctional(PacketPtr pkt
)
80 pkt
->pushLabel(label
);
81 bool done
= SimpleTimingPort::checkFunctional(pkt
);
88 BaseCache::CachePort::deviceBlockSize()
90 return cache
->getBlockSize();
95 BaseCache::CachePort::recvRetryCommon()
97 assert(waitingOnRetry
);
98 waitingOnRetry
= false;
104 BaseCache::CachePort::setBlocked()
107 DPRINTF(Cache
, "Cache Blocking\n");
109 //Clear the retry flag
110 mustSendRetry
= false;
114 BaseCache::CachePort::clearBlocked()
117 DPRINTF(Cache
, "Cache Unblocking\n");
121 DPRINTF(Cache
, "Cache Sending Retry\n");
122 mustSendRetry
= false;
123 SendRetryEvent
*ev
= new SendRetryEvent(this, true);
124 // @TODO: need to find a better time (next bus cycle?)
125 schedule(ev
, curTick
+ 1);
133 if (!cpuSidePort
|| !memSidePort
)
134 panic("Cache not hooked up on both sides\n");
135 cpuSidePort
->sendStatusChange(Port::RangeChange
);
140 BaseCache::regStats()
142 using namespace Stats
;
145 for (int access_idx
= 0; access_idx
< MemCmd::NUM_MEM_CMDS
; ++access_idx
) {
146 MemCmd
cmd(access_idx
);
147 const string
&cstr
= cmd
.toString();
150 .init(maxThreadsPerCPU
)
151 .name(name() + "." + cstr
+ "_hits")
152 .desc("number of " + cstr
+ " hits")
153 .flags(total
| nozero
| nonan
)
157 // These macros make it easier to sum the right subset of commands and
158 // to change the subset of commands that are considered "demand" vs
160 #define SUM_DEMAND(s) \
161 (s[MemCmd::ReadReq] + s[MemCmd::WriteReq] + s[MemCmd::ReadExReq])
163 // should writebacks be included here? prior code was inconsistent...
164 #define SUM_NON_DEMAND(s) \
165 (s[MemCmd::SoftPFReq] + s[MemCmd::HardPFReq])
168 .name(name() + ".demand_hits")
169 .desc("number of demand (read+write) hits")
172 demandHits
= SUM_DEMAND(hits
);
175 .name(name() + ".overall_hits")
176 .desc("number of overall hits")
179 overallHits
= demandHits
+ SUM_NON_DEMAND(hits
);
182 for (int access_idx
= 0; access_idx
< MemCmd::NUM_MEM_CMDS
; ++access_idx
) {
183 MemCmd
cmd(access_idx
);
184 const string
&cstr
= cmd
.toString();
187 .init(maxThreadsPerCPU
)
188 .name(name() + "." + cstr
+ "_misses")
189 .desc("number of " + cstr
+ " misses")
190 .flags(total
| nozero
| nonan
)
195 .name(name() + ".demand_misses")
196 .desc("number of demand (read+write) misses")
199 demandMisses
= SUM_DEMAND(misses
);
202 .name(name() + ".overall_misses")
203 .desc("number of overall misses")
206 overallMisses
= demandMisses
+ SUM_NON_DEMAND(misses
);
208 // Miss latency statistics
209 for (int access_idx
= 0; access_idx
< MemCmd::NUM_MEM_CMDS
; ++access_idx
) {
210 MemCmd
cmd(access_idx
);
211 const string
&cstr
= cmd
.toString();
213 missLatency
[access_idx
]
214 .init(maxThreadsPerCPU
)
215 .name(name() + "." + cstr
+ "_miss_latency")
216 .desc("number of " + cstr
+ " miss cycles")
217 .flags(total
| nozero
| nonan
)
222 .name(name() + ".demand_miss_latency")
223 .desc("number of demand (read+write) miss cycles")
226 demandMissLatency
= SUM_DEMAND(missLatency
);
229 .name(name() + ".overall_miss_latency")
230 .desc("number of overall miss cycles")
233 overallMissLatency
= demandMissLatency
+ SUM_NON_DEMAND(missLatency
);
236 for (int access_idx
= 0; access_idx
< MemCmd::NUM_MEM_CMDS
; ++access_idx
) {
237 MemCmd
cmd(access_idx
);
238 const string
&cstr
= cmd
.toString();
241 .name(name() + "." + cstr
+ "_accesses")
242 .desc("number of " + cstr
+ " accesses(hits+misses)")
243 .flags(total
| nozero
| nonan
)
246 accesses
[access_idx
] = hits
[access_idx
] + misses
[access_idx
];
250 .name(name() + ".demand_accesses")
251 .desc("number of demand (read+write) accesses")
254 demandAccesses
= demandHits
+ demandMisses
;
257 .name(name() + ".overall_accesses")
258 .desc("number of overall (read+write) accesses")
261 overallAccesses
= overallHits
+ overallMisses
;
263 // miss rate formulas
264 for (int access_idx
= 0; access_idx
< MemCmd::NUM_MEM_CMDS
; ++access_idx
) {
265 MemCmd
cmd(access_idx
);
266 const string
&cstr
= cmd
.toString();
269 .name(name() + "." + cstr
+ "_miss_rate")
270 .desc("miss rate for " + cstr
+ " accesses")
271 .flags(total
| nozero
| nonan
)
274 missRate
[access_idx
] = misses
[access_idx
] / accesses
[access_idx
];
278 .name(name() + ".demand_miss_rate")
279 .desc("miss rate for demand accesses")
282 demandMissRate
= demandMisses
/ demandAccesses
;
285 .name(name() + ".overall_miss_rate")
286 .desc("miss rate for overall accesses")
289 overallMissRate
= overallMisses
/ overallAccesses
;
291 // miss latency formulas
292 for (int access_idx
= 0; access_idx
< MemCmd::NUM_MEM_CMDS
; ++access_idx
) {
293 MemCmd
cmd(access_idx
);
294 const string
&cstr
= cmd
.toString();
296 avgMissLatency
[access_idx
]
297 .name(name() + "." + cstr
+ "_avg_miss_latency")
298 .desc("average " + cstr
+ " miss latency")
299 .flags(total
| nozero
| nonan
)
302 avgMissLatency
[access_idx
] =
303 missLatency
[access_idx
] / misses
[access_idx
];
307 .name(name() + ".demand_avg_miss_latency")
308 .desc("average overall miss latency")
311 demandAvgMissLatency
= demandMissLatency
/ demandMisses
;
313 overallAvgMissLatency
314 .name(name() + ".overall_avg_miss_latency")
315 .desc("average overall miss latency")
318 overallAvgMissLatency
= overallMissLatency
/ overallMisses
;
320 blocked_cycles
.init(NUM_BLOCKED_CAUSES
);
322 .name(name() + ".blocked_cycles")
323 .desc("number of cycles access was blocked")
324 .subname(Blocked_NoMSHRs
, "no_mshrs")
325 .subname(Blocked_NoTargets
, "no_targets")
329 blocked_causes
.init(NUM_BLOCKED_CAUSES
);
331 .name(name() + ".blocked")
332 .desc("number of cycles access was blocked")
333 .subname(Blocked_NoMSHRs
, "no_mshrs")
334 .subname(Blocked_NoTargets
, "no_targets")
338 .name(name() + ".avg_blocked_cycles")
339 .desc("average number of cycles each access was blocked")
340 .subname(Blocked_NoMSHRs
, "no_mshrs")
341 .subname(Blocked_NoTargets
, "no_targets")
344 avg_blocked
= blocked_cycles
/ blocked_causes
;
347 .name(name() + ".fast_writes")
348 .desc("number of fast writes performed")
352 .name(name() + ".cache_copies")
353 .desc("number of cache copies performed")
357 .init(maxThreadsPerCPU
)
358 .name(name() + ".writebacks")
359 .desc("number of writebacks")
364 // MSHR hit statistics
365 for (int access_idx
= 0; access_idx
< MemCmd::NUM_MEM_CMDS
; ++access_idx
) {
366 MemCmd
cmd(access_idx
);
367 const string
&cstr
= cmd
.toString();
369 mshr_hits
[access_idx
]
370 .init(maxThreadsPerCPU
)
371 .name(name() + "." + cstr
+ "_mshr_hits")
372 .desc("number of " + cstr
+ " MSHR hits")
373 .flags(total
| nozero
| nonan
)
378 .name(name() + ".demand_mshr_hits")
379 .desc("number of demand (read+write) MSHR hits")
382 demandMshrHits
= SUM_DEMAND(mshr_hits
);
385 .name(name() + ".overall_mshr_hits")
386 .desc("number of overall MSHR hits")
389 overallMshrHits
= demandMshrHits
+ SUM_NON_DEMAND(mshr_hits
);
391 // MSHR miss statistics
392 for (int access_idx
= 0; access_idx
< MemCmd::NUM_MEM_CMDS
; ++access_idx
) {
393 MemCmd
cmd(access_idx
);
394 const string
&cstr
= cmd
.toString();
396 mshr_misses
[access_idx
]
397 .init(maxThreadsPerCPU
)
398 .name(name() + "." + cstr
+ "_mshr_misses")
399 .desc("number of " + cstr
+ " MSHR misses")
400 .flags(total
| nozero
| nonan
)
405 .name(name() + ".demand_mshr_misses")
406 .desc("number of demand (read+write) MSHR misses")
409 demandMshrMisses
= SUM_DEMAND(mshr_misses
);
412 .name(name() + ".overall_mshr_misses")
413 .desc("number of overall MSHR misses")
416 overallMshrMisses
= demandMshrMisses
+ SUM_NON_DEMAND(mshr_misses
);
418 // MSHR miss latency statistics
419 for (int access_idx
= 0; access_idx
< MemCmd::NUM_MEM_CMDS
; ++access_idx
) {
420 MemCmd
cmd(access_idx
);
421 const string
&cstr
= cmd
.toString();
423 mshr_miss_latency
[access_idx
]
424 .init(maxThreadsPerCPU
)
425 .name(name() + "." + cstr
+ "_mshr_miss_latency")
426 .desc("number of " + cstr
+ " MSHR miss cycles")
427 .flags(total
| nozero
| nonan
)
431 demandMshrMissLatency
432 .name(name() + ".demand_mshr_miss_latency")
433 .desc("number of demand (read+write) MSHR miss cycles")
436 demandMshrMissLatency
= SUM_DEMAND(mshr_miss_latency
);
438 overallMshrMissLatency
439 .name(name() + ".overall_mshr_miss_latency")
440 .desc("number of overall MSHR miss cycles")
443 overallMshrMissLatency
=
444 demandMshrMissLatency
+ SUM_NON_DEMAND(mshr_miss_latency
);
446 // MSHR uncacheable statistics
447 for (int access_idx
= 0; access_idx
< MemCmd::NUM_MEM_CMDS
; ++access_idx
) {
448 MemCmd
cmd(access_idx
);
449 const string
&cstr
= cmd
.toString();
451 mshr_uncacheable
[access_idx
]
452 .init(maxThreadsPerCPU
)
453 .name(name() + "." + cstr
+ "_mshr_uncacheable")
454 .desc("number of " + cstr
+ " MSHR uncacheable")
455 .flags(total
| nozero
| nonan
)
459 overallMshrUncacheable
460 .name(name() + ".overall_mshr_uncacheable_misses")
461 .desc("number of overall MSHR uncacheable misses")
464 overallMshrUncacheable
=
465 SUM_DEMAND(mshr_uncacheable
) + SUM_NON_DEMAND(mshr_uncacheable
);
467 // MSHR miss latency statistics
468 for (int access_idx
= 0; access_idx
< MemCmd::NUM_MEM_CMDS
; ++access_idx
) {
469 MemCmd
cmd(access_idx
);
470 const string
&cstr
= cmd
.toString();
472 mshr_uncacheable_lat
[access_idx
]
473 .init(maxThreadsPerCPU
)
474 .name(name() + "." + cstr
+ "_mshr_uncacheable_latency")
475 .desc("number of " + cstr
+ " MSHR uncacheable cycles")
476 .flags(total
| nozero
| nonan
)
480 overallMshrUncacheableLatency
481 .name(name() + ".overall_mshr_uncacheable_latency")
482 .desc("number of overall MSHR uncacheable cycles")
485 overallMshrUncacheableLatency
=
486 SUM_DEMAND(mshr_uncacheable_lat
) +
487 SUM_NON_DEMAND(mshr_uncacheable_lat
);
490 // MSHR access formulas
491 for (int access_idx
= 0; access_idx
< MemCmd::NUM_MEM_CMDS
; ++access_idx
) {
492 MemCmd
cmd(access_idx
);
493 const string
&cstr
= cmd
.toString();
495 mshrAccesses
[access_idx
]
496 .name(name() + "." + cstr
+ "_mshr_accesses")
497 .desc("number of " + cstr
+ " mshr accesses(hits+misses)")
498 .flags(total
| nozero
| nonan
)
500 mshrAccesses
[access_idx
] =
501 mshr_hits
[access_idx
] + mshr_misses
[access_idx
]
502 + mshr_uncacheable
[access_idx
];
506 .name(name() + ".demand_mshr_accesses")
507 .desc("number of demand (read+write) mshr accesses")
508 .flags(total
| nozero
| nonan
)
510 demandMshrAccesses
= demandMshrHits
+ demandMshrMisses
;
513 .name(name() + ".overall_mshr_accesses")
514 .desc("number of overall (read+write) mshr accesses")
515 .flags(total
| nozero
| nonan
)
517 overallMshrAccesses
= overallMshrHits
+ overallMshrMisses
518 + overallMshrUncacheable
;
521 // MSHR miss rate formulas
522 for (int access_idx
= 0; access_idx
< MemCmd::NUM_MEM_CMDS
; ++access_idx
) {
523 MemCmd
cmd(access_idx
);
524 const string
&cstr
= cmd
.toString();
526 mshrMissRate
[access_idx
]
527 .name(name() + "." + cstr
+ "_mshr_miss_rate")
528 .desc("mshr miss rate for " + cstr
+ " accesses")
529 .flags(total
| nozero
| nonan
)
532 mshrMissRate
[access_idx
] =
533 mshr_misses
[access_idx
] / accesses
[access_idx
];
537 .name(name() + ".demand_mshr_miss_rate")
538 .desc("mshr miss rate for demand accesses")
541 demandMshrMissRate
= demandMshrMisses
/ demandAccesses
;
544 .name(name() + ".overall_mshr_miss_rate")
545 .desc("mshr miss rate for overall accesses")
548 overallMshrMissRate
= overallMshrMisses
/ overallAccesses
;
550 // mshrMiss latency formulas
551 for (int access_idx
= 0; access_idx
< MemCmd::NUM_MEM_CMDS
; ++access_idx
) {
552 MemCmd
cmd(access_idx
);
553 const string
&cstr
= cmd
.toString();
555 avgMshrMissLatency
[access_idx
]
556 .name(name() + "." + cstr
+ "_avg_mshr_miss_latency")
557 .desc("average " + cstr
+ " mshr miss latency")
558 .flags(total
| nozero
| nonan
)
561 avgMshrMissLatency
[access_idx
] =
562 mshr_miss_latency
[access_idx
] / mshr_misses
[access_idx
];
565 demandAvgMshrMissLatency
566 .name(name() + ".demand_avg_mshr_miss_latency")
567 .desc("average overall mshr miss latency")
570 demandAvgMshrMissLatency
= demandMshrMissLatency
/ demandMshrMisses
;
572 overallAvgMshrMissLatency
573 .name(name() + ".overall_avg_mshr_miss_latency")
574 .desc("average overall mshr miss latency")
577 overallAvgMshrMissLatency
= overallMshrMissLatency
/ overallMshrMisses
;
579 // mshrUncacheable latency formulas
580 for (int access_idx
= 0; access_idx
< MemCmd::NUM_MEM_CMDS
; ++access_idx
) {
581 MemCmd
cmd(access_idx
);
582 const string
&cstr
= cmd
.toString();
584 avgMshrUncacheableLatency
[access_idx
]
585 .name(name() + "." + cstr
+ "_avg_mshr_uncacheable_latency")
586 .desc("average " + cstr
+ " mshr uncacheable latency")
587 .flags(total
| nozero
| nonan
)
590 avgMshrUncacheableLatency
[access_idx
] =
591 mshr_uncacheable_lat
[access_idx
] / mshr_uncacheable
[access_idx
];
594 overallAvgMshrUncacheableLatency
595 .name(name() + ".overall_avg_mshr_uncacheable_latency")
596 .desc("average overall mshr uncacheable latency")
599 overallAvgMshrUncacheableLatency
= overallMshrUncacheableLatency
/ overallMshrUncacheable
;
602 .init(maxThreadsPerCPU
)
603 .name(name() + ".mshr_cap_events")
604 .desc("number of times MSHR cap was activated")
608 //software prefetching stats
609 soft_prefetch_mshr_full
610 .init(maxThreadsPerCPU
)
611 .name(name() + ".soft_prefetch_mshr_full")
612 .desc("number of mshr full events for SW prefetching instrutions")
616 mshr_no_allocate_misses
617 .name(name() +".no_allocate_misses")
618 .desc("Number of misses that were no-allocate")
624 BaseCache::drain(Event
*de
)
626 int count
= memSidePort
->drain(de
) + cpuSidePort
->drain(de
);
632 changeState(SimObject::Draining
);
636 changeState(SimObject::Drained
);