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