base.cc revision 8232
19651SAndreas.Sandberg@ARM.com/*
29651SAndreas.Sandberg@ARM.com * Copyright (c) 2003-2005 The Regents of The University of Michigan
39651SAndreas.Sandberg@ARM.com * All rights reserved.
49651SAndreas.Sandberg@ARM.com *
59651SAndreas.Sandberg@ARM.com * Redistribution and use in source and binary forms, with or without
69651SAndreas.Sandberg@ARM.com * modification, are permitted provided that the following conditions are
79651SAndreas.Sandberg@ARM.com * met: redistributions of source code must retain the above copyright
89651SAndreas.Sandberg@ARM.com * notice, this list of conditions and the following disclaimer;
99651SAndreas.Sandberg@ARM.com * redistributions in binary form must reproduce the above copyright
109651SAndreas.Sandberg@ARM.com * notice, this list of conditions and the following disclaimer in the
119651SAndreas.Sandberg@ARM.com * documentation and/or other materials provided with the distribution;
129651SAndreas.Sandberg@ARM.com * neither the name of the copyright holders nor the names of its
139651SAndreas.Sandberg@ARM.com * contributors may be used to endorse or promote products derived from
149651SAndreas.Sandberg@ARM.com * this software without specific prior written permission.
159651SAndreas.Sandberg@ARM.com *
169651SAndreas.Sandberg@ARM.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
179651SAndreas.Sandberg@ARM.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
189651SAndreas.Sandberg@ARM.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
199651SAndreas.Sandberg@ARM.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
209651SAndreas.Sandberg@ARM.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
219651SAndreas.Sandberg@ARM.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
229651SAndreas.Sandberg@ARM.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
239651SAndreas.Sandberg@ARM.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
249651SAndreas.Sandberg@ARM.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
259651SAndreas.Sandberg@ARM.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
269651SAndreas.Sandberg@ARM.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
279651SAndreas.Sandberg@ARM.com *
289651SAndreas.Sandberg@ARM.com * Authors: Erik Hallnor
299651SAndreas.Sandberg@ARM.com */
309651SAndreas.Sandberg@ARM.com
319651SAndreas.Sandberg@ARM.com/**
329651SAndreas.Sandberg@ARM.com * @file
339651SAndreas.Sandberg@ARM.com * Definition of BaseCache functions.
349651SAndreas.Sandberg@ARM.com */
359651SAndreas.Sandberg@ARM.com
369651SAndreas.Sandberg@ARM.com#include "cpu/base.hh"
379651SAndreas.Sandberg@ARM.com#include "cpu/smt.hh"
389651SAndreas.Sandberg@ARM.com#include "debug/Cache.hh"
399651SAndreas.Sandberg@ARM.com#include "mem/cache/base.hh"
4011793Sbrandon.potter@amd.com#include "mem/cache/mshr.hh"
419651SAndreas.Sandberg@ARM.com
429651SAndreas.Sandberg@ARM.comusing namespace std;
439651SAndreas.Sandberg@ARM.com
449651SAndreas.Sandberg@ARM.comBaseCache::CachePort::CachePort(const std::string &_name, BaseCache *_cache,
459651SAndreas.Sandberg@ARM.com                                const std::string &_label)
469651SAndreas.Sandberg@ARM.com    : SimpleTimingPort(_name, _cache), cache(_cache),
479651SAndreas.Sandberg@ARM.com      label(_label), otherPort(NULL),
489651SAndreas.Sandberg@ARM.com      blocked(false), mustSendRetry(false)
499651SAndreas.Sandberg@ARM.com{
509651SAndreas.Sandberg@ARM.com}
519651SAndreas.Sandberg@ARM.com
529651SAndreas.Sandberg@ARM.com
5312334Sgabeblack@google.comBaseCache::BaseCache(const Params *p)
549651SAndreas.Sandberg@ARM.com    : MemObject(p),
559651SAndreas.Sandberg@ARM.com      mshrQueue("MSHRs", p->mshrs, 4, MSHRQueue_MSHRs),
569651SAndreas.Sandberg@ARM.com      writeBuffer("write buffer", p->write_buffers, p->mshrs+1000,
579651SAndreas.Sandberg@ARM.com                  MSHRQueue_WriteBuffer),
589651SAndreas.Sandberg@ARM.com      blkSize(p->block_size),
599651SAndreas.Sandberg@ARM.com      hitLatency(p->latency),
609651SAndreas.Sandberg@ARM.com      numTarget(p->tgts_per_mshr),
619651SAndreas.Sandberg@ARM.com      forwardSnoops(p->forward_snoops),
629651SAndreas.Sandberg@ARM.com      isTopLevel(p->is_top_level),
639651SAndreas.Sandberg@ARM.com      blocked(0),
649651SAndreas.Sandberg@ARM.com      noTargetMSHR(NULL),
659651SAndreas.Sandberg@ARM.com      missCount(p->max_miss_count),
669651SAndreas.Sandberg@ARM.com      drainEvent(NULL),
679651SAndreas.Sandberg@ARM.com      addrRange(p->addr_range),
689651SAndreas.Sandberg@ARM.com      _numCpus(p->num_cpus)
699651SAndreas.Sandberg@ARM.com{
709651SAndreas.Sandberg@ARM.com}
719651SAndreas.Sandberg@ARM.com
729651SAndreas.Sandberg@ARM.comvoid
739651SAndreas.Sandberg@ARM.comBaseCache::CachePort::recvStatusChange(Port::Status status)
749651SAndreas.Sandberg@ARM.com{
759651SAndreas.Sandberg@ARM.com    if (status == Port::RangeChange) {
769651SAndreas.Sandberg@ARM.com        otherPort->sendStatusChange(Port::RangeChange);
779651SAndreas.Sandberg@ARM.com    }
789651SAndreas.Sandberg@ARM.com}
799651SAndreas.Sandberg@ARM.com
809651SAndreas.Sandberg@ARM.com
819651SAndreas.Sandberg@ARM.combool
829651SAndreas.Sandberg@ARM.comBaseCache::CachePort::checkFunctional(PacketPtr pkt)
839651SAndreas.Sandberg@ARM.com{
849651SAndreas.Sandberg@ARM.com    pkt->pushLabel(label);
859651SAndreas.Sandberg@ARM.com    bool done = SimpleTimingPort::checkFunctional(pkt);
869651SAndreas.Sandberg@ARM.com    pkt->popLabel();
879651SAndreas.Sandberg@ARM.com    return done;
889651SAndreas.Sandberg@ARM.com}
899651SAndreas.Sandberg@ARM.com
909651SAndreas.Sandberg@ARM.com
919651SAndreas.Sandberg@ARM.comunsigned
929651SAndreas.Sandberg@ARM.comBaseCache::CachePort::deviceBlockSize() const
939651SAndreas.Sandberg@ARM.com{
949651SAndreas.Sandberg@ARM.com    return cache->getBlockSize();
959651SAndreas.Sandberg@ARM.com}
969651SAndreas.Sandberg@ARM.com
979651SAndreas.Sandberg@ARM.com
989651SAndreas.Sandberg@ARM.combool
999651SAndreas.Sandberg@ARM.comBaseCache::CachePort::recvRetryCommon()
1009651SAndreas.Sandberg@ARM.com{
1019651SAndreas.Sandberg@ARM.com    assert(waitingOnRetry);
1029651SAndreas.Sandberg@ARM.com    waitingOnRetry = false;
1039651SAndreas.Sandberg@ARM.com    return false;
1049651SAndreas.Sandberg@ARM.com}
1059651SAndreas.Sandberg@ARM.com
1069651SAndreas.Sandberg@ARM.com
1079651SAndreas.Sandberg@ARM.comvoid
1089651SAndreas.Sandberg@ARM.comBaseCache::CachePort::setBlocked()
1099651SAndreas.Sandberg@ARM.com{
1109651SAndreas.Sandberg@ARM.com    assert(!blocked);
1119651SAndreas.Sandberg@ARM.com    DPRINTF(Cache, "Cache Blocking\n");
1129651SAndreas.Sandberg@ARM.com    blocked = true;
1139651SAndreas.Sandberg@ARM.com    //Clear the retry flag
1149651SAndreas.Sandberg@ARM.com    mustSendRetry = false;
1159651SAndreas.Sandberg@ARM.com}
1169651SAndreas.Sandberg@ARM.com
1179651SAndreas.Sandberg@ARM.comvoid
1189651SAndreas.Sandberg@ARM.comBaseCache::CachePort::clearBlocked()
1199651SAndreas.Sandberg@ARM.com{
1209651SAndreas.Sandberg@ARM.com    assert(blocked);
1219651SAndreas.Sandberg@ARM.com    DPRINTF(Cache, "Cache Unblocking\n");
1229651SAndreas.Sandberg@ARM.com    blocked = false;
1239651SAndreas.Sandberg@ARM.com    if (mustSendRetry)
1249651SAndreas.Sandberg@ARM.com    {
1259651SAndreas.Sandberg@ARM.com        DPRINTF(Cache, "Cache Sending Retry\n");
1269651SAndreas.Sandberg@ARM.com        mustSendRetry = false;
1279651SAndreas.Sandberg@ARM.com        SendRetryEvent *ev = new SendRetryEvent(this, true);
1289651SAndreas.Sandberg@ARM.com        // @TODO: need to find a better time (next bus cycle?)
1299651SAndreas.Sandberg@ARM.com        schedule(ev, curTick() + 1);
1309651SAndreas.Sandberg@ARM.com    }
1319651SAndreas.Sandberg@ARM.com}
1329651SAndreas.Sandberg@ARM.com
1339651SAndreas.Sandberg@ARM.com
1349651SAndreas.Sandberg@ARM.comvoid
1359651SAndreas.Sandberg@ARM.comBaseCache::init()
1369651SAndreas.Sandberg@ARM.com{
1379651SAndreas.Sandberg@ARM.com    if (!cpuSidePort || !memSidePort)
1389651SAndreas.Sandberg@ARM.com        panic("Cache not hooked up on both sides\n");
1399651SAndreas.Sandberg@ARM.com    cpuSidePort->sendStatusChange(Port::RangeChange);
1409651SAndreas.Sandberg@ARM.com}
1419651SAndreas.Sandberg@ARM.com
1429651SAndreas.Sandberg@ARM.com
1439651SAndreas.Sandberg@ARM.comvoid
1449651SAndreas.Sandberg@ARM.comBaseCache::regStats()
1459651SAndreas.Sandberg@ARM.com{
1469651SAndreas.Sandberg@ARM.com    using namespace Stats;
1479651SAndreas.Sandberg@ARM.com
1489651SAndreas.Sandberg@ARM.com    // Hit statistics
1499651SAndreas.Sandberg@ARM.com    for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
1509651SAndreas.Sandberg@ARM.com        MemCmd cmd(access_idx);
1519651SAndreas.Sandberg@ARM.com        const string &cstr = cmd.toString();
1529651SAndreas.Sandberg@ARM.com
1539651SAndreas.Sandberg@ARM.com        hits[access_idx]
1549651SAndreas.Sandberg@ARM.com#if FULL_SYSTEM
1559651SAndreas.Sandberg@ARM.com            .init(_numCpus + 1)
1569651SAndreas.Sandberg@ARM.com#else
1579651SAndreas.Sandberg@ARM.com            .init(_numCpus)
1589651SAndreas.Sandberg@ARM.com#endif
1599651SAndreas.Sandberg@ARM.com            .name(name() + "." + cstr + "_hits")
1609651SAndreas.Sandberg@ARM.com            .desc("number of " + cstr + " hits")
1619651SAndreas.Sandberg@ARM.com            .flags(total | nozero | nonan)
1629651SAndreas.Sandberg@ARM.com            ;
1639651SAndreas.Sandberg@ARM.com    }
1649651SAndreas.Sandberg@ARM.com
1659651SAndreas.Sandberg@ARM.com// These macros make it easier to sum the right subset of commands and
1669651SAndreas.Sandberg@ARM.com// to change the subset of commands that are considered "demand" vs
1679651SAndreas.Sandberg@ARM.com// "non-demand"
1689651SAndreas.Sandberg@ARM.com#define SUM_DEMAND(s) \
1699651SAndreas.Sandberg@ARM.com    (s[MemCmd::ReadReq] + s[MemCmd::WriteReq] + s[MemCmd::ReadExReq])
1709651SAndreas.Sandberg@ARM.com
1719651SAndreas.Sandberg@ARM.com// should writebacks be included here?  prior code was inconsistent...
17213787Sgambordr@oregonstate.edu#define SUM_NON_DEMAND(s) \
17313787Sgambordr@oregonstate.edu    (s[MemCmd::SoftPFReq] + s[MemCmd::HardPFReq])
17413787Sgambordr@oregonstate.edu
17513787Sgambordr@oregonstate.edu    demandHits
17613787Sgambordr@oregonstate.edu        .name(name() + ".demand_hits")
17713787Sgambordr@oregonstate.edu        .desc("number of demand (read+write) hits")
17813787Sgambordr@oregonstate.edu        .flags(total)
17913787Sgambordr@oregonstate.edu        ;
18013787Sgambordr@oregonstate.edu    demandHits = SUM_DEMAND(hits);
18113787Sgambordr@oregonstate.edu
18213787Sgambordr@oregonstate.edu    overallHits
18313787Sgambordr@oregonstate.edu        .name(name() + ".overall_hits")
1849651SAndreas.Sandberg@ARM.com        .desc("number of overall hits")
1859651SAndreas.Sandberg@ARM.com        .flags(total)
1869651SAndreas.Sandberg@ARM.com        ;
1879651SAndreas.Sandberg@ARM.com    overallHits = demandHits + SUM_NON_DEMAND(hits);
1889651SAndreas.Sandberg@ARM.com
1899651SAndreas.Sandberg@ARM.com    // Miss statistics
1909651SAndreas.Sandberg@ARM.com    for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
1919651SAndreas.Sandberg@ARM.com        MemCmd cmd(access_idx);
1929651SAndreas.Sandberg@ARM.com        const string &cstr = cmd.toString();
1939651SAndreas.Sandberg@ARM.com
1949651SAndreas.Sandberg@ARM.com        misses[access_idx]
1959651SAndreas.Sandberg@ARM.com#if FULL_SYSTEM
1969651SAndreas.Sandberg@ARM.com            .init(_numCpus + 1)
1979651SAndreas.Sandberg@ARM.com#else
1989651SAndreas.Sandberg@ARM.com            .init(_numCpus)
1999651SAndreas.Sandberg@ARM.com#endif
2009651SAndreas.Sandberg@ARM.com            .name(name() + "." + cstr + "_misses")
2019651SAndreas.Sandberg@ARM.com            .desc("number of " + cstr + " misses")
2029651SAndreas.Sandberg@ARM.com            .flags(total | nozero | nonan)
2039651SAndreas.Sandberg@ARM.com            ;
2049651SAndreas.Sandberg@ARM.com    }
2059651SAndreas.Sandberg@ARM.com
2069651SAndreas.Sandberg@ARM.com    demandMisses
2079651SAndreas.Sandberg@ARM.com        .name(name() + ".demand_misses")
2089651SAndreas.Sandberg@ARM.com        .desc("number of demand (read+write) misses")
2099651SAndreas.Sandberg@ARM.com        .flags(total)
2109651SAndreas.Sandberg@ARM.com        ;
2119651SAndreas.Sandberg@ARM.com    demandMisses = SUM_DEMAND(misses);
2129651SAndreas.Sandberg@ARM.com
2139651SAndreas.Sandberg@ARM.com    overallMisses
2149651SAndreas.Sandberg@ARM.com        .name(name() + ".overall_misses")
2159651SAndreas.Sandberg@ARM.com        .desc("number of overall misses")
2169651SAndreas.Sandberg@ARM.com        .flags(total)
2179651SAndreas.Sandberg@ARM.com        ;
2189651SAndreas.Sandberg@ARM.com    overallMisses = demandMisses + SUM_NON_DEMAND(misses);
2199651SAndreas.Sandberg@ARM.com
2209651SAndreas.Sandberg@ARM.com    // Miss latency statistics
2219651SAndreas.Sandberg@ARM.com    for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
2229651SAndreas.Sandberg@ARM.com        MemCmd cmd(access_idx);
2239651SAndreas.Sandberg@ARM.com        const string &cstr = cmd.toString();
2249651SAndreas.Sandberg@ARM.com
2259651SAndreas.Sandberg@ARM.com        missLatency[access_idx]
2269651SAndreas.Sandberg@ARM.com            .init(maxThreadsPerCPU)
2279651SAndreas.Sandberg@ARM.com            .name(name() + "." + cstr + "_miss_latency")
2289651SAndreas.Sandberg@ARM.com            .desc("number of " + cstr + " miss cycles")
2299651SAndreas.Sandberg@ARM.com            .flags(total | nozero | nonan)
2309651SAndreas.Sandberg@ARM.com            ;
2319651SAndreas.Sandberg@ARM.com    }
2329651SAndreas.Sandberg@ARM.com
2339651SAndreas.Sandberg@ARM.com    demandMissLatency
2349651SAndreas.Sandberg@ARM.com        .name(name() + ".demand_miss_latency")
2359651SAndreas.Sandberg@ARM.com        .desc("number of demand (read+write) miss cycles")
2369651SAndreas.Sandberg@ARM.com        .flags(total)
2379651SAndreas.Sandberg@ARM.com        ;
2389651SAndreas.Sandberg@ARM.com    demandMissLatency = SUM_DEMAND(missLatency);
2399651SAndreas.Sandberg@ARM.com
2409651SAndreas.Sandberg@ARM.com    overallMissLatency
2419651SAndreas.Sandberg@ARM.com        .name(name() + ".overall_miss_latency")
2429651SAndreas.Sandberg@ARM.com        .desc("number of overall miss cycles")
2439651SAndreas.Sandberg@ARM.com        .flags(total)
2449651SAndreas.Sandberg@ARM.com        ;
2459651SAndreas.Sandberg@ARM.com    overallMissLatency = demandMissLatency + SUM_NON_DEMAND(missLatency);
2469651SAndreas.Sandberg@ARM.com
2479651SAndreas.Sandberg@ARM.com    // access formulas
2489651SAndreas.Sandberg@ARM.com    for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
2499651SAndreas.Sandberg@ARM.com        MemCmd cmd(access_idx);
2509651SAndreas.Sandberg@ARM.com        const string &cstr = cmd.toString();
2519651SAndreas.Sandberg@ARM.com
2529651SAndreas.Sandberg@ARM.com        accesses[access_idx]
2539651SAndreas.Sandberg@ARM.com            .name(name() + "." + cstr + "_accesses")
2549651SAndreas.Sandberg@ARM.com            .desc("number of " + cstr + " accesses(hits+misses)")
2559651SAndreas.Sandberg@ARM.com            .flags(total | nozero | nonan)
25611321Ssteve.reinhardt@amd.com            ;
2579651SAndreas.Sandberg@ARM.com
258        accesses[access_idx] = hits[access_idx] + misses[access_idx];
259    }
260
261    demandAccesses
262        .name(name() + ".demand_accesses")
263        .desc("number of demand (read+write) accesses")
264        .flags(total)
265        ;
266    demandAccesses = demandHits + demandMisses;
267
268    overallAccesses
269        .name(name() + ".overall_accesses")
270        .desc("number of overall (read+write) accesses")
271        .flags(total)
272        ;
273    overallAccesses = overallHits + overallMisses;
274
275    // miss rate formulas
276    for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
277        MemCmd cmd(access_idx);
278        const string &cstr = cmd.toString();
279
280        missRate[access_idx]
281            .name(name() + "." + cstr + "_miss_rate")
282            .desc("miss rate for " + cstr + " accesses")
283            .flags(total | nozero | nonan)
284            ;
285
286        missRate[access_idx] = misses[access_idx] / accesses[access_idx];
287    }
288
289    demandMissRate
290        .name(name() + ".demand_miss_rate")
291        .desc("miss rate for demand accesses")
292        .flags(total)
293        ;
294    demandMissRate = demandMisses / demandAccesses;
295
296    overallMissRate
297        .name(name() + ".overall_miss_rate")
298        .desc("miss rate for overall accesses")
299        .flags(total)
300        ;
301    overallMissRate = overallMisses / overallAccesses;
302
303    // miss latency formulas
304    for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
305        MemCmd cmd(access_idx);
306        const string &cstr = cmd.toString();
307
308        avgMissLatency[access_idx]
309            .name(name() + "." + cstr + "_avg_miss_latency")
310            .desc("average " + cstr + " miss latency")
311            .flags(total | nozero | nonan)
312            ;
313
314        avgMissLatency[access_idx] =
315            missLatency[access_idx] / misses[access_idx];
316    }
317
318    demandAvgMissLatency
319        .name(name() + ".demand_avg_miss_latency")
320        .desc("average overall miss latency")
321        .flags(total)
322        ;
323    demandAvgMissLatency = demandMissLatency / demandMisses;
324
325    overallAvgMissLatency
326        .name(name() + ".overall_avg_miss_latency")
327        .desc("average overall miss latency")
328        .flags(total)
329        ;
330    overallAvgMissLatency = overallMissLatency / overallMisses;
331
332    blocked_cycles.init(NUM_BLOCKED_CAUSES);
333    blocked_cycles
334        .name(name() + ".blocked_cycles")
335        .desc("number of cycles access was blocked")
336        .subname(Blocked_NoMSHRs, "no_mshrs")
337        .subname(Blocked_NoTargets, "no_targets")
338        ;
339
340
341    blocked_causes.init(NUM_BLOCKED_CAUSES);
342    blocked_causes
343        .name(name() + ".blocked")
344        .desc("number of cycles access was blocked")
345        .subname(Blocked_NoMSHRs, "no_mshrs")
346        .subname(Blocked_NoTargets, "no_targets")
347        ;
348
349    avg_blocked
350        .name(name() + ".avg_blocked_cycles")
351        .desc("average number of cycles each access was blocked")
352        .subname(Blocked_NoMSHRs, "no_mshrs")
353        .subname(Blocked_NoTargets, "no_targets")
354        ;
355
356    avg_blocked = blocked_cycles / blocked_causes;
357
358    fastWrites
359        .name(name() + ".fast_writes")
360        .desc("number of fast writes performed")
361        ;
362
363    cacheCopies
364        .name(name() + ".cache_copies")
365        .desc("number of cache copies performed")
366        ;
367
368    writebacks
369        .init(maxThreadsPerCPU)
370        .name(name() + ".writebacks")
371        .desc("number of writebacks")
372        .flags(total)
373        ;
374
375    // MSHR statistics
376    // MSHR hit statistics
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        mshr_hits[access_idx]
382            .init(maxThreadsPerCPU)
383            .name(name() + "." + cstr + "_mshr_hits")
384            .desc("number of " + cstr + " MSHR hits")
385            .flags(total | nozero | nonan)
386            ;
387    }
388
389    demandMshrHits
390        .name(name() + ".demand_mshr_hits")
391        .desc("number of demand (read+write) MSHR hits")
392        .flags(total)
393        ;
394    demandMshrHits = SUM_DEMAND(mshr_hits);
395
396    overallMshrHits
397        .name(name() + ".overall_mshr_hits")
398        .desc("number of overall MSHR hits")
399        .flags(total)
400        ;
401    overallMshrHits = demandMshrHits + SUM_NON_DEMAND(mshr_hits);
402
403    // MSHR miss statistics
404    for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
405        MemCmd cmd(access_idx);
406        const string &cstr = cmd.toString();
407
408        mshr_misses[access_idx]
409            .init(maxThreadsPerCPU)
410            .name(name() + "." + cstr + "_mshr_misses")
411            .desc("number of " + cstr + " MSHR misses")
412            .flags(total | nozero | nonan)
413            ;
414    }
415
416    demandMshrMisses
417        .name(name() + ".demand_mshr_misses")
418        .desc("number of demand (read+write) MSHR misses")
419        .flags(total)
420        ;
421    demandMshrMisses = SUM_DEMAND(mshr_misses);
422
423    overallMshrMisses
424        .name(name() + ".overall_mshr_misses")
425        .desc("number of overall MSHR misses")
426        .flags(total)
427        ;
428    overallMshrMisses = demandMshrMisses + SUM_NON_DEMAND(mshr_misses);
429
430    // MSHR miss latency statistics
431    for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
432        MemCmd cmd(access_idx);
433        const string &cstr = cmd.toString();
434
435        mshr_miss_latency[access_idx]
436            .init(maxThreadsPerCPU)
437            .name(name() + "." + cstr + "_mshr_miss_latency")
438            .desc("number of " + cstr + " MSHR miss cycles")
439            .flags(total | nozero | nonan)
440            ;
441    }
442
443    demandMshrMissLatency
444        .name(name() + ".demand_mshr_miss_latency")
445        .desc("number of demand (read+write) MSHR miss cycles")
446        .flags(total)
447        ;
448    demandMshrMissLatency = SUM_DEMAND(mshr_miss_latency);
449
450    overallMshrMissLatency
451        .name(name() + ".overall_mshr_miss_latency")
452        .desc("number of overall MSHR miss cycles")
453        .flags(total)
454        ;
455    overallMshrMissLatency =
456        demandMshrMissLatency + SUM_NON_DEMAND(mshr_miss_latency);
457
458    // MSHR uncacheable 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_uncacheable[access_idx]
464            .init(maxThreadsPerCPU)
465            .name(name() + "." + cstr + "_mshr_uncacheable")
466            .desc("number of " + cstr + " MSHR uncacheable")
467            .flags(total | nozero | nonan)
468            ;
469    }
470
471    overallMshrUncacheable
472        .name(name() + ".overall_mshr_uncacheable_misses")
473        .desc("number of overall MSHR uncacheable misses")
474        .flags(total)
475        ;
476    overallMshrUncacheable =
477        SUM_DEMAND(mshr_uncacheable) + SUM_NON_DEMAND(mshr_uncacheable);
478
479    // MSHR miss latency statistics
480    for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
481        MemCmd cmd(access_idx);
482        const string &cstr = cmd.toString();
483
484        mshr_uncacheable_lat[access_idx]
485            .init(maxThreadsPerCPU)
486            .name(name() + "." + cstr + "_mshr_uncacheable_latency")
487            .desc("number of " + cstr + " MSHR uncacheable cycles")
488            .flags(total | nozero | nonan)
489            ;
490    }
491
492    overallMshrUncacheableLatency
493        .name(name() + ".overall_mshr_uncacheable_latency")
494        .desc("number of overall MSHR uncacheable cycles")
495        .flags(total)
496        ;
497    overallMshrUncacheableLatency =
498        SUM_DEMAND(mshr_uncacheable_lat) +
499        SUM_NON_DEMAND(mshr_uncacheable_lat);
500
501#if 0
502    // MSHR access formulas
503    for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
504        MemCmd cmd(access_idx);
505        const string &cstr = cmd.toString();
506
507        mshrAccesses[access_idx]
508            .name(name() + "." + cstr + "_mshr_accesses")
509            .desc("number of " + cstr + " mshr accesses(hits+misses)")
510            .flags(total | nozero | nonan)
511            ;
512        mshrAccesses[access_idx] =
513            mshr_hits[access_idx] + mshr_misses[access_idx]
514            + mshr_uncacheable[access_idx];
515    }
516
517    demandMshrAccesses
518        .name(name() + ".demand_mshr_accesses")
519        .desc("number of demand (read+write) mshr accesses")
520        .flags(total | nozero | nonan)
521        ;
522    demandMshrAccesses = demandMshrHits + demandMshrMisses;
523
524    overallMshrAccesses
525        .name(name() + ".overall_mshr_accesses")
526        .desc("number of overall (read+write) mshr accesses")
527        .flags(total | nozero | nonan)
528        ;
529    overallMshrAccesses = overallMshrHits + overallMshrMisses
530        + overallMshrUncacheable;
531#endif
532
533    // MSHR miss rate formulas
534    for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
535        MemCmd cmd(access_idx);
536        const string &cstr = cmd.toString();
537
538        mshrMissRate[access_idx]
539            .name(name() + "." + cstr + "_mshr_miss_rate")
540            .desc("mshr miss rate for " + cstr + " accesses")
541            .flags(total | nozero | nonan)
542            ;
543
544        mshrMissRate[access_idx] =
545            mshr_misses[access_idx] / accesses[access_idx];
546    }
547
548    demandMshrMissRate
549        .name(name() + ".demand_mshr_miss_rate")
550        .desc("mshr miss rate for demand accesses")
551        .flags(total)
552        ;
553    demandMshrMissRate = demandMshrMisses / demandAccesses;
554
555    overallMshrMissRate
556        .name(name() + ".overall_mshr_miss_rate")
557        .desc("mshr miss rate for overall accesses")
558        .flags(total)
559        ;
560    overallMshrMissRate = overallMshrMisses / overallAccesses;
561
562    // mshrMiss latency formulas
563    for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
564        MemCmd cmd(access_idx);
565        const string &cstr = cmd.toString();
566
567        avgMshrMissLatency[access_idx]
568            .name(name() + "." + cstr + "_avg_mshr_miss_latency")
569            .desc("average " + cstr + " mshr miss latency")
570            .flags(total | nozero | nonan)
571            ;
572
573        avgMshrMissLatency[access_idx] =
574            mshr_miss_latency[access_idx] / mshr_misses[access_idx];
575    }
576
577    demandAvgMshrMissLatency
578        .name(name() + ".demand_avg_mshr_miss_latency")
579        .desc("average overall mshr miss latency")
580        .flags(total)
581        ;
582    demandAvgMshrMissLatency = demandMshrMissLatency / demandMshrMisses;
583
584    overallAvgMshrMissLatency
585        .name(name() + ".overall_avg_mshr_miss_latency")
586        .desc("average overall mshr miss latency")
587        .flags(total)
588        ;
589    overallAvgMshrMissLatency = overallMshrMissLatency / overallMshrMisses;
590
591    // mshrUncacheable latency formulas
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        avgMshrUncacheableLatency[access_idx]
597            .name(name() + "." + cstr + "_avg_mshr_uncacheable_latency")
598            .desc("average " + cstr + " mshr uncacheable latency")
599            .flags(total | nozero | nonan)
600            ;
601
602        avgMshrUncacheableLatency[access_idx] =
603            mshr_uncacheable_lat[access_idx] / mshr_uncacheable[access_idx];
604    }
605
606    overallAvgMshrUncacheableLatency
607        .name(name() + ".overall_avg_mshr_uncacheable_latency")
608        .desc("average overall mshr uncacheable latency")
609        .flags(total)
610        ;
611    overallAvgMshrUncacheableLatency = overallMshrUncacheableLatency / overallMshrUncacheable;
612
613    mshr_cap_events
614        .init(maxThreadsPerCPU)
615        .name(name() + ".mshr_cap_events")
616        .desc("number of times MSHR cap was activated")
617        .flags(total)
618        ;
619
620    //software prefetching stats
621    soft_prefetch_mshr_full
622        .init(maxThreadsPerCPU)
623        .name(name() + ".soft_prefetch_mshr_full")
624        .desc("number of mshr full events for SW prefetching instrutions")
625        .flags(total)
626        ;
627
628    mshr_no_allocate_misses
629        .name(name() +".no_allocate_misses")
630        .desc("Number of misses that were no-allocate")
631        ;
632
633}
634
635unsigned int
636BaseCache::drain(Event *de)
637{
638    int count = memSidePort->drain(de) + cpuSidePort->drain(de);
639
640    // Set status
641    if (count != 0) {
642        drainEvent = de;
643
644        changeState(SimObject::Draining);
645        return count;
646    }
647
648    changeState(SimObject::Drained);
649    return 0;
650}
651