base.cc revision 11522
16657Snate@binkert.org/*
26657Snate@binkert.org * Copyright (c) 2012-2013 ARM Limited
36657Snate@binkert.org * All rights reserved.
46657Snate@binkert.org *
56657Snate@binkert.org * The license below extends only to copyright in the software and shall
66657Snate@binkert.org * not be construed as granting a license to any other intellectual
76657Snate@binkert.org * property including but not limited to intellectual property relating
86657Snate@binkert.org * to a hardware implementation of the functionality of the software
96657Snate@binkert.org * licensed hereunder.  You may use the software subject to the license
106657Snate@binkert.org * terms below provided that you ensure that this notice is replicated
116657Snate@binkert.org * unmodified and in its entirety in all distributions of the software,
126657Snate@binkert.org * modified or unmodified, in source code or in binary form.
136657Snate@binkert.org *
146657Snate@binkert.org * Copyright (c) 2003-2005 The Regents of The University of Michigan
156657Snate@binkert.org * All rights reserved.
166657Snate@binkert.org *
176657Snate@binkert.org * Redistribution and use in source and binary forms, with or without
186657Snate@binkert.org * modification, are permitted provided that the following conditions are
196657Snate@binkert.org * met: redistributions of source code must retain the above copyright
206657Snate@binkert.org * notice, this list of conditions and the following disclaimer;
216657Snate@binkert.org * redistributions in binary form must reproduce the above copyright
226657Snate@binkert.org * notice, this list of conditions and the following disclaimer in the
236657Snate@binkert.org * documentation and/or other materials provided with the distribution;
246657Snate@binkert.org * neither the name of the copyright holders nor the names of its
256657Snate@binkert.org * contributors may be used to endorse or promote products derived from
266657Snate@binkert.org * this software without specific prior written permission.
276657Snate@binkert.org *
286657Snate@binkert.org * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
296657Snate@binkert.org * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
306657Snate@binkert.org * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
316657Snate@binkert.org * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
3211282Santhony.gutierrez@amd.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
336657Snate@binkert.org * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
346657Snate@binkert.org * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
3511282Santhony.gutierrez@amd.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
366657Snate@binkert.org * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
376657Snate@binkert.org * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
386657Snate@binkert.org * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
396657Snate@binkert.org *
406657Snate@binkert.org * Authors: Erik Hallnor
416657Snate@binkert.org */
426657Snate@binkert.org
436714Ssteve.reinhardt@amd.com/**
446714Ssteve.reinhardt@amd.com * @file
456714Ssteve.reinhardt@amd.com * Definition of BaseCache functions.
466877Ssteve.reinhardt@amd.com */
476714Ssteve.reinhardt@amd.com
486714Ssteve.reinhardt@amd.com#include "mem/cache/base.hh"
496657Snate@binkert.org
506714Ssteve.reinhardt@amd.com#include "debug/Cache.hh"
516714Ssteve.reinhardt@amd.com#include "debug/Drain.hh"
526657Snate@binkert.org#include "mem/cache/cache.hh"
536657Snate@binkert.org#include "mem/cache/mshr.hh"
546657Snate@binkert.org#include "mem/cache/tags/fa_lru.hh"
556657Snate@binkert.org#include "mem/cache/tags/lru.hh"
566657Snate@binkert.org#include "mem/cache/tags/random_repl.hh"
576657Snate@binkert.org#include "sim/full_system.hh"
586657Snate@binkert.org
596657Snate@binkert.orgusing namespace std;
606657Snate@binkert.org
616657Snate@binkert.orgBaseCache::CacheSlavePort::CacheSlavePort(const std::string &_name,
626657Snate@binkert.org                                          BaseCache *_cache,
636657Snate@binkert.org                                          const std::string &_label)
646657Snate@binkert.org    : QueuedSlavePort(_name, _cache, queue), queue(*_cache, *this, _label),
656657Snate@binkert.org      blocked(false), mustSendRetry(false), sendRetryEvent(this)
666657Snate@binkert.org{
676657Snate@binkert.org}
686657Snate@binkert.org
696657Snate@binkert.orgBaseCache::BaseCache(const BaseCacheParams *p, unsigned blk_size)
706657Snate@binkert.org    : MemObject(p),
716657Snate@binkert.org      cpuSidePort(nullptr), memSidePort(nullptr),
726657Snate@binkert.org      mshrQueue("MSHRs", p->mshrs, 0, p->demand_mshr_reserve), // see below
7311282Santhony.gutierrez@amd.com      writeBuffer("write buffer", p->write_buffers, p->mshrs), // see below
7411282Santhony.gutierrez@amd.com      blkSize(blk_size),
7511282Santhony.gutierrez@amd.com      lookupLatency(p->hit_latency),
769773Snilay@cs.wisc.edu      forwardLatency(p->hit_latency),
7711282Santhony.gutierrez@amd.com      fillLatency(p->response_latency),
7811282Santhony.gutierrez@amd.com      responseLatency(p->response_latency),
7911282Santhony.gutierrez@amd.com      numTarget(p->tgts_per_mshr),
806657Snate@binkert.org      forwardSnoops(true),
816657Snate@binkert.org      isReadOnly(p->is_read_only),
826657Snate@binkert.org      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    MemObject::regStats();
180
181    using namespace Stats;
182
183    // Hit statistics
184    for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
185        MemCmd cmd(access_idx);
186        const string &cstr = cmd.toString();
187
188        hits[access_idx]
189            .init(system->maxMasters())
190            .name(name() + "." + cstr + "_hits")
191            .desc("number of " + cstr + " hits")
192            .flags(total | nozero | nonan)
193            ;
194        for (int i = 0; i < system->maxMasters(); i++) {
195            hits[access_idx].subname(i, system->getMasterName(i));
196        }
197    }
198
199// These macros make it easier to sum the right subset of commands and
200// to change the subset of commands that are considered "demand" vs
201// "non-demand"
202#define SUM_DEMAND(s) \
203    (s[MemCmd::ReadReq] + s[MemCmd::WriteReq] + s[MemCmd::WriteLineReq] + \
204     s[MemCmd::ReadExReq] + s[MemCmd::ReadCleanReq] + s[MemCmd::ReadSharedReq])
205
206// should writebacks be included here?  prior code was inconsistent...
207#define SUM_NON_DEMAND(s) \
208    (s[MemCmd::SoftPFReq] + s[MemCmd::HardPFReq])
209
210    demandHits
211        .name(name() + ".demand_hits")
212        .desc("number of demand (read+write) hits")
213        .flags(total | nozero | nonan)
214        ;
215    demandHits = SUM_DEMAND(hits);
216    for (int i = 0; i < system->maxMasters(); i++) {
217        demandHits.subname(i, system->getMasterName(i));
218    }
219
220    overallHits
221        .name(name() + ".overall_hits")
222        .desc("number of overall hits")
223        .flags(total | nozero | nonan)
224        ;
225    overallHits = demandHits + SUM_NON_DEMAND(hits);
226    for (int i = 0; i < system->maxMasters(); i++) {
227        overallHits.subname(i, system->getMasterName(i));
228    }
229
230    // Miss statistics
231    for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
232        MemCmd cmd(access_idx);
233        const string &cstr = cmd.toString();
234
235        misses[access_idx]
236            .init(system->maxMasters())
237            .name(name() + "." + cstr + "_misses")
238            .desc("number of " + cstr + " misses")
239            .flags(total | nozero | nonan)
240            ;
241        for (int i = 0; i < system->maxMasters(); i++) {
242            misses[access_idx].subname(i, system->getMasterName(i));
243        }
244    }
245
246    demandMisses
247        .name(name() + ".demand_misses")
248        .desc("number of demand (read+write) misses")
249        .flags(total | nozero | nonan)
250        ;
251    demandMisses = SUM_DEMAND(misses);
252    for (int i = 0; i < system->maxMasters(); i++) {
253        demandMisses.subname(i, system->getMasterName(i));
254    }
255
256    overallMisses
257        .name(name() + ".overall_misses")
258        .desc("number of overall misses")
259        .flags(total | nozero | nonan)
260        ;
261    overallMisses = demandMisses + SUM_NON_DEMAND(misses);
262    for (int i = 0; i < system->maxMasters(); i++) {
263        overallMisses.subname(i, system->getMasterName(i));
264    }
265
266    // Miss latency statistics
267    for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
268        MemCmd cmd(access_idx);
269        const string &cstr = cmd.toString();
270
271        missLatency[access_idx]
272            .init(system->maxMasters())
273            .name(name() + "." + cstr + "_miss_latency")
274            .desc("number of " + cstr + " miss cycles")
275            .flags(total | nozero | nonan)
276            ;
277        for (int i = 0; i < system->maxMasters(); i++) {
278            missLatency[access_idx].subname(i, system->getMasterName(i));
279        }
280    }
281
282    demandMissLatency
283        .name(name() + ".demand_miss_latency")
284        .desc("number of demand (read+write) miss cycles")
285        .flags(total | nozero | nonan)
286        ;
287    demandMissLatency = SUM_DEMAND(missLatency);
288    for (int i = 0; i < system->maxMasters(); i++) {
289        demandMissLatency.subname(i, system->getMasterName(i));
290    }
291
292    overallMissLatency
293        .name(name() + ".overall_miss_latency")
294        .desc("number of overall miss cycles")
295        .flags(total | nozero | nonan)
296        ;
297    overallMissLatency = demandMissLatency + SUM_NON_DEMAND(missLatency);
298    for (int i = 0; i < system->maxMasters(); i++) {
299        overallMissLatency.subname(i, system->getMasterName(i));
300    }
301
302    // access formulas
303    for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
304        MemCmd cmd(access_idx);
305        const string &cstr = cmd.toString();
306
307        accesses[access_idx]
308            .name(name() + "." + cstr + "_accesses")
309            .desc("number of " + cstr + " accesses(hits+misses)")
310            .flags(total | nozero | nonan)
311            ;
312        accesses[access_idx] = hits[access_idx] + misses[access_idx];
313
314        for (int i = 0; i < system->maxMasters(); i++) {
315            accesses[access_idx].subname(i, system->getMasterName(i));
316        }
317    }
318
319    demandAccesses
320        .name(name() + ".demand_accesses")
321        .desc("number of demand (read+write) accesses")
322        .flags(total | nozero | nonan)
323        ;
324    demandAccesses = demandHits + demandMisses;
325    for (int i = 0; i < system->maxMasters(); i++) {
326        demandAccesses.subname(i, system->getMasterName(i));
327    }
328
329    overallAccesses
330        .name(name() + ".overall_accesses")
331        .desc("number of overall (read+write) accesses")
332        .flags(total | nozero | nonan)
333        ;
334    overallAccesses = overallHits + overallMisses;
335    for (int i = 0; i < system->maxMasters(); i++) {
336        overallAccesses.subname(i, system->getMasterName(i));
337    }
338
339    // miss rate formulas
340    for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
341        MemCmd cmd(access_idx);
342        const string &cstr = cmd.toString();
343
344        missRate[access_idx]
345            .name(name() + "." + cstr + "_miss_rate")
346            .desc("miss rate for " + cstr + " accesses")
347            .flags(total | nozero | nonan)
348            ;
349        missRate[access_idx] = misses[access_idx] / accesses[access_idx];
350
351        for (int i = 0; i < system->maxMasters(); i++) {
352            missRate[access_idx].subname(i, system->getMasterName(i));
353        }
354    }
355
356    demandMissRate
357        .name(name() + ".demand_miss_rate")
358        .desc("miss rate for demand accesses")
359        .flags(total | nozero | nonan)
360        ;
361    demandMissRate = demandMisses / demandAccesses;
362    for (int i = 0; i < system->maxMasters(); i++) {
363        demandMissRate.subname(i, system->getMasterName(i));
364    }
365
366    overallMissRate
367        .name(name() + ".overall_miss_rate")
368        .desc("miss rate for overall accesses")
369        .flags(total | nozero | nonan)
370        ;
371    overallMissRate = overallMisses / overallAccesses;
372    for (int i = 0; i < system->maxMasters(); i++) {
373        overallMissRate.subname(i, system->getMasterName(i));
374    }
375
376    // miss latency formulas
377    for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
378        MemCmd cmd(access_idx);
379        const string &cstr = cmd.toString();
380
381        avgMissLatency[access_idx]
382            .name(name() + "." + cstr + "_avg_miss_latency")
383            .desc("average " + cstr + " miss latency")
384            .flags(total | nozero | nonan)
385            ;
386        avgMissLatency[access_idx] =
387            missLatency[access_idx] / misses[access_idx];
388
389        for (int i = 0; i < system->maxMasters(); i++) {
390            avgMissLatency[access_idx].subname(i, system->getMasterName(i));
391        }
392    }
393
394    demandAvgMissLatency
395        .name(name() + ".demand_avg_miss_latency")
396        .desc("average overall miss latency")
397        .flags(total | nozero | nonan)
398        ;
399    demandAvgMissLatency = demandMissLatency / demandMisses;
400    for (int i = 0; i < system->maxMasters(); i++) {
401        demandAvgMissLatency.subname(i, system->getMasterName(i));
402    }
403
404    overallAvgMissLatency
405        .name(name() + ".overall_avg_miss_latency")
406        .desc("average overall miss latency")
407        .flags(total | nozero | nonan)
408        ;
409    overallAvgMissLatency = overallMissLatency / overallMisses;
410    for (int i = 0; i < system->maxMasters(); i++) {
411        overallAvgMissLatency.subname(i, system->getMasterName(i));
412    }
413
414    blocked_cycles.init(NUM_BLOCKED_CAUSES);
415    blocked_cycles
416        .name(name() + ".blocked_cycles")
417        .desc("number of cycles access was blocked")
418        .subname(Blocked_NoMSHRs, "no_mshrs")
419        .subname(Blocked_NoTargets, "no_targets")
420        ;
421
422
423    blocked_causes.init(NUM_BLOCKED_CAUSES);
424    blocked_causes
425        .name(name() + ".blocked")
426        .desc("number of cycles access was blocked")
427        .subname(Blocked_NoMSHRs, "no_mshrs")
428        .subname(Blocked_NoTargets, "no_targets")
429        ;
430
431    avg_blocked
432        .name(name() + ".avg_blocked_cycles")
433        .desc("average number of cycles each access was blocked")
434        .subname(Blocked_NoMSHRs, "no_mshrs")
435        .subname(Blocked_NoTargets, "no_targets")
436        ;
437
438    avg_blocked = blocked_cycles / blocked_causes;
439
440    unusedPrefetches
441        .name(name() + ".unused_prefetches")
442        .desc("number of HardPF blocks evicted w/o reference")
443        .flags(nozero)
444        ;
445
446    writebacks
447        .init(system->maxMasters())
448        .name(name() + ".writebacks")
449        .desc("number of writebacks")
450        .flags(total | nozero | nonan)
451        ;
452    for (int i = 0; i < system->maxMasters(); i++) {
453        writebacks.subname(i, system->getMasterName(i));
454    }
455
456    // MSHR statistics
457    // MSHR hit statistics
458    for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
459        MemCmd cmd(access_idx);
460        const string &cstr = cmd.toString();
461
462        mshr_hits[access_idx]
463            .init(system->maxMasters())
464            .name(name() + "." + cstr + "_mshr_hits")
465            .desc("number of " + cstr + " MSHR hits")
466            .flags(total | nozero | nonan)
467            ;
468        for (int i = 0; i < system->maxMasters(); i++) {
469            mshr_hits[access_idx].subname(i, system->getMasterName(i));
470        }
471    }
472
473    demandMshrHits
474        .name(name() + ".demand_mshr_hits")
475        .desc("number of demand (read+write) MSHR hits")
476        .flags(total | nozero | nonan)
477        ;
478    demandMshrHits = SUM_DEMAND(mshr_hits);
479    for (int i = 0; i < system->maxMasters(); i++) {
480        demandMshrHits.subname(i, system->getMasterName(i));
481    }
482
483    overallMshrHits
484        .name(name() + ".overall_mshr_hits")
485        .desc("number of overall MSHR hits")
486        .flags(total | nozero | nonan)
487        ;
488    overallMshrHits = demandMshrHits + SUM_NON_DEMAND(mshr_hits);
489    for (int i = 0; i < system->maxMasters(); i++) {
490        overallMshrHits.subname(i, system->getMasterName(i));
491    }
492
493    // MSHR miss statistics
494    for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
495        MemCmd cmd(access_idx);
496        const string &cstr = cmd.toString();
497
498        mshr_misses[access_idx]
499            .init(system->maxMasters())
500            .name(name() + "." + cstr + "_mshr_misses")
501            .desc("number of " + cstr + " MSHR misses")
502            .flags(total | nozero | nonan)
503            ;
504        for (int i = 0; i < system->maxMasters(); i++) {
505            mshr_misses[access_idx].subname(i, system->getMasterName(i));
506        }
507    }
508
509    demandMshrMisses
510        .name(name() + ".demand_mshr_misses")
511        .desc("number of demand (read+write) MSHR misses")
512        .flags(total | nozero | nonan)
513        ;
514    demandMshrMisses = SUM_DEMAND(mshr_misses);
515    for (int i = 0; i < system->maxMasters(); i++) {
516        demandMshrMisses.subname(i, system->getMasterName(i));
517    }
518
519    overallMshrMisses
520        .name(name() + ".overall_mshr_misses")
521        .desc("number of overall MSHR misses")
522        .flags(total | nozero | nonan)
523        ;
524    overallMshrMisses = demandMshrMisses + SUM_NON_DEMAND(mshr_misses);
525    for (int i = 0; i < system->maxMasters(); i++) {
526        overallMshrMisses.subname(i, system->getMasterName(i));
527    }
528
529    // MSHR miss latency statistics
530    for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
531        MemCmd cmd(access_idx);
532        const string &cstr = cmd.toString();
533
534        mshr_miss_latency[access_idx]
535            .init(system->maxMasters())
536            .name(name() + "." + cstr + "_mshr_miss_latency")
537            .desc("number of " + cstr + " MSHR miss cycles")
538            .flags(total | nozero | nonan)
539            ;
540        for (int i = 0; i < system->maxMasters(); i++) {
541            mshr_miss_latency[access_idx].subname(i, system->getMasterName(i));
542        }
543    }
544
545    demandMshrMissLatency
546        .name(name() + ".demand_mshr_miss_latency")
547        .desc("number of demand (read+write) MSHR miss cycles")
548        .flags(total | nozero | nonan)
549        ;
550    demandMshrMissLatency = SUM_DEMAND(mshr_miss_latency);
551    for (int i = 0; i < system->maxMasters(); i++) {
552        demandMshrMissLatency.subname(i, system->getMasterName(i));
553    }
554
555    overallMshrMissLatency
556        .name(name() + ".overall_mshr_miss_latency")
557        .desc("number of overall MSHR miss cycles")
558        .flags(total | nozero | nonan)
559        ;
560    overallMshrMissLatency =
561        demandMshrMissLatency + SUM_NON_DEMAND(mshr_miss_latency);
562    for (int i = 0; i < system->maxMasters(); i++) {
563        overallMshrMissLatency.subname(i, system->getMasterName(i));
564    }
565
566    // MSHR uncacheable statistics
567    for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
568        MemCmd cmd(access_idx);
569        const string &cstr = cmd.toString();
570
571        mshr_uncacheable[access_idx]
572            .init(system->maxMasters())
573            .name(name() + "." + cstr + "_mshr_uncacheable")
574            .desc("number of " + cstr + " MSHR uncacheable")
575            .flags(total | nozero | nonan)
576            ;
577        for (int i = 0; i < system->maxMasters(); i++) {
578            mshr_uncacheable[access_idx].subname(i, system->getMasterName(i));
579        }
580    }
581
582    overallMshrUncacheable
583        .name(name() + ".overall_mshr_uncacheable_misses")
584        .desc("number of overall MSHR uncacheable misses")
585        .flags(total | nozero | nonan)
586        ;
587    overallMshrUncacheable =
588        SUM_DEMAND(mshr_uncacheable) + SUM_NON_DEMAND(mshr_uncacheable);
589    for (int i = 0; i < system->maxMasters(); i++) {
590        overallMshrUncacheable.subname(i, system->getMasterName(i));
591    }
592
593    // MSHR miss latency statistics
594    for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
595        MemCmd cmd(access_idx);
596        const string &cstr = cmd.toString();
597
598        mshr_uncacheable_lat[access_idx]
599            .init(system->maxMasters())
600            .name(name() + "." + cstr + "_mshr_uncacheable_latency")
601            .desc("number of " + cstr + " MSHR uncacheable cycles")
602            .flags(total | nozero | nonan)
603            ;
604        for (int i = 0; i < system->maxMasters(); i++) {
605            mshr_uncacheable_lat[access_idx].subname(
606                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(
707                i, system->getMasterName(i));
708        }
709    }
710
711    demandAvgMshrMissLatency
712        .name(name() + ".demand_avg_mshr_miss_latency")
713        .desc("average overall mshr miss latency")
714        .flags(total | nozero | nonan)
715        ;
716    demandAvgMshrMissLatency = demandMshrMissLatency / demandMshrMisses;
717    for (int i = 0; i < system->maxMasters(); i++) {
718        demandAvgMshrMissLatency.subname(i, system->getMasterName(i));
719    }
720
721    overallAvgMshrMissLatency
722        .name(name() + ".overall_avg_mshr_miss_latency")
723        .desc("average overall mshr miss latency")
724        .flags(total | nozero | nonan)
725        ;
726    overallAvgMshrMissLatency = overallMshrMissLatency / overallMshrMisses;
727    for (int i = 0; i < system->maxMasters(); i++) {
728        overallAvgMshrMissLatency.subname(i, system->getMasterName(i));
729    }
730
731    // mshrUncacheable latency formulas
732    for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
733        MemCmd cmd(access_idx);
734        const string &cstr = cmd.toString();
735
736        avgMshrUncacheableLatency[access_idx]
737            .name(name() + "." + cstr + "_avg_mshr_uncacheable_latency")
738            .desc("average " + cstr + " mshr uncacheable latency")
739            .flags(total | nozero | nonan)
740            ;
741        avgMshrUncacheableLatency[access_idx] =
742            mshr_uncacheable_lat[access_idx] / mshr_uncacheable[access_idx];
743
744        for (int i = 0; i < system->maxMasters(); i++) {
745            avgMshrUncacheableLatency[access_idx].subname(
746                i, system->getMasterName(i));
747        }
748    }
749
750    overallAvgMshrUncacheableLatency
751        .name(name() + ".overall_avg_mshr_uncacheable_latency")
752        .desc("average overall mshr uncacheable latency")
753        .flags(total | nozero | nonan)
754        ;
755    overallAvgMshrUncacheableLatency =
756        overallMshrUncacheableLatency / overallMshrUncacheable;
757    for (int i = 0; i < system->maxMasters(); i++) {
758        overallAvgMshrUncacheableLatency.subname(i, system->getMasterName(i));
759    }
760
761}
762