base.cc revision 11455:067177a1b578
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] + s[MemCmd::WriteLineReq] + \
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    unusedPrefetches
438        .name(name() + ".unused_prefetches")
439        .desc("number of HardPF blocks evicted w/o reference")
440        .flags(nozero)
441        ;
442
443    writebacks
444        .init(system->maxMasters())
445        .name(name() + ".writebacks")
446        .desc("number of writebacks")
447        .flags(total | nozero | nonan)
448        ;
449    for (int i = 0; i < system->maxMasters(); i++) {
450        writebacks.subname(i, system->getMasterName(i));
451    }
452
453    // MSHR statistics
454    // MSHR hit statistics
455    for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
456        MemCmd cmd(access_idx);
457        const string &cstr = cmd.toString();
458
459        mshr_hits[access_idx]
460            .init(system->maxMasters())
461            .name(name() + "." + cstr + "_mshr_hits")
462            .desc("number of " + cstr + " MSHR hits")
463            .flags(total | nozero | nonan)
464            ;
465        for (int i = 0; i < system->maxMasters(); i++) {
466            mshr_hits[access_idx].subname(i, system->getMasterName(i));
467        }
468    }
469
470    demandMshrHits
471        .name(name() + ".demand_mshr_hits")
472        .desc("number of demand (read+write) MSHR hits")
473        .flags(total | nozero | nonan)
474        ;
475    demandMshrHits = SUM_DEMAND(mshr_hits);
476    for (int i = 0; i < system->maxMasters(); i++) {
477        demandMshrHits.subname(i, system->getMasterName(i));
478    }
479
480    overallMshrHits
481        .name(name() + ".overall_mshr_hits")
482        .desc("number of overall MSHR hits")
483        .flags(total | nozero | nonan)
484        ;
485    overallMshrHits = demandMshrHits + SUM_NON_DEMAND(mshr_hits);
486    for (int i = 0; i < system->maxMasters(); i++) {
487        overallMshrHits.subname(i, system->getMasterName(i));
488    }
489
490    // MSHR miss statistics
491    for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
492        MemCmd cmd(access_idx);
493        const string &cstr = cmd.toString();
494
495        mshr_misses[access_idx]
496            .init(system->maxMasters())
497            .name(name() + "." + cstr + "_mshr_misses")
498            .desc("number of " + cstr + " MSHR misses")
499            .flags(total | nozero | nonan)
500            ;
501        for (int i = 0; i < system->maxMasters(); i++) {
502            mshr_misses[access_idx].subname(i, system->getMasterName(i));
503        }
504    }
505
506    demandMshrMisses
507        .name(name() + ".demand_mshr_misses")
508        .desc("number of demand (read+write) MSHR misses")
509        .flags(total | nozero | nonan)
510        ;
511    demandMshrMisses = SUM_DEMAND(mshr_misses);
512    for (int i = 0; i < system->maxMasters(); i++) {
513        demandMshrMisses.subname(i, system->getMasterName(i));
514    }
515
516    overallMshrMisses
517        .name(name() + ".overall_mshr_misses")
518        .desc("number of overall MSHR misses")
519        .flags(total | nozero | nonan)
520        ;
521    overallMshrMisses = demandMshrMisses + SUM_NON_DEMAND(mshr_misses);
522    for (int i = 0; i < system->maxMasters(); i++) {
523        overallMshrMisses.subname(i, system->getMasterName(i));
524    }
525
526    // MSHR miss latency statistics
527    for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
528        MemCmd cmd(access_idx);
529        const string &cstr = cmd.toString();
530
531        mshr_miss_latency[access_idx]
532            .init(system->maxMasters())
533            .name(name() + "." + cstr + "_mshr_miss_latency")
534            .desc("number of " + cstr + " MSHR miss cycles")
535            .flags(total | nozero | nonan)
536            ;
537        for (int i = 0; i < system->maxMasters(); i++) {
538            mshr_miss_latency[access_idx].subname(i, system->getMasterName(i));
539        }
540    }
541
542    demandMshrMissLatency
543        .name(name() + ".demand_mshr_miss_latency")
544        .desc("number of demand (read+write) MSHR miss cycles")
545        .flags(total | nozero | nonan)
546        ;
547    demandMshrMissLatency = SUM_DEMAND(mshr_miss_latency);
548    for (int i = 0; i < system->maxMasters(); i++) {
549        demandMshrMissLatency.subname(i, system->getMasterName(i));
550    }
551
552    overallMshrMissLatency
553        .name(name() + ".overall_mshr_miss_latency")
554        .desc("number of overall MSHR miss cycles")
555        .flags(total | nozero | nonan)
556        ;
557    overallMshrMissLatency =
558        demandMshrMissLatency + SUM_NON_DEMAND(mshr_miss_latency);
559    for (int i = 0; i < system->maxMasters(); i++) {
560        overallMshrMissLatency.subname(i, system->getMasterName(i));
561    }
562
563    // MSHR uncacheable statistics
564    for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
565        MemCmd cmd(access_idx);
566        const string &cstr = cmd.toString();
567
568        mshr_uncacheable[access_idx]
569            .init(system->maxMasters())
570            .name(name() + "." + cstr + "_mshr_uncacheable")
571            .desc("number of " + cstr + " MSHR uncacheable")
572            .flags(total | nozero | nonan)
573            ;
574        for (int i = 0; i < system->maxMasters(); i++) {
575            mshr_uncacheable[access_idx].subname(i, system->getMasterName(i));
576        }
577    }
578
579    overallMshrUncacheable
580        .name(name() + ".overall_mshr_uncacheable_misses")
581        .desc("number of overall MSHR uncacheable misses")
582        .flags(total | nozero | nonan)
583        ;
584    overallMshrUncacheable =
585        SUM_DEMAND(mshr_uncacheable) + SUM_NON_DEMAND(mshr_uncacheable);
586    for (int i = 0; i < system->maxMasters(); i++) {
587        overallMshrUncacheable.subname(i, system->getMasterName(i));
588    }
589
590    // MSHR miss latency statistics
591    for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
592        MemCmd cmd(access_idx);
593        const string &cstr = cmd.toString();
594
595        mshr_uncacheable_lat[access_idx]
596            .init(system->maxMasters())
597            .name(name() + "." + cstr + "_mshr_uncacheable_latency")
598            .desc("number of " + cstr + " MSHR uncacheable cycles")
599            .flags(total | nozero | nonan)
600            ;
601        for (int i = 0; i < system->maxMasters(); i++) {
602            mshr_uncacheable_lat[access_idx].subname(i, system->getMasterName(i));
603        }
604    }
605
606    overallMshrUncacheableLatency
607        .name(name() + ".overall_mshr_uncacheable_latency")
608        .desc("number of overall MSHR uncacheable cycles")
609        .flags(total | nozero | nonan)
610        ;
611    overallMshrUncacheableLatency =
612        SUM_DEMAND(mshr_uncacheable_lat) +
613        SUM_NON_DEMAND(mshr_uncacheable_lat);
614    for (int i = 0; i < system->maxMasters(); i++) {
615        overallMshrUncacheableLatency.subname(i, system->getMasterName(i));
616    }
617
618#if 0
619    // MSHR access formulas
620    for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
621        MemCmd cmd(access_idx);
622        const string &cstr = cmd.toString();
623
624        mshrAccesses[access_idx]
625            .name(name() + "." + cstr + "_mshr_accesses")
626            .desc("number of " + cstr + " mshr accesses(hits+misses)")
627            .flags(total | nozero | nonan)
628            ;
629        mshrAccesses[access_idx] =
630            mshr_hits[access_idx] + mshr_misses[access_idx]
631            + mshr_uncacheable[access_idx];
632    }
633
634    demandMshrAccesses
635        .name(name() + ".demand_mshr_accesses")
636        .desc("number of demand (read+write) mshr accesses")
637        .flags(total | nozero | nonan)
638        ;
639    demandMshrAccesses = demandMshrHits + demandMshrMisses;
640
641    overallMshrAccesses
642        .name(name() + ".overall_mshr_accesses")
643        .desc("number of overall (read+write) mshr accesses")
644        .flags(total | nozero | nonan)
645        ;
646    overallMshrAccesses = overallMshrHits + overallMshrMisses
647        + overallMshrUncacheable;
648#endif
649
650    // MSHR miss rate formulas
651    for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
652        MemCmd cmd(access_idx);
653        const string &cstr = cmd.toString();
654
655        mshrMissRate[access_idx]
656            .name(name() + "." + cstr + "_mshr_miss_rate")
657            .desc("mshr miss rate for " + cstr + " accesses")
658            .flags(total | nozero | nonan)
659            ;
660        mshrMissRate[access_idx] =
661            mshr_misses[access_idx] / accesses[access_idx];
662
663        for (int i = 0; i < system->maxMasters(); i++) {
664            mshrMissRate[access_idx].subname(i, system->getMasterName(i));
665        }
666    }
667
668    demandMshrMissRate
669        .name(name() + ".demand_mshr_miss_rate")
670        .desc("mshr miss rate for demand accesses")
671        .flags(total | nozero | nonan)
672        ;
673    demandMshrMissRate = demandMshrMisses / demandAccesses;
674    for (int i = 0; i < system->maxMasters(); i++) {
675        demandMshrMissRate.subname(i, system->getMasterName(i));
676    }
677
678    overallMshrMissRate
679        .name(name() + ".overall_mshr_miss_rate")
680        .desc("mshr miss rate for overall accesses")
681        .flags(total | nozero | nonan)
682        ;
683    overallMshrMissRate = overallMshrMisses / overallAccesses;
684    for (int i = 0; i < system->maxMasters(); i++) {
685        overallMshrMissRate.subname(i, system->getMasterName(i));
686    }
687
688    // mshrMiss latency formulas
689    for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
690        MemCmd cmd(access_idx);
691        const string &cstr = cmd.toString();
692
693        avgMshrMissLatency[access_idx]
694            .name(name() + "." + cstr + "_avg_mshr_miss_latency")
695            .desc("average " + cstr + " mshr miss latency")
696            .flags(total | nozero | nonan)
697            ;
698        avgMshrMissLatency[access_idx] =
699            mshr_miss_latency[access_idx] / mshr_misses[access_idx];
700
701        for (int i = 0; i < system->maxMasters(); i++) {
702            avgMshrMissLatency[access_idx].subname(i, system->getMasterName(i));
703        }
704    }
705
706    demandAvgMshrMissLatency
707        .name(name() + ".demand_avg_mshr_miss_latency")
708        .desc("average overall mshr miss latency")
709        .flags(total | nozero | nonan)
710        ;
711    demandAvgMshrMissLatency = demandMshrMissLatency / demandMshrMisses;
712    for (int i = 0; i < system->maxMasters(); i++) {
713        demandAvgMshrMissLatency.subname(i, system->getMasterName(i));
714    }
715
716    overallAvgMshrMissLatency
717        .name(name() + ".overall_avg_mshr_miss_latency")
718        .desc("average overall mshr miss latency")
719        .flags(total | nozero | nonan)
720        ;
721    overallAvgMshrMissLatency = overallMshrMissLatency / overallMshrMisses;
722    for (int i = 0; i < system->maxMasters(); i++) {
723        overallAvgMshrMissLatency.subname(i, system->getMasterName(i));
724    }
725
726    // mshrUncacheable latency formulas
727    for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
728        MemCmd cmd(access_idx);
729        const string &cstr = cmd.toString();
730
731        avgMshrUncacheableLatency[access_idx]
732            .name(name() + "." + cstr + "_avg_mshr_uncacheable_latency")
733            .desc("average " + cstr + " mshr uncacheable latency")
734            .flags(total | nozero | nonan)
735            ;
736        avgMshrUncacheableLatency[access_idx] =
737            mshr_uncacheable_lat[access_idx] / mshr_uncacheable[access_idx];
738
739        for (int i = 0; i < system->maxMasters(); i++) {
740            avgMshrUncacheableLatency[access_idx].subname(i, system->getMasterName(i));
741        }
742    }
743
744    overallAvgMshrUncacheableLatency
745        .name(name() + ".overall_avg_mshr_uncacheable_latency")
746        .desc("average overall mshr uncacheable latency")
747        .flags(total | nozero | nonan)
748        ;
749    overallAvgMshrUncacheableLatency = overallMshrUncacheableLatency / overallMshrUncacheable;
750    for (int i = 0; i < system->maxMasters(); i++) {
751        overallAvgMshrUncacheableLatency.subname(i, system->getMasterName(i));
752    }
753
754}
755