base.cc revision 10714
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
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    }
803}
804