1/*
2 * Copyright (c) 2012-2013 ARM Limited
3 * All rights reserved.
4 *
5 * The license below extends only to copyright in the software and shall
6 * not be construed as granting a license to any other intellectual
7 * property including but not limited to intellectual property relating
8 * to a hardware implementation of the functionality of the software
9 * licensed hereunder. You may use the software subject to the license
10 * terms below provided that you ensure that this notice is replicated
11 * unmodified and in its entirety in all distributions of the software,
12 * modified or unmodified, in source code or in binary form.
13 *
14 * Copyright (c) 2003-2005 The Regents of The University of Michigan
15 * All rights reserved.
16 *
17 * Redistribution and use in source and binary forms, with or without
18 * modification, are permitted provided that the following conditions are
19 * met: redistributions of source code must retain the above copyright
20 * notice, this list of conditions and the following disclaimer;
21 * redistributions in binary form must reproduce the above copyright
22 * notice, this list of conditions and the following disclaimer in the
23 * documentation and/or other materials provided with the distribution;
24 * neither the name of the copyright holders nor the names of its
25 * contributors may be used to endorse or promote products derived from
26 * this software without specific prior written permission.
27 *
28 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
29 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
30 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
31 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
32 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
33 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
34 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
35 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
36 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
37 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
38 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
39 *
40 * Authors: Erik Hallnor
41 */
42
43/**
44 * @file
45 * Definition of BaseCache functions.
46 */
47
48#include "debug/Cache.hh"
49#include "debug/Drain.hh"
50#include "mem/cache/tags/fa_lru.hh"
51#include "mem/cache/tags/lru.hh"
52#include "mem/cache/tags/random_repl.hh"
53#include "mem/cache/base.hh"
54#include "mem/cache/cache.hh"
55#include "mem/cache/mshr.hh"
56#include "sim/full_system.hh"
57
58using namespace std;
59
60BaseCache::CacheSlavePort::CacheSlavePort(const std::string &_name,
61 BaseCache *_cache,
62 const std::string &_label)
63 : QueuedSlavePort(_name, _cache, queue), queue(*_cache, *this, _label),
64 blocked(false), mustSendRetry(false), sendRetryEvent(this)
65{
66}
67
68BaseCache::BaseCache(const Params *p)
69 : MemObject(p),
70 cpuSidePort(nullptr), memSidePort(nullptr),
71 mshrQueue("MSHRs", p->mshrs, 4, p->demand_mshr_reserve, MSHRQueue_MSHRs),
72 writeBuffer("write buffer", p->write_buffers, p->mshrs+1000, 0,
73 MSHRQueue_WriteBuffer),
74 blkSize(p->system->cacheLineSize()),
75 lookupLatency(p->hit_latency),
76 forwardLatency(p->hit_latency),
77 fillLatency(p->response_latency),
78 responseLatency(p->response_latency),
79 numTarget(p->tgts_per_mshr),
80 forwardSnoops(p->forward_snoops),
81 isTopLevel(p->is_top_level),
82 blocked(0),
83 order(0),
84 noTargetMSHR(NULL),
85 missCount(p->max_miss_count),
86 addrRanges(p->addr_ranges.begin(), p->addr_ranges.end()),
87 system(p->system)
88{
89}
90
91void
92BaseCache::CacheSlavePort::setBlocked()
93{
94 assert(!blocked);
95 DPRINTF(CachePort, "Port is blocking new requests\n");
96 blocked = true;
97 // if we already scheduled a retry in this cycle, but it has not yet
98 // happened, cancel it
99 if (sendRetryEvent.scheduled()) {
100 owner.deschedule(sendRetryEvent);
101 DPRINTF(CachePort, "Port descheduled retry\n");
102 mustSendRetry = true;
103 }
104}
105
106void
107BaseCache::CacheSlavePort::clearBlocked()
108{
109 assert(blocked);
110 DPRINTF(CachePort, "Port is accepting new requests\n");
111 blocked = false;
112 if (mustSendRetry) {
113 // @TODO: need to find a better time (next cycle?)
114 owner.schedule(sendRetryEvent, curTick() + 1);
115 }
116}
117
118void
119BaseCache::CacheSlavePort::processSendRetry()
120{
121 DPRINTF(CachePort, "Port is sending retry\n");
122
123 // reset the flag and call retry
124 mustSendRetry = false;
125 sendRetryReq();
126}
127
128void
129BaseCache::init()
130{
131 if (!cpuSidePort->isConnected() || !memSidePort->isConnected())
132 fatal("Cache ports on %s are not connected\n", name());
133 cpuSidePort->sendRangeChange();
134}
135
136BaseMasterPort &
137BaseCache::getMasterPort(const std::string &if_name, PortID idx)
138{
139 if (if_name == "mem_side") {
140 return *memSidePort;
141 } else {
142 return MemObject::getMasterPort(if_name, idx);
143 }
144}
145
146BaseSlavePort &
147BaseCache::getSlavePort(const std::string &if_name, PortID idx)
148{
149 if (if_name == "cpu_side") {
150 return *cpuSidePort;
151 } else {
152 return MemObject::getSlavePort(if_name, idx);
153 }
154}
155
156bool
157BaseCache::inRange(Addr addr) const
158{
159 for (const auto& r : addrRanges) {
160 if (r.contains(addr)) {
161 return true;
162 }
163 }
164 return false;
165}
166
167void
168BaseCache::regStats()
169{
170 using namespace Stats;
171
172 // Hit statistics
173 for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
174 MemCmd cmd(access_idx);
175 const string &cstr = cmd.toString();
176
177 hits[access_idx]
178 .init(system->maxMasters())
179 .name(name() + "." + cstr + "_hits")
180 .desc("number of " + cstr + " hits")
181 .flags(total | nozero | nonan)
182 ;
183 for (int i = 0; i < system->maxMasters(); i++) {
184 hits[access_idx].subname(i, system->getMasterName(i));
185 }
186 }
187
188// These macros make it easier to sum the right subset of commands and
189// to change the subset of commands that are considered "demand" vs
190// "non-demand"
191#define SUM_DEMAND(s) \
192 (s[MemCmd::ReadReq] + s[MemCmd::WriteReq] + s[MemCmd::ReadExReq])
193
194// should writebacks be included here? prior code was inconsistent...
195#define SUM_NON_DEMAND(s) \
196 (s[MemCmd::SoftPFReq] + s[MemCmd::HardPFReq])
197
198 demandHits
199 .name(name() + ".demand_hits")
200 .desc("number of demand (read+write) hits")
201 .flags(total | nozero | nonan)
202 ;
203 demandHits = SUM_DEMAND(hits);
204 for (int i = 0; i < system->maxMasters(); i++) {
205 demandHits.subname(i, system->getMasterName(i));
206 }
207
208 overallHits
209 .name(name() + ".overall_hits")
210 .desc("number of overall hits")
211 .flags(total | nozero | nonan)
212 ;
213 overallHits = demandHits + SUM_NON_DEMAND(hits);
214 for (int i = 0; i < system->maxMasters(); i++) {
215 overallHits.subname(i, system->getMasterName(i));
216 }
217
218 // Miss statistics
219 for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
220 MemCmd cmd(access_idx);
221 const string &cstr = cmd.toString();
222
223 misses[access_idx]
224 .init(system->maxMasters())
225 .name(name() + "." + cstr + "_misses")
226 .desc("number of " + cstr + " misses")
227 .flags(total | nozero | nonan)
228 ;
229 for (int i = 0; i < system->maxMasters(); i++) {
230 misses[access_idx].subname(i, system->getMasterName(i));
231 }
232 }
233
234 demandMisses
235 .name(name() + ".demand_misses")
236 .desc("number of demand (read+write) misses")
237 .flags(total | nozero | nonan)
238 ;
239 demandMisses = SUM_DEMAND(misses);
240 for (int i = 0; i < system->maxMasters(); i++) {
241 demandMisses.subname(i, system->getMasterName(i));
242 }
243
244 overallMisses
245 .name(name() + ".overall_misses")
246 .desc("number of overall misses")
247 .flags(total | nozero | nonan)
248 ;
249 overallMisses = demandMisses + SUM_NON_DEMAND(misses);
250 for (int i = 0; i < system->maxMasters(); i++) {
251 overallMisses.subname(i, system->getMasterName(i));
252 }
253
254 // Miss latency statistics
255 for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
256 MemCmd cmd(access_idx);
257 const string &cstr = cmd.toString();
258
259 missLatency[access_idx]
260 .init(system->maxMasters())
261 .name(name() + "." + cstr + "_miss_latency")
262 .desc("number of " + cstr + " miss cycles")
263 .flags(total | nozero | nonan)
264 ;
265 for (int i = 0; i < system->maxMasters(); i++) {
266 missLatency[access_idx].subname(i, system->getMasterName(i));
267 }
268 }
269
270 demandMissLatency
271 .name(name() + ".demand_miss_latency")
272 .desc("number of demand (read+write) miss cycles")
273 .flags(total | nozero | nonan)
274 ;
275 demandMissLatency = SUM_DEMAND(missLatency);
276 for (int i = 0; i < system->maxMasters(); i++) {
277 demandMissLatency.subname(i, system->getMasterName(i));
278 }
279
280 overallMissLatency
281 .name(name() + ".overall_miss_latency")
282 .desc("number of overall miss cycles")
283 .flags(total | nozero | nonan)
284 ;
285 overallMissLatency = demandMissLatency + SUM_NON_DEMAND(missLatency);
286 for (int i = 0; i < system->maxMasters(); i++) {
287 overallMissLatency.subname(i, system->getMasterName(i));
288 }
289
290 // access formulas
291 for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
292 MemCmd cmd(access_idx);
293 const string &cstr = cmd.toString();
294
295 accesses[access_idx]
296 .name(name() + "." + cstr + "_accesses")
297 .desc("number of " + cstr + " accesses(hits+misses)")
298 .flags(total | nozero | nonan)
299 ;
300 accesses[access_idx] = hits[access_idx] + misses[access_idx];
301
302 for (int i = 0; i < system->maxMasters(); i++) {
303 accesses[access_idx].subname(i, system->getMasterName(i));
304 }
305 }
306
307 demandAccesses
308 .name(name() + ".demand_accesses")
309 .desc("number of demand (read+write) accesses")
310 .flags(total | nozero | nonan)
311 ;
312 demandAccesses = demandHits + demandMisses;
313 for (int i = 0; i < system->maxMasters(); i++) {
314 demandAccesses.subname(i, system->getMasterName(i));
315 }
316
317 overallAccesses
318 .name(name() + ".overall_accesses")
319 .desc("number of overall (read+write) accesses")
320 .flags(total | nozero | nonan)
321 ;
322 overallAccesses = overallHits + overallMisses;
323 for (int i = 0; i < system->maxMasters(); i++) {
324 overallAccesses.subname(i, system->getMasterName(i));
325 }
326
327 // miss rate formulas
328 for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
329 MemCmd cmd(access_idx);
330 const string &cstr = cmd.toString();
331
332 missRate[access_idx]
333 .name(name() + "." + cstr + "_miss_rate")
334 .desc("miss rate for " + cstr + " accesses")
335 .flags(total | nozero | nonan)
336 ;
337 missRate[access_idx] = misses[access_idx] / accesses[access_idx];
338
339 for (int i = 0; i < system->maxMasters(); i++) {
340 missRate[access_idx].subname(i, system->getMasterName(i));
341 }
342 }
343
344 demandMissRate
345 .name(name() + ".demand_miss_rate")
346 .desc("miss rate for demand accesses")
347 .flags(total | nozero | nonan)
348 ;
349 demandMissRate = demandMisses / demandAccesses;
350 for (int i = 0; i < system->maxMasters(); i++) {
351 demandMissRate.subname(i, system->getMasterName(i));
352 }
353
354 overallMissRate
355 .name(name() + ".overall_miss_rate")
356 .desc("miss rate for overall accesses")
357 .flags(total | nozero | nonan)
358 ;
359 overallMissRate = overallMisses / overallAccesses;
360 for (int i = 0; i < system->maxMasters(); i++) {
361 overallMissRate.subname(i, system->getMasterName(i));
362 }
363
364 // miss latency formulas
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();
368
369 avgMissLatency[access_idx]
370 .name(name() + "." + cstr + "_avg_miss_latency")
371 .desc("average " + cstr + " miss latency")
372 .flags(total | nozero | nonan)
373 ;
374 avgMissLatency[access_idx] =
375 missLatency[access_idx] / misses[access_idx];
376
377 for (int i = 0; i < system->maxMasters(); i++) {
378 avgMissLatency[access_idx].subname(i, system->getMasterName(i));
379 }
380 }
381
382 demandAvgMissLatency
383 .name(name() + ".demand_avg_miss_latency")
384 .desc("average overall miss latency")
385 .flags(total | nozero | nonan)
386 ;
387 demandAvgMissLatency = demandMissLatency / demandMisses;
388 for (int i = 0; i < system->maxMasters(); i++) {
389 demandAvgMissLatency.subname(i, system->getMasterName(i));
390 }
391
392 overallAvgMissLatency
393 .name(name() + ".overall_avg_miss_latency")
394 .desc("average overall miss latency")
395 .flags(total | nozero | nonan)
396 ;
397 overallAvgMissLatency = overallMissLatency / overallMisses;
398 for (int i = 0; i < system->maxMasters(); i++) {
399 overallAvgMissLatency.subname(i, system->getMasterName(i));
400 }
401
402 blocked_cycles.init(NUM_BLOCKED_CAUSES);
403 blocked_cycles
404 .name(name() + ".blocked_cycles")
405 .desc("number of cycles access was blocked")
406 .subname(Blocked_NoMSHRs, "no_mshrs")
407 .subname(Blocked_NoTargets, "no_targets")
408 ;
409
410
411 blocked_causes.init(NUM_BLOCKED_CAUSES);
412 blocked_causes
413 .name(name() + ".blocked")
414 .desc("number of cycles access was blocked")
415 .subname(Blocked_NoMSHRs, "no_mshrs")
416 .subname(Blocked_NoTargets, "no_targets")
417 ;
418
419 avg_blocked
420 .name(name() + ".avg_blocked_cycles")
421 .desc("average number of cycles each access was blocked")
422 .subname(Blocked_NoMSHRs, "no_mshrs")
423 .subname(Blocked_NoTargets, "no_targets")
424 ;
425
426 avg_blocked = blocked_cycles / blocked_causes;
427
428 fastWrites
429 .name(name() + ".fast_writes")
430 .desc("number of fast writes performed")
431 ;
432
433 cacheCopies
434 .name(name() + ".cache_copies")
435 .desc("number of cache copies performed")
436 ;
437
438 writebacks
439 .init(system->maxMasters())
440 .name(name() + ".writebacks")
441 .desc("number of writebacks")
442 .flags(total | nozero | nonan)
443 ;
444 for (int i = 0; i < system->maxMasters(); i++) {
445 writebacks.subname(i, system->getMasterName(i));
446 }
447
448 // MSHR statistics
449 // MSHR hit 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();
453
454 mshr_hits[access_idx]
455 .init(system->maxMasters())
456 .name(name() + "." + cstr + "_mshr_hits")
457 .desc("number of " + cstr + " MSHR hits")
458 .flags(total | nozero | nonan)
459 ;
460 for (int i = 0; i < system->maxMasters(); i++) {
461 mshr_hits[access_idx].subname(i, system->getMasterName(i));
462 }
463 }
464
465 demandMshrHits
466 .name(name() + ".demand_mshr_hits")
467 .desc("number of demand (read+write) MSHR hits")
468 .flags(total | nozero | nonan)
469 ;
470 demandMshrHits = SUM_DEMAND(mshr_hits);
471 for (int i = 0; i < system->maxMasters(); i++) {
472 demandMshrHits.subname(i, system->getMasterName(i));
473 }
474
475 overallMshrHits
476 .name(name() + ".overall_mshr_hits")
477 .desc("number of overall MSHR hits")
478 .flags(total | nozero | nonan)
479 ;
480 overallMshrHits = demandMshrHits + SUM_NON_DEMAND(mshr_hits);
481 for (int i = 0; i < system->maxMasters(); i++) {
482 overallMshrHits.subname(i, system->getMasterName(i));
483 }
484
485 // MSHR miss statistics
486 for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
487 MemCmd cmd(access_idx);
488 const string &cstr = cmd.toString();
489
490 mshr_misses[access_idx]
491 .init(system->maxMasters())
492 .name(name() + "." + cstr + "_mshr_misses")
493 .desc("number of " + cstr + " MSHR misses")
494 .flags(total | nozero | nonan)
495 ;
496 for (int i = 0; i < system->maxMasters(); i++) {
497 mshr_misses[access_idx].subname(i, system->getMasterName(i));
498 }
499 }
500
501 demandMshrMisses
502 .name(name() + ".demand_mshr_misses")
503 .desc("number of demand (read+write) MSHR misses")
504 .flags(total | nozero | nonan)
505 ;
506 demandMshrMisses = SUM_DEMAND(mshr_misses);
507 for (int i = 0; i < system->maxMasters(); i++) {
508 demandMshrMisses.subname(i, system->getMasterName(i));
509 }
510
511 overallMshrMisses
512 .name(name() + ".overall_mshr_misses")
513 .desc("number of overall MSHR misses")
514 .flags(total | nozero | nonan)
515 ;
516 overallMshrMisses = demandMshrMisses + SUM_NON_DEMAND(mshr_misses);
517 for (int i = 0; i < system->maxMasters(); i++) {
518 overallMshrMisses.subname(i, system->getMasterName(i));
519 }
520
521 // MSHR miss latency statistics
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();
525
526 mshr_miss_latency[access_idx]
527 .init(system->maxMasters())
528 .name(name() + "." + cstr + "_mshr_miss_latency")
529 .desc("number of " + cstr + " MSHR miss cycles")
530 .flags(total | nozero | nonan)
531 ;
532 for (int i = 0; i < system->maxMasters(); i++) {
533 mshr_miss_latency[access_idx].subname(i, system->getMasterName(i));
534 }
535 }
536
537 demandMshrMissLatency
538 .name(name() + ".demand_mshr_miss_latency")
539 .desc("number of demand (read+write) MSHR miss cycles")
540 .flags(total | nozero | nonan)
541 ;
542 demandMshrMissLatency = SUM_DEMAND(mshr_miss_latency);
543 for (int i = 0; i < system->maxMasters(); i++) {
544 demandMshrMissLatency.subname(i, system->getMasterName(i));
545 }
546
547 overallMshrMissLatency
548 .name(name() + ".overall_mshr_miss_latency")
549 .desc("number of overall MSHR miss cycles")
550 .flags(total | nozero | nonan)
551 ;
552 overallMshrMissLatency =
553 demandMshrMissLatency + SUM_NON_DEMAND(mshr_miss_latency);
554 for (int i = 0; i < system->maxMasters(); i++) {
555 overallMshrMissLatency.subname(i, system->getMasterName(i));
556 }
557
558 // MSHR uncacheable statistics
559 for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
560 MemCmd cmd(access_idx);
561 const string &cstr = cmd.toString();
562
563 mshr_uncacheable[access_idx]
564 .init(system->maxMasters())
565 .name(name() + "." + cstr + "_mshr_uncacheable")
566 .desc("number of " + cstr + " MSHR uncacheable")
567 .flags(total | nozero | nonan)
568 ;
569 for (int i = 0; i < system->maxMasters(); i++) {
570 mshr_uncacheable[access_idx].subname(i, system->getMasterName(i));
571 }
572 }
573
574 overallMshrUncacheable
575 .name(name() + ".overall_mshr_uncacheable_misses")
576 .desc("number of overall MSHR uncacheable misses")
577 .flags(total | nozero | nonan)
578 ;
579 overallMshrUncacheable =
580 SUM_DEMAND(mshr_uncacheable) + SUM_NON_DEMAND(mshr_uncacheable);
581 for (int i = 0; i < system->maxMasters(); i++) {
582 overallMshrUncacheable.subname(i, system->getMasterName(i));
583 }
584
585 // MSHR miss latency statistics
586 for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
587 MemCmd cmd(access_idx);
588 const string &cstr = cmd.toString();
589
590 mshr_uncacheable_lat[access_idx]
591 .init(system->maxMasters())
592 .name(name() + "." + cstr + "_mshr_uncacheable_latency")
593 .desc("number of " + cstr + " MSHR uncacheable cycles")
594 .flags(total | nozero | nonan)
595 ;
596 for (int i = 0; i < system->maxMasters(); i++) {
597 mshr_uncacheable_lat[access_idx].subname(i, system->getMasterName(i));
598 }
599 }
600
601 overallMshrUncacheableLatency
602 .name(name() + ".overall_mshr_uncacheable_latency")
603 .desc("number of overall MSHR uncacheable cycles")
604 .flags(total | nozero | nonan)
605 ;
606 overallMshrUncacheableLatency =
607 SUM_DEMAND(mshr_uncacheable_lat) +
608 SUM_NON_DEMAND(mshr_uncacheable_lat);
609 for (int i = 0; i < system->maxMasters(); i++) {
610 overallMshrUncacheableLatency.subname(i, system->getMasterName(i));
611 }
612
613#if 0
614 // MSHR access formulas
615 for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
616 MemCmd cmd(access_idx);
617 const string &cstr = cmd.toString();
618
619 mshrAccesses[access_idx]
620 .name(name() + "." + cstr + "_mshr_accesses")
621 .desc("number of " + cstr + " mshr accesses(hits+misses)")
622 .flags(total | nozero | nonan)
623 ;
624 mshrAccesses[access_idx] =
625 mshr_hits[access_idx] + mshr_misses[access_idx]
626 + mshr_uncacheable[access_idx];
627 }
628
629 demandMshrAccesses
630 .name(name() + ".demand_mshr_accesses")
631 .desc("number of demand (read+write) mshr accesses")
632 .flags(total | nozero | nonan)
633 ;
634 demandMshrAccesses = demandMshrHits + demandMshrMisses;
635
636 overallMshrAccesses
637 .name(name() + ".overall_mshr_accesses")
638 .desc("number of overall (read+write) mshr accesses")
639 .flags(total | nozero | nonan)
640 ;
641 overallMshrAccesses = overallMshrHits + overallMshrMisses
642 + overallMshrUncacheable;
643#endif
644
645 // MSHR miss rate formulas
646 for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
647 MemCmd cmd(access_idx);
648 const string &cstr = cmd.toString();
649
650 mshrMissRate[access_idx]
651 .name(name() + "." + cstr + "_mshr_miss_rate")
652 .desc("mshr miss rate for " + cstr + " accesses")
653 .flags(total | nozero | nonan)
654 ;
655 mshrMissRate[access_idx] =
656 mshr_misses[access_idx] / accesses[access_idx];
657
658 for (int i = 0; i < system->maxMasters(); i++) {
659 mshrMissRate[access_idx].subname(i, system->getMasterName(i));
660 }
661 }
662
663 demandMshrMissRate
664 .name(name() + ".demand_mshr_miss_rate")
665 .desc("mshr miss rate for demand accesses")
666 .flags(total | nozero | nonan)
667 ;
668 demandMshrMissRate = demandMshrMisses / demandAccesses;
669 for (int i = 0; i < system->maxMasters(); i++) {
670 demandMshrMissRate.subname(i, system->getMasterName(i));
671 }
672
673 overallMshrMissRate
674 .name(name() + ".overall_mshr_miss_rate")
675 .desc("mshr miss rate for overall accesses")
676 .flags(total | nozero | nonan)
677 ;
678 overallMshrMissRate = overallMshrMisses / overallAccesses;
679 for (int i = 0; i < system->maxMasters(); i++) {
680 overallMshrMissRate.subname(i, system->getMasterName(i));
681 }
682
683 // mshrMiss latency formulas
684 for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
685 MemCmd cmd(access_idx);
686 const string &cstr = cmd.toString();
687
688 avgMshrMissLatency[access_idx]
689 .name(name() + "." + cstr + "_avg_mshr_miss_latency")
690 .desc("average " + cstr + " mshr miss latency")
691 .flags(total | nozero | nonan)
692 ;
693 avgMshrMissLatency[access_idx] =
694 mshr_miss_latency[access_idx] / mshr_misses[access_idx];
695
696 for (int i = 0; i < system->maxMasters(); i++) {
697 avgMshrMissLatency[access_idx].subname(i, system->getMasterName(i));
698 }
699 }
700
701 demandAvgMshrMissLatency
702 .name(name() + ".demand_avg_mshr_miss_latency")
703 .desc("average overall mshr miss latency")
704 .flags(total | nozero | nonan)
705 ;
706 demandAvgMshrMissLatency = demandMshrMissLatency / demandMshrMisses;
707 for (int i = 0; i < system->maxMasters(); i++) {
708 demandAvgMshrMissLatency.subname(i, system->getMasterName(i));
709 }
710
711 overallAvgMshrMissLatency
712 .name(name() + ".overall_avg_mshr_miss_latency")
713 .desc("average overall mshr miss latency")
714 .flags(total | nozero | nonan)
715 ;
716 overallAvgMshrMissLatency = overallMshrMissLatency / overallMshrMisses;
717 for (int i = 0; i < system->maxMasters(); i++) {
718 overallAvgMshrMissLatency.subname(i, system->getMasterName(i));
719 }
720
721 // mshrUncacheable latency formulas
722 for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
723 MemCmd cmd(access_idx);
724 const string &cstr = cmd.toString();
725
726 avgMshrUncacheableLatency[access_idx]
727 .name(name() + "." + cstr + "_avg_mshr_uncacheable_latency")
728 .desc("average " + cstr + " mshr uncacheable latency")
729 .flags(total | nozero | nonan)
730 ;
731 avgMshrUncacheableLatency[access_idx] =
732 mshr_uncacheable_lat[access_idx] / mshr_uncacheable[access_idx];
733
734 for (int i = 0; i < system->maxMasters(); i++) {
735 avgMshrUncacheableLatency[access_idx].subname(i, system->getMasterName(i));
736 }
737 }
738
739 overallAvgMshrUncacheableLatency
740 .name(name() + ".overall_avg_mshr_uncacheable_latency")
741 .desc("average overall mshr uncacheable latency")
742 .flags(total | nozero | nonan)
743 ;
744 overallAvgMshrUncacheableLatency = overallMshrUncacheableLatency / overallMshrUncacheable;
745 for (int i = 0; i < system->maxMasters(); i++) {
746 overallAvgMshrUncacheableLatency.subname(i, system->getMasterName(i));
747 }
748
749 mshr_cap_events
750 .init(system->maxMasters())
751 .name(name() + ".mshr_cap_events")
752 .desc("number of times MSHR cap was activated")
753 .flags(total | nozero | nonan)
754 ;
755 for (int i = 0; i < system->maxMasters(); i++) {
756 mshr_cap_events.subname(i, system->getMasterName(i));
757 }
758
759 //software prefetching stats
760 soft_prefetch_mshr_full
761 .init(system->maxMasters())
762 .name(name() + ".soft_prefetch_mshr_full")
763 .desc("number of mshr full events for SW prefetching instrutions")
764 .flags(total | nozero | nonan)
765 ;
766 for (int i = 0; i < system->maxMasters(); i++) {
767 soft_prefetch_mshr_full.subname(i, system->getMasterName(i));
768 }
769
770 mshr_no_allocate_misses
771 .name(name() +".no_allocate_misses")
772 .desc("Number of misses that were no-allocate")
773 ;
774
775}
776
777unsigned int
778BaseCache::drain(DrainManager *dm)
779{
780 int count = memSidePort->drain(dm) + cpuSidePort->drain(dm) +
781 mshrQueue.drain(dm) + writeBuffer.drain(dm);
782
783 // Set status
784 if (count != 0) {
785 setDrainState(Drainable::Draining);
786 DPRINTF(Drain, "Cache not drained\n");
787 return count;
788 }
789
790 setDrainState(Drainable::Drained);
791 return 0;
792}
793
794BaseCache *
795BaseCacheParams::create()
796{
797 assert(tags);
798
799 return new Cache(this);
800}