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