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