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