base.cc (10714:9ba5e70964a4) base.cc (10815:169af9a2779f)
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
156void
157BaseCache::regStats()
158{
159 using namespace Stats;
160
161 // Hit statistics
162 for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
163 MemCmd cmd(access_idx);
164 const string &cstr = cmd.toString();
165
166 hits[access_idx]
167 .init(system->maxMasters())
168 .name(name() + "." + cstr + "_hits")
169 .desc("number of " + cstr + " hits")
170 .flags(total | nozero | nonan)
171 ;
172 for (int i = 0; i < system->maxMasters(); i++) {
173 hits[access_idx].subname(i, system->getMasterName(i));
174 }
175 }
176
177// These macros make it easier to sum the right subset of commands and
178// to change the subset of commands that are considered "demand" vs
179// "non-demand"
180#define SUM_DEMAND(s) \
181 (s[MemCmd::ReadReq] + s[MemCmd::WriteReq] + s[MemCmd::ReadExReq])
182
183// should writebacks be included here? prior code was inconsistent...
184#define SUM_NON_DEMAND(s) \
185 (s[MemCmd::SoftPFReq] + s[MemCmd::HardPFReq])
186
187 demandHits
188 .name(name() + ".demand_hits")
189 .desc("number of demand (read+write) hits")
190 .flags(total | nozero | nonan)
191 ;
192 demandHits = SUM_DEMAND(hits);
193 for (int i = 0; i < system->maxMasters(); i++) {
194 demandHits.subname(i, system->getMasterName(i));
195 }
196
197 overallHits
198 .name(name() + ".overall_hits")
199 .desc("number of overall hits")
200 .flags(total | nozero | nonan)
201 ;
202 overallHits = demandHits + SUM_NON_DEMAND(hits);
203 for (int i = 0; i < system->maxMasters(); i++) {
204 overallHits.subname(i, system->getMasterName(i));
205 }
206
207 // Miss statistics
208 for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
209 MemCmd cmd(access_idx);
210 const string &cstr = cmd.toString();
211
212 misses[access_idx]
213 .init(system->maxMasters())
214 .name(name() + "." + cstr + "_misses")
215 .desc("number of " + cstr + " misses")
216 .flags(total | nozero | nonan)
217 ;
218 for (int i = 0; i < system->maxMasters(); i++) {
219 misses[access_idx].subname(i, system->getMasterName(i));
220 }
221 }
222
223 demandMisses
224 .name(name() + ".demand_misses")
225 .desc("number of demand (read+write) misses")
226 .flags(total | nozero | nonan)
227 ;
228 demandMisses = SUM_DEMAND(misses);
229 for (int i = 0; i < system->maxMasters(); i++) {
230 demandMisses.subname(i, system->getMasterName(i));
231 }
232
233 overallMisses
234 .name(name() + ".overall_misses")
235 .desc("number of overall misses")
236 .flags(total | nozero | nonan)
237 ;
238 overallMisses = demandMisses + SUM_NON_DEMAND(misses);
239 for (int i = 0; i < system->maxMasters(); i++) {
240 overallMisses.subname(i, system->getMasterName(i));
241 }
242
243 // Miss latency statistics
244 for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
245 MemCmd cmd(access_idx);
246 const string &cstr = cmd.toString();
247
248 missLatency[access_idx]
249 .init(system->maxMasters())
250 .name(name() + "." + cstr + "_miss_latency")
251 .desc("number of " + cstr + " miss cycles")
252 .flags(total | nozero | nonan)
253 ;
254 for (int i = 0; i < system->maxMasters(); i++) {
255 missLatency[access_idx].subname(i, system->getMasterName(i));
256 }
257 }
258
259 demandMissLatency
260 .name(name() + ".demand_miss_latency")
261 .desc("number of demand (read+write) miss cycles")
262 .flags(total | nozero | nonan)
263 ;
264 demandMissLatency = SUM_DEMAND(missLatency);
265 for (int i = 0; i < system->maxMasters(); i++) {
266 demandMissLatency.subname(i, system->getMasterName(i));
267 }
268
269 overallMissLatency
270 .name(name() + ".overall_miss_latency")
271 .desc("number of overall miss cycles")
272 .flags(total | nozero | nonan)
273 ;
274 overallMissLatency = demandMissLatency + SUM_NON_DEMAND(missLatency);
275 for (int i = 0; i < system->maxMasters(); i++) {
276 overallMissLatency.subname(i, system->getMasterName(i));
277 }
278
279 // access formulas
280 for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
281 MemCmd cmd(access_idx);
282 const string &cstr = cmd.toString();
283
284 accesses[access_idx]
285 .name(name() + "." + cstr + "_accesses")
286 .desc("number of " + cstr + " accesses(hits+misses)")
287 .flags(total | nozero | nonan)
288 ;
289 accesses[access_idx] = hits[access_idx] + misses[access_idx];
290
291 for (int i = 0; i < system->maxMasters(); i++) {
292 accesses[access_idx].subname(i, system->getMasterName(i));
293 }
294 }
295
296 demandAccesses
297 .name(name() + ".demand_accesses")
298 .desc("number of demand (read+write) accesses")
299 .flags(total | nozero | nonan)
300 ;
301 demandAccesses = demandHits + demandMisses;
302 for (int i = 0; i < system->maxMasters(); i++) {
303 demandAccesses.subname(i, system->getMasterName(i));
304 }
305
306 overallAccesses
307 .name(name() + ".overall_accesses")
308 .desc("number of overall (read+write) accesses")
309 .flags(total | nozero | nonan)
310 ;
311 overallAccesses = overallHits + overallMisses;
312 for (int i = 0; i < system->maxMasters(); i++) {
313 overallAccesses.subname(i, system->getMasterName(i));
314 }
315
316 // miss rate formulas
317 for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
318 MemCmd cmd(access_idx);
319 const string &cstr = cmd.toString();
320
321 missRate[access_idx]
322 .name(name() + "." + cstr + "_miss_rate")
323 .desc("miss rate for " + cstr + " accesses")
324 .flags(total | nozero | nonan)
325 ;
326 missRate[access_idx] = misses[access_idx] / accesses[access_idx];
327
328 for (int i = 0; i < system->maxMasters(); i++) {
329 missRate[access_idx].subname(i, system->getMasterName(i));
330 }
331 }
332
333 demandMissRate
334 .name(name() + ".demand_miss_rate")
335 .desc("miss rate for demand accesses")
336 .flags(total | nozero | nonan)
337 ;
338 demandMissRate = demandMisses / demandAccesses;
339 for (int i = 0; i < system->maxMasters(); i++) {
340 demandMissRate.subname(i, system->getMasterName(i));
341 }
342
343 overallMissRate
344 .name(name() + ".overall_miss_rate")
345 .desc("miss rate for overall accesses")
346 .flags(total | nozero | nonan)
347 ;
348 overallMissRate = overallMisses / overallAccesses;
349 for (int i = 0; i < system->maxMasters(); i++) {
350 overallMissRate.subname(i, system->getMasterName(i));
351 }
352
353 // miss latency formulas
354 for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
355 MemCmd cmd(access_idx);
356 const string &cstr = cmd.toString();
357
358 avgMissLatency[access_idx]
359 .name(name() + "." + cstr + "_avg_miss_latency")
360 .desc("average " + cstr + " miss latency")
361 .flags(total | nozero | nonan)
362 ;
363 avgMissLatency[access_idx] =
364 missLatency[access_idx] / misses[access_idx];
365
366 for (int i = 0; i < system->maxMasters(); i++) {
367 avgMissLatency[access_idx].subname(i, system->getMasterName(i));
368 }
369 }
370
371 demandAvgMissLatency
372 .name(name() + ".demand_avg_miss_latency")
373 .desc("average overall miss latency")
374 .flags(total | nozero | nonan)
375 ;
376 demandAvgMissLatency = demandMissLatency / demandMisses;
377 for (int i = 0; i < system->maxMasters(); i++) {
378 demandAvgMissLatency.subname(i, system->getMasterName(i));
379 }
380
381 overallAvgMissLatency
382 .name(name() + ".overall_avg_miss_latency")
383 .desc("average overall miss latency")
384 .flags(total | nozero | nonan)
385 ;
386 overallAvgMissLatency = overallMissLatency / overallMisses;
387 for (int i = 0; i < system->maxMasters(); i++) {
388 overallAvgMissLatency.subname(i, system->getMasterName(i));
389 }
390
391 blocked_cycles.init(NUM_BLOCKED_CAUSES);
392 blocked_cycles
393 .name(name() + ".blocked_cycles")
394 .desc("number of cycles access was blocked")
395 .subname(Blocked_NoMSHRs, "no_mshrs")
396 .subname(Blocked_NoTargets, "no_targets")
397 ;
398
399
400 blocked_causes.init(NUM_BLOCKED_CAUSES);
401 blocked_causes
402 .name(name() + ".blocked")
403 .desc("number of cycles access was blocked")
404 .subname(Blocked_NoMSHRs, "no_mshrs")
405 .subname(Blocked_NoTargets, "no_targets")
406 ;
407
408 avg_blocked
409 .name(name() + ".avg_blocked_cycles")
410 .desc("average number of cycles each access was blocked")
411 .subname(Blocked_NoMSHRs, "no_mshrs")
412 .subname(Blocked_NoTargets, "no_targets")
413 ;
414
415 avg_blocked = blocked_cycles / blocked_causes;
416
417 fastWrites
418 .name(name() + ".fast_writes")
419 .desc("number of fast writes performed")
420 ;
421
422 cacheCopies
423 .name(name() + ".cache_copies")
424 .desc("number of cache copies performed")
425 ;
426
427 writebacks
428 .init(system->maxMasters())
429 .name(name() + ".writebacks")
430 .desc("number of writebacks")
431 .flags(total | nozero | nonan)
432 ;
433 for (int i = 0; i < system->maxMasters(); i++) {
434 writebacks.subname(i, system->getMasterName(i));
435 }
436
437 // MSHR statistics
438 // MSHR hit statistics
439 for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
440 MemCmd cmd(access_idx);
441 const string &cstr = cmd.toString();
442
443 mshr_hits[access_idx]
444 .init(system->maxMasters())
445 .name(name() + "." + cstr + "_mshr_hits")
446 .desc("number of " + cstr + " MSHR hits")
447 .flags(total | nozero | nonan)
448 ;
449 for (int i = 0; i < system->maxMasters(); i++) {
450 mshr_hits[access_idx].subname(i, system->getMasterName(i));
451 }
452 }
453
454 demandMshrHits
455 .name(name() + ".demand_mshr_hits")
456 .desc("number of demand (read+write) MSHR hits")
457 .flags(total | nozero | nonan)
458 ;
459 demandMshrHits = SUM_DEMAND(mshr_hits);
460 for (int i = 0; i < system->maxMasters(); i++) {
461 demandMshrHits.subname(i, system->getMasterName(i));
462 }
463
464 overallMshrHits
465 .name(name() + ".overall_mshr_hits")
466 .desc("number of overall MSHR hits")
467 .flags(total | nozero | nonan)
468 ;
469 overallMshrHits = demandMshrHits + SUM_NON_DEMAND(mshr_hits);
470 for (int i = 0; i < system->maxMasters(); i++) {
471 overallMshrHits.subname(i, system->getMasterName(i));
472 }
473
474 // MSHR miss statistics
475 for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
476 MemCmd cmd(access_idx);
477 const string &cstr = cmd.toString();
478
479 mshr_misses[access_idx]
480 .init(system->maxMasters())
481 .name(name() + "." + cstr + "_mshr_misses")
482 .desc("number of " + cstr + " MSHR misses")
483 .flags(total | nozero | nonan)
484 ;
485 for (int i = 0; i < system->maxMasters(); i++) {
486 mshr_misses[access_idx].subname(i, system->getMasterName(i));
487 }
488 }
489
490 demandMshrMisses
491 .name(name() + ".demand_mshr_misses")
492 .desc("number of demand (read+write) MSHR misses")
493 .flags(total | nozero | nonan)
494 ;
495 demandMshrMisses = SUM_DEMAND(mshr_misses);
496 for (int i = 0; i < system->maxMasters(); i++) {
497 demandMshrMisses.subname(i, system->getMasterName(i));
498 }
499
500 overallMshrMisses
501 .name(name() + ".overall_mshr_misses")
502 .desc("number of overall MSHR misses")
503 .flags(total | nozero | nonan)
504 ;
505 overallMshrMisses = demandMshrMisses + SUM_NON_DEMAND(mshr_misses);
506 for (int i = 0; i < system->maxMasters(); i++) {
507 overallMshrMisses.subname(i, system->getMasterName(i));
508 }
509
510 // MSHR miss latency statistics
511 for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
512 MemCmd cmd(access_idx);
513 const string &cstr = cmd.toString();
514
515 mshr_miss_latency[access_idx]
516 .init(system->maxMasters())
517 .name(name() + "." + cstr + "_mshr_miss_latency")
518 .desc("number of " + cstr + " MSHR miss cycles")
519 .flags(total | nozero | nonan)
520 ;
521 for (int i = 0; i < system->maxMasters(); i++) {
522 mshr_miss_latency[access_idx].subname(i, system->getMasterName(i));
523 }
524 }
525
526 demandMshrMissLatency
527 .name(name() + ".demand_mshr_miss_latency")
528 .desc("number of demand (read+write) MSHR miss cycles")
529 .flags(total | nozero | nonan)
530 ;
531 demandMshrMissLatency = SUM_DEMAND(mshr_miss_latency);
532 for (int i = 0; i < system->maxMasters(); i++) {
533 demandMshrMissLatency.subname(i, system->getMasterName(i));
534 }
535
536 overallMshrMissLatency
537 .name(name() + ".overall_mshr_miss_latency")
538 .desc("number of overall MSHR miss cycles")
539 .flags(total | nozero | nonan)
540 ;
541 overallMshrMissLatency =
542 demandMshrMissLatency + SUM_NON_DEMAND(mshr_miss_latency);
543 for (int i = 0; i < system->maxMasters(); i++) {
544 overallMshrMissLatency.subname(i, system->getMasterName(i));
545 }
546
547 // MSHR uncacheable statistics
548 for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
549 MemCmd cmd(access_idx);
550 const string &cstr = cmd.toString();
551
552 mshr_uncacheable[access_idx]
553 .init(system->maxMasters())
554 .name(name() + "." + cstr + "_mshr_uncacheable")
555 .desc("number of " + cstr + " MSHR uncacheable")
556 .flags(total | nozero | nonan)
557 ;
558 for (int i = 0; i < system->maxMasters(); i++) {
559 mshr_uncacheable[access_idx].subname(i, system->getMasterName(i));
560 }
561 }
562
563 overallMshrUncacheable
564 .name(name() + ".overall_mshr_uncacheable_misses")
565 .desc("number of overall MSHR uncacheable misses")
566 .flags(total | nozero | nonan)
567 ;
568 overallMshrUncacheable =
569 SUM_DEMAND(mshr_uncacheable) + SUM_NON_DEMAND(mshr_uncacheable);
570 for (int i = 0; i < system->maxMasters(); i++) {
571 overallMshrUncacheable.subname(i, system->getMasterName(i));
572 }
573
574 // MSHR miss latency statistics
575 for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
576 MemCmd cmd(access_idx);
577 const string &cstr = cmd.toString();
578
579 mshr_uncacheable_lat[access_idx]
580 .init(system->maxMasters())
581 .name(name() + "." + cstr + "_mshr_uncacheable_latency")
582 .desc("number of " + cstr + " MSHR uncacheable cycles")
583 .flags(total | nozero | nonan)
584 ;
585 for (int i = 0; i < system->maxMasters(); i++) {
586 mshr_uncacheable_lat[access_idx].subname(i, system->getMasterName(i));
587 }
588 }
589
590 overallMshrUncacheableLatency
591 .name(name() + ".overall_mshr_uncacheable_latency")
592 .desc("number of overall MSHR uncacheable cycles")
593 .flags(total | nozero | nonan)
594 ;
595 overallMshrUncacheableLatency =
596 SUM_DEMAND(mshr_uncacheable_lat) +
597 SUM_NON_DEMAND(mshr_uncacheable_lat);
598 for (int i = 0; i < system->maxMasters(); i++) {
599 overallMshrUncacheableLatency.subname(i, system->getMasterName(i));
600 }
601
602#if 0
603 // MSHR access formulas
604 for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
605 MemCmd cmd(access_idx);
606 const string &cstr = cmd.toString();
607
608 mshrAccesses[access_idx]
609 .name(name() + "." + cstr + "_mshr_accesses")
610 .desc("number of " + cstr + " mshr accesses(hits+misses)")
611 .flags(total | nozero | nonan)
612 ;
613 mshrAccesses[access_idx] =
614 mshr_hits[access_idx] + mshr_misses[access_idx]
615 + mshr_uncacheable[access_idx];
616 }
617
618 demandMshrAccesses
619 .name(name() + ".demand_mshr_accesses")
620 .desc("number of demand (read+write) mshr accesses")
621 .flags(total | nozero | nonan)
622 ;
623 demandMshrAccesses = demandMshrHits + demandMshrMisses;
624
625 overallMshrAccesses
626 .name(name() + ".overall_mshr_accesses")
627 .desc("number of overall (read+write) mshr accesses")
628 .flags(total | nozero | nonan)
629 ;
630 overallMshrAccesses = overallMshrHits + overallMshrMisses
631 + overallMshrUncacheable;
632#endif
633
634 // MSHR miss rate formulas
635 for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
636 MemCmd cmd(access_idx);
637 const string &cstr = cmd.toString();
638
639 mshrMissRate[access_idx]
640 .name(name() + "." + cstr + "_mshr_miss_rate")
641 .desc("mshr miss rate for " + cstr + " accesses")
642 .flags(total | nozero | nonan)
643 ;
644 mshrMissRate[access_idx] =
645 mshr_misses[access_idx] / accesses[access_idx];
646
647 for (int i = 0; i < system->maxMasters(); i++) {
648 mshrMissRate[access_idx].subname(i, system->getMasterName(i));
649 }
650 }
651
652 demandMshrMissRate
653 .name(name() + ".demand_mshr_miss_rate")
654 .desc("mshr miss rate for demand accesses")
655 .flags(total | nozero | nonan)
656 ;
657 demandMshrMissRate = demandMshrMisses / demandAccesses;
658 for (int i = 0; i < system->maxMasters(); i++) {
659 demandMshrMissRate.subname(i, system->getMasterName(i));
660 }
661
662 overallMshrMissRate
663 .name(name() + ".overall_mshr_miss_rate")
664 .desc("mshr miss rate for overall accesses")
665 .flags(total | nozero | nonan)
666 ;
667 overallMshrMissRate = overallMshrMisses / overallAccesses;
668 for (int i = 0; i < system->maxMasters(); i++) {
669 overallMshrMissRate.subname(i, system->getMasterName(i));
670 }
671
672 // mshrMiss latency formulas
673 for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
674 MemCmd cmd(access_idx);
675 const string &cstr = cmd.toString();
676
677 avgMshrMissLatency[access_idx]
678 .name(name() + "." + cstr + "_avg_mshr_miss_latency")
679 .desc("average " + cstr + " mshr miss latency")
680 .flags(total | nozero | nonan)
681 ;
682 avgMshrMissLatency[access_idx] =
683 mshr_miss_latency[access_idx] / mshr_misses[access_idx];
684
685 for (int i = 0; i < system->maxMasters(); i++) {
686 avgMshrMissLatency[access_idx].subname(i, system->getMasterName(i));
687 }
688 }
689
690 demandAvgMshrMissLatency
691 .name(name() + ".demand_avg_mshr_miss_latency")
692 .desc("average overall mshr miss latency")
693 .flags(total | nozero | nonan)
694 ;
695 demandAvgMshrMissLatency = demandMshrMissLatency / demandMshrMisses;
696 for (int i = 0; i < system->maxMasters(); i++) {
697 demandAvgMshrMissLatency.subname(i, system->getMasterName(i));
698 }
699
700 overallAvgMshrMissLatency
701 .name(name() + ".overall_avg_mshr_miss_latency")
702 .desc("average overall mshr miss latency")
703 .flags(total | nozero | nonan)
704 ;
705 overallAvgMshrMissLatency = overallMshrMissLatency / overallMshrMisses;
706 for (int i = 0; i < system->maxMasters(); i++) {
707 overallAvgMshrMissLatency.subname(i, system->getMasterName(i));
708 }
709
710 // mshrUncacheable latency formulas
711 for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
712 MemCmd cmd(access_idx);
713 const string &cstr = cmd.toString();
714
715 avgMshrUncacheableLatency[access_idx]
716 .name(name() + "." + cstr + "_avg_mshr_uncacheable_latency")
717 .desc("average " + cstr + " mshr uncacheable latency")
718 .flags(total | nozero | nonan)
719 ;
720 avgMshrUncacheableLatency[access_idx] =
721 mshr_uncacheable_lat[access_idx] / mshr_uncacheable[access_idx];
722
723 for (int i = 0; i < system->maxMasters(); i++) {
724 avgMshrUncacheableLatency[access_idx].subname(i, system->getMasterName(i));
725 }
726 }
727
728 overallAvgMshrUncacheableLatency
729 .name(name() + ".overall_avg_mshr_uncacheable_latency")
730 .desc("average overall mshr uncacheable latency")
731 .flags(total | nozero | nonan)
732 ;
733 overallAvgMshrUncacheableLatency = overallMshrUncacheableLatency / overallMshrUncacheable;
734 for (int i = 0; i < system->maxMasters(); i++) {
735 overallAvgMshrUncacheableLatency.subname(i, system->getMasterName(i));
736 }
737
738 mshr_cap_events
739 .init(system->maxMasters())
740 .name(name() + ".mshr_cap_events")
741 .desc("number of times MSHR cap was activated")
742 .flags(total | nozero | nonan)
743 ;
744 for (int i = 0; i < system->maxMasters(); i++) {
745 mshr_cap_events.subname(i, system->getMasterName(i));
746 }
747
748 //software prefetching stats
749 soft_prefetch_mshr_full
750 .init(system->maxMasters())
751 .name(name() + ".soft_prefetch_mshr_full")
752 .desc("number of mshr full events for SW prefetching instrutions")
753 .flags(total | nozero | nonan)
754 ;
755 for (int i = 0; i < system->maxMasters(); i++) {
756 soft_prefetch_mshr_full.subname(i, system->getMasterName(i));
757 }
758
759 mshr_no_allocate_misses
760 .name(name() +".no_allocate_misses")
761 .desc("Number of misses that were no-allocate")
762 ;
763
764}
765
766unsigned int
767BaseCache::drain(DrainManager *dm)
768{
769 int count = memSidePort->drain(dm) + cpuSidePort->drain(dm) +
770 mshrQueue.drain(dm) + writeBuffer.drain(dm);
771
772 // Set status
773 if (count != 0) {
774 setDrainState(Drainable::Draining);
775 DPRINTF(Drain, "Cache not drained\n");
776 return count;
777 }
778
779 setDrainState(Drainable::Drained);
780 return 0;
781}
782
783BaseCache *
784BaseCacheParams::create()
785{
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
156void
157BaseCache::regStats()
158{
159 using namespace Stats;
160
161 // Hit statistics
162 for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
163 MemCmd cmd(access_idx);
164 const string &cstr = cmd.toString();
165
166 hits[access_idx]
167 .init(system->maxMasters())
168 .name(name() + "." + cstr + "_hits")
169 .desc("number of " + cstr + " hits")
170 .flags(total | nozero | nonan)
171 ;
172 for (int i = 0; i < system->maxMasters(); i++) {
173 hits[access_idx].subname(i, system->getMasterName(i));
174 }
175 }
176
177// These macros make it easier to sum the right subset of commands and
178// to change the subset of commands that are considered "demand" vs
179// "non-demand"
180#define SUM_DEMAND(s) \
181 (s[MemCmd::ReadReq] + s[MemCmd::WriteReq] + s[MemCmd::ReadExReq])
182
183// should writebacks be included here? prior code was inconsistent...
184#define SUM_NON_DEMAND(s) \
185 (s[MemCmd::SoftPFReq] + s[MemCmd::HardPFReq])
186
187 demandHits
188 .name(name() + ".demand_hits")
189 .desc("number of demand (read+write) hits")
190 .flags(total | nozero | nonan)
191 ;
192 demandHits = SUM_DEMAND(hits);
193 for (int i = 0; i < system->maxMasters(); i++) {
194 demandHits.subname(i, system->getMasterName(i));
195 }
196
197 overallHits
198 .name(name() + ".overall_hits")
199 .desc("number of overall hits")
200 .flags(total | nozero | nonan)
201 ;
202 overallHits = demandHits + SUM_NON_DEMAND(hits);
203 for (int i = 0; i < system->maxMasters(); i++) {
204 overallHits.subname(i, system->getMasterName(i));
205 }
206
207 // Miss statistics
208 for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
209 MemCmd cmd(access_idx);
210 const string &cstr = cmd.toString();
211
212 misses[access_idx]
213 .init(system->maxMasters())
214 .name(name() + "." + cstr + "_misses")
215 .desc("number of " + cstr + " misses")
216 .flags(total | nozero | nonan)
217 ;
218 for (int i = 0; i < system->maxMasters(); i++) {
219 misses[access_idx].subname(i, system->getMasterName(i));
220 }
221 }
222
223 demandMisses
224 .name(name() + ".demand_misses")
225 .desc("number of demand (read+write) misses")
226 .flags(total | nozero | nonan)
227 ;
228 demandMisses = SUM_DEMAND(misses);
229 for (int i = 0; i < system->maxMasters(); i++) {
230 demandMisses.subname(i, system->getMasterName(i));
231 }
232
233 overallMisses
234 .name(name() + ".overall_misses")
235 .desc("number of overall misses")
236 .flags(total | nozero | nonan)
237 ;
238 overallMisses = demandMisses + SUM_NON_DEMAND(misses);
239 for (int i = 0; i < system->maxMasters(); i++) {
240 overallMisses.subname(i, system->getMasterName(i));
241 }
242
243 // Miss latency statistics
244 for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
245 MemCmd cmd(access_idx);
246 const string &cstr = cmd.toString();
247
248 missLatency[access_idx]
249 .init(system->maxMasters())
250 .name(name() + "." + cstr + "_miss_latency")
251 .desc("number of " + cstr + " miss cycles")
252 .flags(total | nozero | nonan)
253 ;
254 for (int i = 0; i < system->maxMasters(); i++) {
255 missLatency[access_idx].subname(i, system->getMasterName(i));
256 }
257 }
258
259 demandMissLatency
260 .name(name() + ".demand_miss_latency")
261 .desc("number of demand (read+write) miss cycles")
262 .flags(total | nozero | nonan)
263 ;
264 demandMissLatency = SUM_DEMAND(missLatency);
265 for (int i = 0; i < system->maxMasters(); i++) {
266 demandMissLatency.subname(i, system->getMasterName(i));
267 }
268
269 overallMissLatency
270 .name(name() + ".overall_miss_latency")
271 .desc("number of overall miss cycles")
272 .flags(total | nozero | nonan)
273 ;
274 overallMissLatency = demandMissLatency + SUM_NON_DEMAND(missLatency);
275 for (int i = 0; i < system->maxMasters(); i++) {
276 overallMissLatency.subname(i, system->getMasterName(i));
277 }
278
279 // access formulas
280 for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
281 MemCmd cmd(access_idx);
282 const string &cstr = cmd.toString();
283
284 accesses[access_idx]
285 .name(name() + "." + cstr + "_accesses")
286 .desc("number of " + cstr + " accesses(hits+misses)")
287 .flags(total | nozero | nonan)
288 ;
289 accesses[access_idx] = hits[access_idx] + misses[access_idx];
290
291 for (int i = 0; i < system->maxMasters(); i++) {
292 accesses[access_idx].subname(i, system->getMasterName(i));
293 }
294 }
295
296 demandAccesses
297 .name(name() + ".demand_accesses")
298 .desc("number of demand (read+write) accesses")
299 .flags(total | nozero | nonan)
300 ;
301 demandAccesses = demandHits + demandMisses;
302 for (int i = 0; i < system->maxMasters(); i++) {
303 demandAccesses.subname(i, system->getMasterName(i));
304 }
305
306 overallAccesses
307 .name(name() + ".overall_accesses")
308 .desc("number of overall (read+write) accesses")
309 .flags(total | nozero | nonan)
310 ;
311 overallAccesses = overallHits + overallMisses;
312 for (int i = 0; i < system->maxMasters(); i++) {
313 overallAccesses.subname(i, system->getMasterName(i));
314 }
315
316 // miss rate formulas
317 for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
318 MemCmd cmd(access_idx);
319 const string &cstr = cmd.toString();
320
321 missRate[access_idx]
322 .name(name() + "." + cstr + "_miss_rate")
323 .desc("miss rate for " + cstr + " accesses")
324 .flags(total | nozero | nonan)
325 ;
326 missRate[access_idx] = misses[access_idx] / accesses[access_idx];
327
328 for (int i = 0; i < system->maxMasters(); i++) {
329 missRate[access_idx].subname(i, system->getMasterName(i));
330 }
331 }
332
333 demandMissRate
334 .name(name() + ".demand_miss_rate")
335 .desc("miss rate for demand accesses")
336 .flags(total | nozero | nonan)
337 ;
338 demandMissRate = demandMisses / demandAccesses;
339 for (int i = 0; i < system->maxMasters(); i++) {
340 demandMissRate.subname(i, system->getMasterName(i));
341 }
342
343 overallMissRate
344 .name(name() + ".overall_miss_rate")
345 .desc("miss rate for overall accesses")
346 .flags(total | nozero | nonan)
347 ;
348 overallMissRate = overallMisses / overallAccesses;
349 for (int i = 0; i < system->maxMasters(); i++) {
350 overallMissRate.subname(i, system->getMasterName(i));
351 }
352
353 // miss latency formulas
354 for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
355 MemCmd cmd(access_idx);
356 const string &cstr = cmd.toString();
357
358 avgMissLatency[access_idx]
359 .name(name() + "." + cstr + "_avg_miss_latency")
360 .desc("average " + cstr + " miss latency")
361 .flags(total | nozero | nonan)
362 ;
363 avgMissLatency[access_idx] =
364 missLatency[access_idx] / misses[access_idx];
365
366 for (int i = 0; i < system->maxMasters(); i++) {
367 avgMissLatency[access_idx].subname(i, system->getMasterName(i));
368 }
369 }
370
371 demandAvgMissLatency
372 .name(name() + ".demand_avg_miss_latency")
373 .desc("average overall miss latency")
374 .flags(total | nozero | nonan)
375 ;
376 demandAvgMissLatency = demandMissLatency / demandMisses;
377 for (int i = 0; i < system->maxMasters(); i++) {
378 demandAvgMissLatency.subname(i, system->getMasterName(i));
379 }
380
381 overallAvgMissLatency
382 .name(name() + ".overall_avg_miss_latency")
383 .desc("average overall miss latency")
384 .flags(total | nozero | nonan)
385 ;
386 overallAvgMissLatency = overallMissLatency / overallMisses;
387 for (int i = 0; i < system->maxMasters(); i++) {
388 overallAvgMissLatency.subname(i, system->getMasterName(i));
389 }
390
391 blocked_cycles.init(NUM_BLOCKED_CAUSES);
392 blocked_cycles
393 .name(name() + ".blocked_cycles")
394 .desc("number of cycles access was blocked")
395 .subname(Blocked_NoMSHRs, "no_mshrs")
396 .subname(Blocked_NoTargets, "no_targets")
397 ;
398
399
400 blocked_causes.init(NUM_BLOCKED_CAUSES);
401 blocked_causes
402 .name(name() + ".blocked")
403 .desc("number of cycles access was blocked")
404 .subname(Blocked_NoMSHRs, "no_mshrs")
405 .subname(Blocked_NoTargets, "no_targets")
406 ;
407
408 avg_blocked
409 .name(name() + ".avg_blocked_cycles")
410 .desc("average number of cycles each access was blocked")
411 .subname(Blocked_NoMSHRs, "no_mshrs")
412 .subname(Blocked_NoTargets, "no_targets")
413 ;
414
415 avg_blocked = blocked_cycles / blocked_causes;
416
417 fastWrites
418 .name(name() + ".fast_writes")
419 .desc("number of fast writes performed")
420 ;
421
422 cacheCopies
423 .name(name() + ".cache_copies")
424 .desc("number of cache copies performed")
425 ;
426
427 writebacks
428 .init(system->maxMasters())
429 .name(name() + ".writebacks")
430 .desc("number of writebacks")
431 .flags(total | nozero | nonan)
432 ;
433 for (int i = 0; i < system->maxMasters(); i++) {
434 writebacks.subname(i, system->getMasterName(i));
435 }
436
437 // MSHR statistics
438 // MSHR hit statistics
439 for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
440 MemCmd cmd(access_idx);
441 const string &cstr = cmd.toString();
442
443 mshr_hits[access_idx]
444 .init(system->maxMasters())
445 .name(name() + "." + cstr + "_mshr_hits")
446 .desc("number of " + cstr + " MSHR hits")
447 .flags(total | nozero | nonan)
448 ;
449 for (int i = 0; i < system->maxMasters(); i++) {
450 mshr_hits[access_idx].subname(i, system->getMasterName(i));
451 }
452 }
453
454 demandMshrHits
455 .name(name() + ".demand_mshr_hits")
456 .desc("number of demand (read+write) MSHR hits")
457 .flags(total | nozero | nonan)
458 ;
459 demandMshrHits = SUM_DEMAND(mshr_hits);
460 for (int i = 0; i < system->maxMasters(); i++) {
461 demandMshrHits.subname(i, system->getMasterName(i));
462 }
463
464 overallMshrHits
465 .name(name() + ".overall_mshr_hits")
466 .desc("number of overall MSHR hits")
467 .flags(total | nozero | nonan)
468 ;
469 overallMshrHits = demandMshrHits + SUM_NON_DEMAND(mshr_hits);
470 for (int i = 0; i < system->maxMasters(); i++) {
471 overallMshrHits.subname(i, system->getMasterName(i));
472 }
473
474 // MSHR miss statistics
475 for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
476 MemCmd cmd(access_idx);
477 const string &cstr = cmd.toString();
478
479 mshr_misses[access_idx]
480 .init(system->maxMasters())
481 .name(name() + "." + cstr + "_mshr_misses")
482 .desc("number of " + cstr + " MSHR misses")
483 .flags(total | nozero | nonan)
484 ;
485 for (int i = 0; i < system->maxMasters(); i++) {
486 mshr_misses[access_idx].subname(i, system->getMasterName(i));
487 }
488 }
489
490 demandMshrMisses
491 .name(name() + ".demand_mshr_misses")
492 .desc("number of demand (read+write) MSHR misses")
493 .flags(total | nozero | nonan)
494 ;
495 demandMshrMisses = SUM_DEMAND(mshr_misses);
496 for (int i = 0; i < system->maxMasters(); i++) {
497 demandMshrMisses.subname(i, system->getMasterName(i));
498 }
499
500 overallMshrMisses
501 .name(name() + ".overall_mshr_misses")
502 .desc("number of overall MSHR misses")
503 .flags(total | nozero | nonan)
504 ;
505 overallMshrMisses = demandMshrMisses + SUM_NON_DEMAND(mshr_misses);
506 for (int i = 0; i < system->maxMasters(); i++) {
507 overallMshrMisses.subname(i, system->getMasterName(i));
508 }
509
510 // MSHR miss latency statistics
511 for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
512 MemCmd cmd(access_idx);
513 const string &cstr = cmd.toString();
514
515 mshr_miss_latency[access_idx]
516 .init(system->maxMasters())
517 .name(name() + "." + cstr + "_mshr_miss_latency")
518 .desc("number of " + cstr + " MSHR miss cycles")
519 .flags(total | nozero | nonan)
520 ;
521 for (int i = 0; i < system->maxMasters(); i++) {
522 mshr_miss_latency[access_idx].subname(i, system->getMasterName(i));
523 }
524 }
525
526 demandMshrMissLatency
527 .name(name() + ".demand_mshr_miss_latency")
528 .desc("number of demand (read+write) MSHR miss cycles")
529 .flags(total | nozero | nonan)
530 ;
531 demandMshrMissLatency = SUM_DEMAND(mshr_miss_latency);
532 for (int i = 0; i < system->maxMasters(); i++) {
533 demandMshrMissLatency.subname(i, system->getMasterName(i));
534 }
535
536 overallMshrMissLatency
537 .name(name() + ".overall_mshr_miss_latency")
538 .desc("number of overall MSHR miss cycles")
539 .flags(total | nozero | nonan)
540 ;
541 overallMshrMissLatency =
542 demandMshrMissLatency + SUM_NON_DEMAND(mshr_miss_latency);
543 for (int i = 0; i < system->maxMasters(); i++) {
544 overallMshrMissLatency.subname(i, system->getMasterName(i));
545 }
546
547 // MSHR uncacheable statistics
548 for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
549 MemCmd cmd(access_idx);
550 const string &cstr = cmd.toString();
551
552 mshr_uncacheable[access_idx]
553 .init(system->maxMasters())
554 .name(name() + "." + cstr + "_mshr_uncacheable")
555 .desc("number of " + cstr + " MSHR uncacheable")
556 .flags(total | nozero | nonan)
557 ;
558 for (int i = 0; i < system->maxMasters(); i++) {
559 mshr_uncacheable[access_idx].subname(i, system->getMasterName(i));
560 }
561 }
562
563 overallMshrUncacheable
564 .name(name() + ".overall_mshr_uncacheable_misses")
565 .desc("number of overall MSHR uncacheable misses")
566 .flags(total | nozero | nonan)
567 ;
568 overallMshrUncacheable =
569 SUM_DEMAND(mshr_uncacheable) + SUM_NON_DEMAND(mshr_uncacheable);
570 for (int i = 0; i < system->maxMasters(); i++) {
571 overallMshrUncacheable.subname(i, system->getMasterName(i));
572 }
573
574 // MSHR miss latency statistics
575 for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
576 MemCmd cmd(access_idx);
577 const string &cstr = cmd.toString();
578
579 mshr_uncacheable_lat[access_idx]
580 .init(system->maxMasters())
581 .name(name() + "." + cstr + "_mshr_uncacheable_latency")
582 .desc("number of " + cstr + " MSHR uncacheable cycles")
583 .flags(total | nozero | nonan)
584 ;
585 for (int i = 0; i < system->maxMasters(); i++) {
586 mshr_uncacheable_lat[access_idx].subname(i, system->getMasterName(i));
587 }
588 }
589
590 overallMshrUncacheableLatency
591 .name(name() + ".overall_mshr_uncacheable_latency")
592 .desc("number of overall MSHR uncacheable cycles")
593 .flags(total | nozero | nonan)
594 ;
595 overallMshrUncacheableLatency =
596 SUM_DEMAND(mshr_uncacheable_lat) +
597 SUM_NON_DEMAND(mshr_uncacheable_lat);
598 for (int i = 0; i < system->maxMasters(); i++) {
599 overallMshrUncacheableLatency.subname(i, system->getMasterName(i));
600 }
601
602#if 0
603 // MSHR access formulas
604 for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
605 MemCmd cmd(access_idx);
606 const string &cstr = cmd.toString();
607
608 mshrAccesses[access_idx]
609 .name(name() + "." + cstr + "_mshr_accesses")
610 .desc("number of " + cstr + " mshr accesses(hits+misses)")
611 .flags(total | nozero | nonan)
612 ;
613 mshrAccesses[access_idx] =
614 mshr_hits[access_idx] + mshr_misses[access_idx]
615 + mshr_uncacheable[access_idx];
616 }
617
618 demandMshrAccesses
619 .name(name() + ".demand_mshr_accesses")
620 .desc("number of demand (read+write) mshr accesses")
621 .flags(total | nozero | nonan)
622 ;
623 demandMshrAccesses = demandMshrHits + demandMshrMisses;
624
625 overallMshrAccesses
626 .name(name() + ".overall_mshr_accesses")
627 .desc("number of overall (read+write) mshr accesses")
628 .flags(total | nozero | nonan)
629 ;
630 overallMshrAccesses = overallMshrHits + overallMshrMisses
631 + overallMshrUncacheable;
632#endif
633
634 // MSHR miss rate formulas
635 for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
636 MemCmd cmd(access_idx);
637 const string &cstr = cmd.toString();
638
639 mshrMissRate[access_idx]
640 .name(name() + "." + cstr + "_mshr_miss_rate")
641 .desc("mshr miss rate for " + cstr + " accesses")
642 .flags(total | nozero | nonan)
643 ;
644 mshrMissRate[access_idx] =
645 mshr_misses[access_idx] / accesses[access_idx];
646
647 for (int i = 0; i < system->maxMasters(); i++) {
648 mshrMissRate[access_idx].subname(i, system->getMasterName(i));
649 }
650 }
651
652 demandMshrMissRate
653 .name(name() + ".demand_mshr_miss_rate")
654 .desc("mshr miss rate for demand accesses")
655 .flags(total | nozero | nonan)
656 ;
657 demandMshrMissRate = demandMshrMisses / demandAccesses;
658 for (int i = 0; i < system->maxMasters(); i++) {
659 demandMshrMissRate.subname(i, system->getMasterName(i));
660 }
661
662 overallMshrMissRate
663 .name(name() + ".overall_mshr_miss_rate")
664 .desc("mshr miss rate for overall accesses")
665 .flags(total | nozero | nonan)
666 ;
667 overallMshrMissRate = overallMshrMisses / overallAccesses;
668 for (int i = 0; i < system->maxMasters(); i++) {
669 overallMshrMissRate.subname(i, system->getMasterName(i));
670 }
671
672 // mshrMiss latency formulas
673 for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
674 MemCmd cmd(access_idx);
675 const string &cstr = cmd.toString();
676
677 avgMshrMissLatency[access_idx]
678 .name(name() + "." + cstr + "_avg_mshr_miss_latency")
679 .desc("average " + cstr + " mshr miss latency")
680 .flags(total | nozero | nonan)
681 ;
682 avgMshrMissLatency[access_idx] =
683 mshr_miss_latency[access_idx] / mshr_misses[access_idx];
684
685 for (int i = 0; i < system->maxMasters(); i++) {
686 avgMshrMissLatency[access_idx].subname(i, system->getMasterName(i));
687 }
688 }
689
690 demandAvgMshrMissLatency
691 .name(name() + ".demand_avg_mshr_miss_latency")
692 .desc("average overall mshr miss latency")
693 .flags(total | nozero | nonan)
694 ;
695 demandAvgMshrMissLatency = demandMshrMissLatency / demandMshrMisses;
696 for (int i = 0; i < system->maxMasters(); i++) {
697 demandAvgMshrMissLatency.subname(i, system->getMasterName(i));
698 }
699
700 overallAvgMshrMissLatency
701 .name(name() + ".overall_avg_mshr_miss_latency")
702 .desc("average overall mshr miss latency")
703 .flags(total | nozero | nonan)
704 ;
705 overallAvgMshrMissLatency = overallMshrMissLatency / overallMshrMisses;
706 for (int i = 0; i < system->maxMasters(); i++) {
707 overallAvgMshrMissLatency.subname(i, system->getMasterName(i));
708 }
709
710 // mshrUncacheable latency formulas
711 for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
712 MemCmd cmd(access_idx);
713 const string &cstr = cmd.toString();
714
715 avgMshrUncacheableLatency[access_idx]
716 .name(name() + "." + cstr + "_avg_mshr_uncacheable_latency")
717 .desc("average " + cstr + " mshr uncacheable latency")
718 .flags(total | nozero | nonan)
719 ;
720 avgMshrUncacheableLatency[access_idx] =
721 mshr_uncacheable_lat[access_idx] / mshr_uncacheable[access_idx];
722
723 for (int i = 0; i < system->maxMasters(); i++) {
724 avgMshrUncacheableLatency[access_idx].subname(i, system->getMasterName(i));
725 }
726 }
727
728 overallAvgMshrUncacheableLatency
729 .name(name() + ".overall_avg_mshr_uncacheable_latency")
730 .desc("average overall mshr uncacheable latency")
731 .flags(total | nozero | nonan)
732 ;
733 overallAvgMshrUncacheableLatency = overallMshrUncacheableLatency / overallMshrUncacheable;
734 for (int i = 0; i < system->maxMasters(); i++) {
735 overallAvgMshrUncacheableLatency.subname(i, system->getMasterName(i));
736 }
737
738 mshr_cap_events
739 .init(system->maxMasters())
740 .name(name() + ".mshr_cap_events")
741 .desc("number of times MSHR cap was activated")
742 .flags(total | nozero | nonan)
743 ;
744 for (int i = 0; i < system->maxMasters(); i++) {
745 mshr_cap_events.subname(i, system->getMasterName(i));
746 }
747
748 //software prefetching stats
749 soft_prefetch_mshr_full
750 .init(system->maxMasters())
751 .name(name() + ".soft_prefetch_mshr_full")
752 .desc("number of mshr full events for SW prefetching instrutions")
753 .flags(total | nozero | nonan)
754 ;
755 for (int i = 0; i < system->maxMasters(); i++) {
756 soft_prefetch_mshr_full.subname(i, system->getMasterName(i));
757 }
758
759 mshr_no_allocate_misses
760 .name(name() +".no_allocate_misses")
761 .desc("Number of misses that were no-allocate")
762 ;
763
764}
765
766unsigned int
767BaseCache::drain(DrainManager *dm)
768{
769 int count = memSidePort->drain(dm) + cpuSidePort->drain(dm) +
770 mshrQueue.drain(dm) + writeBuffer.drain(dm);
771
772 // Set status
773 if (count != 0) {
774 setDrainState(Drainable::Draining);
775 DPRINTF(Drain, "Cache not drained\n");
776 return count;
777 }
778
779 setDrainState(Drainable::Drained);
780 return 0;
781}
782
783BaseCache *
784BaseCacheParams::create()
785{
786 unsigned numSets = size / (assoc * system->cacheLineSize());
787
788 assert(tags);
789
786 assert(tags);
787
790 if (dynamic_cast<FALRU*>(tags)) {
791 if (numSets != 1)
792 fatal("Got FALRU tags with more than one set\n");
793 return new Cache<FALRU>(this);
794 } else if (dynamic_cast<LRU*>(tags)) {
795 if (numSets == 1)
796 warn("Consider using FALRU tags for a fully associative cache\n");
797 return new Cache<LRU>(this);
798 } else if (dynamic_cast<RandomRepl*>(tags)) {
799 return new Cache<RandomRepl>(this);
800 } else {
801 fatal("No suitable tags selected\n");
802 }
788 return new Cache(this);
803}
789}