base.cc revision 10714
15390SN/A/*
25390SN/A * Copyright (c) 2012-2013 ARM Limited
35390SN/A * All rights reserved.
45390SN/A *
55390SN/A * The license below extends only to copyright in the software and shall
65390SN/A * not be construed as granting a license to any other intellectual
75390SN/A * property including but not limited to intellectual property relating
85390SN/A * to a hardware implementation of the functionality of the software
95390SN/A * licensed hereunder.  You may use the software subject to the license
105390SN/A * terms below provided that you ensure that this notice is replicated
115390SN/A * unmodified and in its entirety in all distributions of the software,
125390SN/A * modified or unmodified, in source code or in binary form.
135390SN/A *
145390SN/A * Copyright (c) 2003-2005 The Regents of The University of Michigan
155390SN/A * All rights reserved.
165390SN/A *
175390SN/A * Redistribution and use in source and binary forms, with or without
185390SN/A * modification, are permitted provided that the following conditions are
195390SN/A * met: redistributions of source code must retain the above copyright
205390SN/A * notice, this list of conditions and the following disclaimer;
215390SN/A * redistributions in binary form must reproduce the above copyright
225390SN/A * notice, this list of conditions and the following disclaimer in the
235390SN/A * documentation and/or other materials provided with the distribution;
245390SN/A * neither the name of the copyright holders nor the names of its
255390SN/A * contributors may be used to endorse or promote products derived from
265390SN/A * this software without specific prior written permission.
275390SN/A *
285390SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
295390SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
305390SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
315631Sgblack@eecs.umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
328232Snate@binkert.org * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
335657Sgblack@eecs.umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
345630Sgblack@eecs.umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
355698Snate@binkert.org * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
365698Snate@binkert.org * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
375390SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
385657Sgblack@eecs.umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
395657Sgblack@eecs.umich.edu *
405827Sgblack@eecs.umich.edu * Authors: Erik Hallnor
415657Sgblack@eecs.umich.edu */
425688Sgblack@eecs.umich.edu
435657Sgblack@eecs.umich.edu/**
445827Sgblack@eecs.umich.edu * @file
455827Sgblack@eecs.umich.edu * Definition of BaseCache functions.
465657Sgblack@eecs.umich.edu */
475657Sgblack@eecs.umich.edu
485657Sgblack@eecs.umich.edu#include "debug/Cache.hh"
495390SN/A#include "debug/Drain.hh"
505390SN/A#include "mem/cache/tags/fa_lru.hh"
515390SN/A#include "mem/cache/tags/lru.hh"
525631Sgblack@eecs.umich.edu#include "mem/cache/tags/random_repl.hh"
535631Sgblack@eecs.umich.edu#include "mem/cache/base.hh"
545631Sgblack@eecs.umich.edu#include "mem/cache/cache.hh"
555631Sgblack@eecs.umich.edu#include "mem/cache/mshr.hh"
565631Sgblack@eecs.umich.edu#include "sim/full_system.hh"
575631Sgblack@eecs.umich.edu
585631Sgblack@eecs.umich.eduusing namespace std;
595631Sgblack@eecs.umich.edu
605631Sgblack@eecs.umich.eduBaseCache::CacheSlavePort::CacheSlavePort(const std::string &_name,
615631Sgblack@eecs.umich.edu                                          BaseCache *_cache,
625631Sgblack@eecs.umich.edu                                          const std::string &_label)
635631Sgblack@eecs.umich.edu    : QueuedSlavePort(_name, _cache, queue), queue(*_cache, *this, _label),
645631Sgblack@eecs.umich.edu      blocked(false), mustSendRetry(false), sendRetryEvent(this)
655631Sgblack@eecs.umich.edu{
665631Sgblack@eecs.umich.edu}
675631Sgblack@eecs.umich.edu
685631Sgblack@eecs.umich.eduBaseCache::BaseCache(const Params *p)
695898Sgblack@eecs.umich.edu    : MemObject(p),
705630Sgblack@eecs.umich.edu      cpuSidePort(nullptr), memSidePort(nullptr),
715390SN/A      mshrQueue("MSHRs", p->mshrs, 4, p->demand_mshr_reserve, MSHRQueue_MSHRs),
725390SN/A      writeBuffer("write buffer", p->write_buffers, p->mshrs+1000, 0,
735390SN/A                  MSHRQueue_WriteBuffer),
745390SN/A      blkSize(p->system->cacheLineSize()),
755390SN/A      lookupLatency(p->hit_latency),
765631Sgblack@eecs.umich.edu      forwardLatency(p->hit_latency),
775631Sgblack@eecs.umich.edu      fillLatency(p->response_latency),
785631Sgblack@eecs.umich.edu      responseLatency(p->response_latency),
795631Sgblack@eecs.umich.edu      numTarget(p->tgts_per_mshr),
805631Sgblack@eecs.umich.edu      forwardSnoops(p->forward_snoops),
815631Sgblack@eecs.umich.edu      isTopLevel(p->is_top_level),
825631Sgblack@eecs.umich.edu      blocked(0),
835631Sgblack@eecs.umich.edu      order(0),
845631Sgblack@eecs.umich.edu      noTargetMSHR(NULL),
855631Sgblack@eecs.umich.edu      missCount(p->max_miss_count),
865631Sgblack@eecs.umich.edu      addrRanges(p->addr_ranges.begin(), p->addr_ranges.end()),
875631Sgblack@eecs.umich.edu      system(p->system)
885631Sgblack@eecs.umich.edu{
895631Sgblack@eecs.umich.edu}
905688Sgblack@eecs.umich.edu
915688Sgblack@eecs.umich.eduvoid
925688Sgblack@eecs.umich.eduBaseCache::CacheSlavePort::setBlocked()
935631Sgblack@eecs.umich.edu{
945631Sgblack@eecs.umich.edu    assert(!blocked);
955631Sgblack@eecs.umich.edu    DPRINTF(CachePort, "Port is blocking new requests\n");
965631Sgblack@eecs.umich.edu    blocked = true;
975631Sgblack@eecs.umich.edu    // if we already scheduled a retry in this cycle, but it has not yet
985631Sgblack@eecs.umich.edu    // happened, cancel it
995631Sgblack@eecs.umich.edu    if (sendRetryEvent.scheduled()) {
1005631Sgblack@eecs.umich.edu        owner.deschedule(sendRetryEvent);
1015631Sgblack@eecs.umich.edu        DPRINTF(CachePort, "Port descheduled retry\n");
1025631Sgblack@eecs.umich.edu        mustSendRetry = true;
1035687Sgblack@eecs.umich.edu    }
1045687Sgblack@eecs.umich.edu}
1055687Sgblack@eecs.umich.edu
1065687Sgblack@eecs.umich.eduvoid
1075687Sgblack@eecs.umich.eduBaseCache::CacheSlavePort::clearBlocked()
1085687Sgblack@eecs.umich.edu{
1095631Sgblack@eecs.umich.edu    assert(blocked);
1105631Sgblack@eecs.umich.edu    DPRINTF(CachePort, "Port is accepting new requests\n");
1115631Sgblack@eecs.umich.edu    blocked = false;
1125631Sgblack@eecs.umich.edu    if (mustSendRetry) {
1135631Sgblack@eecs.umich.edu        // @TODO: need to find a better time (next cycle?)
1145686Sgblack@eecs.umich.edu        owner.schedule(sendRetryEvent, curTick() + 1);
1155686Sgblack@eecs.umich.edu    }
1165686Sgblack@eecs.umich.edu}
1175686Sgblack@eecs.umich.edu
1185686Sgblack@eecs.umich.eduvoid
1195686Sgblack@eecs.umich.eduBaseCache::CacheSlavePort::processSendRetry()
1205631Sgblack@eecs.umich.edu{
1215631Sgblack@eecs.umich.edu    DPRINTF(CachePort, "Port is sending retry\n");
1225631Sgblack@eecs.umich.edu
1235631Sgblack@eecs.umich.edu    // reset the flag and call retry
1245631Sgblack@eecs.umich.edu    mustSendRetry = false;
1255631Sgblack@eecs.umich.edu    sendRetryReq();
1265631Sgblack@eecs.umich.edu}
1275631Sgblack@eecs.umich.edu
1285631Sgblack@eecs.umich.eduvoid
1295631Sgblack@eecs.umich.eduBaseCache::init()
1305631Sgblack@eecs.umich.edu{
1315631Sgblack@eecs.umich.edu    if (!cpuSidePort->isConnected() || !memSidePort->isConnected())
1325631Sgblack@eecs.umich.edu        fatal("Cache ports on %s are not connected\n", name());
1335631Sgblack@eecs.umich.edu    cpuSidePort->sendRangeChange();
1345631Sgblack@eecs.umich.edu}
1355631Sgblack@eecs.umich.edu
1365631Sgblack@eecs.umich.eduBaseMasterPort &
1375631Sgblack@eecs.umich.eduBaseCache::getMasterPort(const std::string &if_name, PortID idx)
1385631Sgblack@eecs.umich.edu{
1395631Sgblack@eecs.umich.edu    if (if_name == "mem_side") {
1405631Sgblack@eecs.umich.edu        return *memSidePort;
1415631Sgblack@eecs.umich.edu    }  else {
1425631Sgblack@eecs.umich.edu        return MemObject::getMasterPort(if_name, idx);
1435631Sgblack@eecs.umich.edu    }
1445631Sgblack@eecs.umich.edu}
1455631Sgblack@eecs.umich.edu
1465631Sgblack@eecs.umich.eduBaseSlavePort &
1475631Sgblack@eecs.umich.eduBaseCache::getSlavePort(const std::string &if_name, PortID idx)
1485631Sgblack@eecs.umich.edu{
1495631Sgblack@eecs.umich.edu    if (if_name == "cpu_side") {
1505631Sgblack@eecs.umich.edu        return *cpuSidePort;
1515631Sgblack@eecs.umich.edu    } else {
1525631Sgblack@eecs.umich.edu        return MemObject::getSlavePort(if_name, idx);
1535631Sgblack@eecs.umich.edu    }
1545631Sgblack@eecs.umich.edu}
1555631Sgblack@eecs.umich.edu
1565631Sgblack@eecs.umich.eduvoid
1575631Sgblack@eecs.umich.eduBaseCache::regStats()
1585631Sgblack@eecs.umich.edu{
1595656Sgblack@eecs.umich.edu    using namespace Stats;
1605631Sgblack@eecs.umich.edu
1615656Sgblack@eecs.umich.edu    // Hit statistics
1625631Sgblack@eecs.umich.edu    for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
1635631Sgblack@eecs.umich.edu        MemCmd cmd(access_idx);
1645631Sgblack@eecs.umich.edu        const string &cstr = cmd.toString();
1655632Sgblack@eecs.umich.edu
1665631Sgblack@eecs.umich.edu        hits[access_idx]
1675631Sgblack@eecs.umich.edu            .init(system->maxMasters())
1685631Sgblack@eecs.umich.edu            .name(name() + "." + cstr + "_hits")
1695631Sgblack@eecs.umich.edu            .desc("number of " + cstr + " hits")
1705631Sgblack@eecs.umich.edu            .flags(total | nozero | nonan)
1715634Sgblack@eecs.umich.edu            ;
1725631Sgblack@eecs.umich.edu        for (int i = 0; i < system->maxMasters(); i++) {
1735631Sgblack@eecs.umich.edu            hits[access_idx].subname(i, system->getMasterName(i));
1745631Sgblack@eecs.umich.edu        }
1755631Sgblack@eecs.umich.edu    }
1765631Sgblack@eecs.umich.edu
1775631Sgblack@eecs.umich.edu// These macros make it easier to sum the right subset of commands and
1785631Sgblack@eecs.umich.edu// to change the subset of commands that are considered "demand" vs
1795631Sgblack@eecs.umich.edu// "non-demand"
1805631Sgblack@eecs.umich.edu#define SUM_DEMAND(s) \
1815632Sgblack@eecs.umich.edu    (s[MemCmd::ReadReq] + s[MemCmd::WriteReq] + s[MemCmd::ReadExReq])
1825631Sgblack@eecs.umich.edu
1835631Sgblack@eecs.umich.edu// should writebacks be included here?  prior code was inconsistent...
1845632Sgblack@eecs.umich.edu#define SUM_NON_DEMAND(s) \
1855631Sgblack@eecs.umich.edu    (s[MemCmd::SoftPFReq] + s[MemCmd::HardPFReq])
1865631Sgblack@eecs.umich.edu
1875631Sgblack@eecs.umich.edu    demandHits
1885631Sgblack@eecs.umich.edu        .name(name() + ".demand_hits")
1895631Sgblack@eecs.umich.edu        .desc("number of demand (read+write) hits")
1905631Sgblack@eecs.umich.edu        .flags(total | nozero | nonan)
1915631Sgblack@eecs.umich.edu        ;
1925631Sgblack@eecs.umich.edu    demandHits = SUM_DEMAND(hits);
1935631Sgblack@eecs.umich.edu    for (int i = 0; i < system->maxMasters(); i++) {
1945631Sgblack@eecs.umich.edu        demandHits.subname(i, system->getMasterName(i));
1955631Sgblack@eecs.umich.edu    }
1965631Sgblack@eecs.umich.edu
1975631Sgblack@eecs.umich.edu    overallHits
1985631Sgblack@eecs.umich.edu        .name(name() + ".overall_hits")
1995631Sgblack@eecs.umich.edu        .desc("number of overall hits")
2005631Sgblack@eecs.umich.edu        .flags(total | nozero | nonan)
2015631Sgblack@eecs.umich.edu        ;
2025631Sgblack@eecs.umich.edu    overallHits = demandHits + SUM_NON_DEMAND(hits);
2035631Sgblack@eecs.umich.edu    for (int i = 0; i < system->maxMasters(); i++) {
2045631Sgblack@eecs.umich.edu        overallHits.subname(i, system->getMasterName(i));
2055688Sgblack@eecs.umich.edu    }
2065631Sgblack@eecs.umich.edu
2075688Sgblack@eecs.umich.edu    // Miss statistics
2085688Sgblack@eecs.umich.edu    for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
2095631Sgblack@eecs.umich.edu        MemCmd cmd(access_idx);
2105631Sgblack@eecs.umich.edu        const string &cstr = cmd.toString();
2115631Sgblack@eecs.umich.edu
2125631Sgblack@eecs.umich.edu        misses[access_idx]
2135631Sgblack@eecs.umich.edu            .init(system->maxMasters())
2145631Sgblack@eecs.umich.edu            .name(name() + "." + cstr + "_misses")
2155898Sgblack@eecs.umich.edu            .desc("number of " + cstr + " misses")
2165630Sgblack@eecs.umich.edu            .flags(total | nozero | nonan)
2175390SN/A            ;
2185630Sgblack@eecs.umich.edu        for (int i = 0; i < system->maxMasters(); i++) {
2195632Sgblack@eecs.umich.edu            misses[access_idx].subname(i, system->getMasterName(i));
2205686Sgblack@eecs.umich.edu        }
2215686Sgblack@eecs.umich.edu    }
2225686Sgblack@eecs.umich.edu
2235686Sgblack@eecs.umich.edu    demandMisses
2245686Sgblack@eecs.umich.edu        .name(name() + ".demand_misses")
2255686Sgblack@eecs.umich.edu        .desc("number of demand (read+write) misses")
2265686Sgblack@eecs.umich.edu        .flags(total | nozero | nonan)
2275686Sgblack@eecs.umich.edu        ;
2285686Sgblack@eecs.umich.edu    demandMisses = SUM_DEMAND(misses);
2295686Sgblack@eecs.umich.edu    for (int i = 0; i < system->maxMasters(); i++) {
2305686Sgblack@eecs.umich.edu        demandMisses.subname(i, system->getMasterName(i));
2315686Sgblack@eecs.umich.edu    }
2325686Sgblack@eecs.umich.edu
2335686Sgblack@eecs.umich.edu    overallMisses
2345686Sgblack@eecs.umich.edu        .name(name() + ".overall_misses")
2355827Sgblack@eecs.umich.edu        .desc("number of overall misses")
2365827Sgblack@eecs.umich.edu        .flags(total | nozero | nonan)
2375827Sgblack@eecs.umich.edu        ;
2385686Sgblack@eecs.umich.edu    overallMisses = demandMisses + SUM_NON_DEMAND(misses);
2395686Sgblack@eecs.umich.edu    for (int i = 0; i < system->maxMasters(); i++) {
2405686Sgblack@eecs.umich.edu        overallMisses.subname(i, system->getMasterName(i));
2415686Sgblack@eecs.umich.edu    }
2425686Sgblack@eecs.umich.edu
2435686Sgblack@eecs.umich.edu    // Miss latency statistics
2445686Sgblack@eecs.umich.edu    for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
2455686Sgblack@eecs.umich.edu        MemCmd cmd(access_idx);
2465632Sgblack@eecs.umich.edu        const string &cstr = cmd.toString();
2475632Sgblack@eecs.umich.edu
2485830Sgblack@eecs.umich.edu        missLatency[access_idx]
2495657Sgblack@eecs.umich.edu            .init(system->maxMasters())
2505657Sgblack@eecs.umich.edu            .name(name() + "." + cstr + "_miss_latency")
2515657Sgblack@eecs.umich.edu            .desc("number of " + cstr + " miss cycles")
2525632Sgblack@eecs.umich.edu            .flags(total | nozero | nonan)
2535632Sgblack@eecs.umich.edu            ;
2545634Sgblack@eecs.umich.edu        for (int i = 0; i < system->maxMasters(); i++) {
2555657Sgblack@eecs.umich.edu            missLatency[access_idx].subname(i, system->getMasterName(i));
2565686Sgblack@eecs.umich.edu        }
2575632Sgblack@eecs.umich.edu    }
2585632Sgblack@eecs.umich.edu
2595632Sgblack@eecs.umich.edu    demandMissLatency
2605827Sgblack@eecs.umich.edu        .name(name() + ".demand_miss_latency")
2615827Sgblack@eecs.umich.edu        .desc("number of demand (read+write) miss cycles")
2625827Sgblack@eecs.umich.edu        .flags(total | nozero | nonan)
2635830Sgblack@eecs.umich.edu        ;
2645827Sgblack@eecs.umich.edu    demandMissLatency = SUM_DEMAND(missLatency);
2655827Sgblack@eecs.umich.edu    for (int i = 0; i < system->maxMasters(); i++) {
2665827Sgblack@eecs.umich.edu        demandMissLatency.subname(i, system->getMasterName(i));
2675827Sgblack@eecs.umich.edu    }
2685827Sgblack@eecs.umich.edu
2695827Sgblack@eecs.umich.edu    overallMissLatency
2705827Sgblack@eecs.umich.edu        .name(name() + ".overall_miss_latency")
2715827Sgblack@eecs.umich.edu        .desc("number of overall miss cycles")
2725827Sgblack@eecs.umich.edu        .flags(total | nozero | nonan)
2735827Sgblack@eecs.umich.edu        ;
2745827Sgblack@eecs.umich.edu    overallMissLatency = demandMissLatency + SUM_NON_DEMAND(missLatency);
2755830Sgblack@eecs.umich.edu    for (int i = 0; i < system->maxMasters(); i++) {
2765827Sgblack@eecs.umich.edu        overallMissLatency.subname(i, system->getMasterName(i));
2775827Sgblack@eecs.umich.edu    }
2785827Sgblack@eecs.umich.edu
2795827Sgblack@eecs.umich.edu    // access formulas
2805827Sgblack@eecs.umich.edu    for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
2815827Sgblack@eecs.umich.edu        MemCmd cmd(access_idx);
2825657Sgblack@eecs.umich.edu        const string &cstr = cmd.toString();
2835657Sgblack@eecs.umich.edu
2845657Sgblack@eecs.umich.edu        accesses[access_idx]
2855657Sgblack@eecs.umich.edu            .name(name() + "." + cstr + "_accesses")
2865657Sgblack@eecs.umich.edu            .desc("number of " + cstr + " accesses(hits+misses)")
2875657Sgblack@eecs.umich.edu            .flags(total | nozero | nonan)
2885657Sgblack@eecs.umich.edu            ;
2895657Sgblack@eecs.umich.edu        accesses[access_idx] = hits[access_idx] + misses[access_idx];
2905657Sgblack@eecs.umich.edu
2915657Sgblack@eecs.umich.edu        for (int i = 0; i < system->maxMasters(); i++) {
2925657Sgblack@eecs.umich.edu            accesses[access_idx].subname(i, system->getMasterName(i));
2935657Sgblack@eecs.umich.edu        }
2945688Sgblack@eecs.umich.edu    }
2955688Sgblack@eecs.umich.edu
2965688Sgblack@eecs.umich.edu    demandAccesses
2975688Sgblack@eecs.umich.edu        .name(name() + ".demand_accesses")
2985688Sgblack@eecs.umich.edu        .desc("number of demand (read+write) accesses")
2995657Sgblack@eecs.umich.edu        .flags(total | nozero | nonan)
3005657Sgblack@eecs.umich.edu        ;
3015657Sgblack@eecs.umich.edu    demandAccesses = demandHits + demandMisses;
3025657Sgblack@eecs.umich.edu    for (int i = 0; i < system->maxMasters(); i++) {
3035657Sgblack@eecs.umich.edu        demandAccesses.subname(i, system->getMasterName(i));
3045657Sgblack@eecs.umich.edu    }
3055657Sgblack@eecs.umich.edu
3065657Sgblack@eecs.umich.edu    overallAccesses
3077903Shestness@cs.utexas.edu        .name(name() + ".overall_accesses")
3087903Shestness@cs.utexas.edu        .desc("number of overall (read+write) accesses")
3097903Shestness@cs.utexas.edu        .flags(total | nozero | nonan)
3107903Shestness@cs.utexas.edu        ;
3117903Shestness@cs.utexas.edu    overallAccesses = overallHits + overallMisses;
3127903Shestness@cs.utexas.edu    for (int i = 0; i < system->maxMasters(); i++) {
3137903Shestness@cs.utexas.edu        overallAccesses.subname(i, system->getMasterName(i));
3147903Shestness@cs.utexas.edu    }
3157903Shestness@cs.utexas.edu
3167903Shestness@cs.utexas.edu    // miss rate formulas
3177903Shestness@cs.utexas.edu    for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
3187903Shestness@cs.utexas.edu        MemCmd cmd(access_idx);
3197903Shestness@cs.utexas.edu        const string &cstr = cmd.toString();
3207903Shestness@cs.utexas.edu
3217903Shestness@cs.utexas.edu        missRate[access_idx]
3227903Shestness@cs.utexas.edu            .name(name() + "." + cstr + "_miss_rate")
3237903Shestness@cs.utexas.edu            .desc("miss rate for " + cstr + " accesses")
3247903Shestness@cs.utexas.edu            .flags(total | nozero | nonan)
3257903Shestness@cs.utexas.edu            ;
3267903Shestness@cs.utexas.edu        missRate[access_idx] = misses[access_idx] / accesses[access_idx];
3277903Shestness@cs.utexas.edu
3287903Shestness@cs.utexas.edu        for (int i = 0; i < system->maxMasters(); i++) {
3297903Shestness@cs.utexas.edu            missRate[access_idx].subname(i, system->getMasterName(i));
3307903Shestness@cs.utexas.edu        }
3317903Shestness@cs.utexas.edu    }
3327903Shestness@cs.utexas.edu
3337903Shestness@cs.utexas.edu    demandMissRate
3347903Shestness@cs.utexas.edu        .name(name() + ".demand_miss_rate")
3357903Shestness@cs.utexas.edu        .desc("miss rate for demand accesses")
3367903Shestness@cs.utexas.edu        .flags(total | nozero | nonan)
3377903Shestness@cs.utexas.edu        ;
3387903Shestness@cs.utexas.edu    demandMissRate = demandMisses / demandAccesses;
3397903Shestness@cs.utexas.edu    for (int i = 0; i < system->maxMasters(); i++) {
3407903Shestness@cs.utexas.edu        demandMissRate.subname(i, system->getMasterName(i));
3417903Shestness@cs.utexas.edu    }
3427903Shestness@cs.utexas.edu
3435630Sgblack@eecs.umich.edu    overallMissRate
3445630Sgblack@eecs.umich.edu        .name(name() + ".overall_miss_rate")
3455630Sgblack@eecs.umich.edu        .desc("miss rate for overall accesses")
3465630Sgblack@eecs.umich.edu        .flags(total | nozero | nonan)
3475630Sgblack@eecs.umich.edu        ;
348    overallMissRate = overallMisses / overallAccesses;
349    for (int i = 0; i < system->maxMasters(); i++) {
350        overallMissRate.subname(i, system->getMasterName(i));
351    }
352
353    // miss latency formulas
354    for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
355        MemCmd cmd(access_idx);
356        const string &cstr = cmd.toString();
357
358        avgMissLatency[access_idx]
359            .name(name() + "." + cstr + "_avg_miss_latency")
360            .desc("average " + cstr + " miss latency")
361            .flags(total | nozero | nonan)
362            ;
363        avgMissLatency[access_idx] =
364            missLatency[access_idx] / misses[access_idx];
365
366        for (int i = 0; i < system->maxMasters(); i++) {
367            avgMissLatency[access_idx].subname(i, system->getMasterName(i));
368        }
369    }
370
371    demandAvgMissLatency
372        .name(name() + ".demand_avg_miss_latency")
373        .desc("average overall miss latency")
374        .flags(total | nozero | nonan)
375        ;
376    demandAvgMissLatency = demandMissLatency / demandMisses;
377    for (int i = 0; i < system->maxMasters(); i++) {
378        demandAvgMissLatency.subname(i, system->getMasterName(i));
379    }
380
381    overallAvgMissLatency
382        .name(name() + ".overall_avg_miss_latency")
383        .desc("average overall miss latency")
384        .flags(total | nozero | nonan)
385        ;
386    overallAvgMissLatency = overallMissLatency / overallMisses;
387    for (int i = 0; i < system->maxMasters(); i++) {
388        overallAvgMissLatency.subname(i, system->getMasterName(i));
389    }
390
391    blocked_cycles.init(NUM_BLOCKED_CAUSES);
392    blocked_cycles
393        .name(name() + ".blocked_cycles")
394        .desc("number of cycles access was blocked")
395        .subname(Blocked_NoMSHRs, "no_mshrs")
396        .subname(Blocked_NoTargets, "no_targets")
397        ;
398
399
400    blocked_causes.init(NUM_BLOCKED_CAUSES);
401    blocked_causes
402        .name(name() + ".blocked")
403        .desc("number of cycles access was blocked")
404        .subname(Blocked_NoMSHRs, "no_mshrs")
405        .subname(Blocked_NoTargets, "no_targets")
406        ;
407
408    avg_blocked
409        .name(name() + ".avg_blocked_cycles")
410        .desc("average number of cycles each access was blocked")
411        .subname(Blocked_NoMSHRs, "no_mshrs")
412        .subname(Blocked_NoTargets, "no_targets")
413        ;
414
415    avg_blocked = blocked_cycles / blocked_causes;
416
417    fastWrites
418        .name(name() + ".fast_writes")
419        .desc("number of fast writes performed")
420        ;
421
422    cacheCopies
423        .name(name() + ".cache_copies")
424        .desc("number of cache copies performed")
425        ;
426
427    writebacks
428        .init(system->maxMasters())
429        .name(name() + ".writebacks")
430        .desc("number of writebacks")
431        .flags(total | nozero | nonan)
432        ;
433    for (int i = 0; i < system->maxMasters(); i++) {
434        writebacks.subname(i, system->getMasterName(i));
435    }
436
437    // MSHR statistics
438    // MSHR hit statistics
439    for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
440        MemCmd cmd(access_idx);
441        const string &cstr = cmd.toString();
442
443        mshr_hits[access_idx]
444            .init(system->maxMasters())
445            .name(name() + "." + cstr + "_mshr_hits")
446            .desc("number of " + cstr + " MSHR hits")
447            .flags(total | nozero | nonan)
448            ;
449        for (int i = 0; i < system->maxMasters(); i++) {
450            mshr_hits[access_idx].subname(i, system->getMasterName(i));
451        }
452    }
453
454    demandMshrHits
455        .name(name() + ".demand_mshr_hits")
456        .desc("number of demand (read+write) MSHR hits")
457        .flags(total | nozero | nonan)
458        ;
459    demandMshrHits = SUM_DEMAND(mshr_hits);
460    for (int i = 0; i < system->maxMasters(); i++) {
461        demandMshrHits.subname(i, system->getMasterName(i));
462    }
463
464    overallMshrHits
465        .name(name() + ".overall_mshr_hits")
466        .desc("number of overall MSHR hits")
467        .flags(total | nozero | nonan)
468        ;
469    overallMshrHits = demandMshrHits + SUM_NON_DEMAND(mshr_hits);
470    for (int i = 0; i < system->maxMasters(); i++) {
471        overallMshrHits.subname(i, system->getMasterName(i));
472    }
473
474    // MSHR miss statistics
475    for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
476        MemCmd cmd(access_idx);
477        const string &cstr = cmd.toString();
478
479        mshr_misses[access_idx]
480            .init(system->maxMasters())
481            .name(name() + "." + cstr + "_mshr_misses")
482            .desc("number of " + cstr + " MSHR misses")
483            .flags(total | nozero | nonan)
484            ;
485        for (int i = 0; i < system->maxMasters(); i++) {
486            mshr_misses[access_idx].subname(i, system->getMasterName(i));
487        }
488    }
489
490    demandMshrMisses
491        .name(name() + ".demand_mshr_misses")
492        .desc("number of demand (read+write) MSHR misses")
493        .flags(total | nozero | nonan)
494        ;
495    demandMshrMisses = SUM_DEMAND(mshr_misses);
496    for (int i = 0; i < system->maxMasters(); i++) {
497        demandMshrMisses.subname(i, system->getMasterName(i));
498    }
499
500    overallMshrMisses
501        .name(name() + ".overall_mshr_misses")
502        .desc("number of overall MSHR misses")
503        .flags(total | nozero | nonan)
504        ;
505    overallMshrMisses = demandMshrMisses + SUM_NON_DEMAND(mshr_misses);
506    for (int i = 0; i < system->maxMasters(); i++) {
507        overallMshrMisses.subname(i, system->getMasterName(i));
508    }
509
510    // MSHR miss latency statistics
511    for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
512        MemCmd cmd(access_idx);
513        const string &cstr = cmd.toString();
514
515        mshr_miss_latency[access_idx]
516            .init(system->maxMasters())
517            .name(name() + "." + cstr + "_mshr_miss_latency")
518            .desc("number of " + cstr + " MSHR miss cycles")
519            .flags(total | nozero | nonan)
520            ;
521        for (int i = 0; i < system->maxMasters(); i++) {
522            mshr_miss_latency[access_idx].subname(i, system->getMasterName(i));
523        }
524    }
525
526    demandMshrMissLatency
527        .name(name() + ".demand_mshr_miss_latency")
528        .desc("number of demand (read+write) MSHR miss cycles")
529        .flags(total | nozero | nonan)
530        ;
531    demandMshrMissLatency = SUM_DEMAND(mshr_miss_latency);
532    for (int i = 0; i < system->maxMasters(); i++) {
533        demandMshrMissLatency.subname(i, system->getMasterName(i));
534    }
535
536    overallMshrMissLatency
537        .name(name() + ".overall_mshr_miss_latency")
538        .desc("number of overall MSHR miss cycles")
539        .flags(total | nozero | nonan)
540        ;
541    overallMshrMissLatency =
542        demandMshrMissLatency + SUM_NON_DEMAND(mshr_miss_latency);
543    for (int i = 0; i < system->maxMasters(); i++) {
544        overallMshrMissLatency.subname(i, system->getMasterName(i));
545    }
546
547    // MSHR uncacheable statistics
548    for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
549        MemCmd cmd(access_idx);
550        const string &cstr = cmd.toString();
551
552        mshr_uncacheable[access_idx]
553            .init(system->maxMasters())
554            .name(name() + "." + cstr + "_mshr_uncacheable")
555            .desc("number of " + cstr + " MSHR uncacheable")
556            .flags(total | nozero | nonan)
557            ;
558        for (int i = 0; i < system->maxMasters(); i++) {
559            mshr_uncacheable[access_idx].subname(i, system->getMasterName(i));
560        }
561    }
562
563    overallMshrUncacheable
564        .name(name() + ".overall_mshr_uncacheable_misses")
565        .desc("number of overall MSHR uncacheable misses")
566        .flags(total | nozero | nonan)
567        ;
568    overallMshrUncacheable =
569        SUM_DEMAND(mshr_uncacheable) + SUM_NON_DEMAND(mshr_uncacheable);
570    for (int i = 0; i < system->maxMasters(); i++) {
571        overallMshrUncacheable.subname(i, system->getMasterName(i));
572    }
573
574    // MSHR miss latency statistics
575    for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
576        MemCmd cmd(access_idx);
577        const string &cstr = cmd.toString();
578
579        mshr_uncacheable_lat[access_idx]
580            .init(system->maxMasters())
581            .name(name() + "." + cstr + "_mshr_uncacheable_latency")
582            .desc("number of " + cstr + " MSHR uncacheable cycles")
583            .flags(total | nozero | nonan)
584            ;
585        for (int i = 0; i < system->maxMasters(); i++) {
586            mshr_uncacheable_lat[access_idx].subname(i, system->getMasterName(i));
587        }
588    }
589
590    overallMshrUncacheableLatency
591        .name(name() + ".overall_mshr_uncacheable_latency")
592        .desc("number of overall MSHR uncacheable cycles")
593        .flags(total | nozero | nonan)
594        ;
595    overallMshrUncacheableLatency =
596        SUM_DEMAND(mshr_uncacheable_lat) +
597        SUM_NON_DEMAND(mshr_uncacheable_lat);
598    for (int i = 0; i < system->maxMasters(); i++) {
599        overallMshrUncacheableLatency.subname(i, system->getMasterName(i));
600    }
601
602#if 0
603    // MSHR access formulas
604    for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
605        MemCmd cmd(access_idx);
606        const string &cstr = cmd.toString();
607
608        mshrAccesses[access_idx]
609            .name(name() + "." + cstr + "_mshr_accesses")
610            .desc("number of " + cstr + " mshr accesses(hits+misses)")
611            .flags(total | nozero | nonan)
612            ;
613        mshrAccesses[access_idx] =
614            mshr_hits[access_idx] + mshr_misses[access_idx]
615            + mshr_uncacheable[access_idx];
616    }
617
618    demandMshrAccesses
619        .name(name() + ".demand_mshr_accesses")
620        .desc("number of demand (read+write) mshr accesses")
621        .flags(total | nozero | nonan)
622        ;
623    demandMshrAccesses = demandMshrHits + demandMshrMisses;
624
625    overallMshrAccesses
626        .name(name() + ".overall_mshr_accesses")
627        .desc("number of overall (read+write) mshr accesses")
628        .flags(total | nozero | nonan)
629        ;
630    overallMshrAccesses = overallMshrHits + overallMshrMisses
631        + overallMshrUncacheable;
632#endif
633
634    // MSHR miss rate formulas
635    for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
636        MemCmd cmd(access_idx);
637        const string &cstr = cmd.toString();
638
639        mshrMissRate[access_idx]
640            .name(name() + "." + cstr + "_mshr_miss_rate")
641            .desc("mshr miss rate for " + cstr + " accesses")
642            .flags(total | nozero | nonan)
643            ;
644        mshrMissRate[access_idx] =
645            mshr_misses[access_idx] / accesses[access_idx];
646
647        for (int i = 0; i < system->maxMasters(); i++) {
648            mshrMissRate[access_idx].subname(i, system->getMasterName(i));
649        }
650    }
651
652    demandMshrMissRate
653        .name(name() + ".demand_mshr_miss_rate")
654        .desc("mshr miss rate for demand accesses")
655        .flags(total | nozero | nonan)
656        ;
657    demandMshrMissRate = demandMshrMisses / demandAccesses;
658    for (int i = 0; i < system->maxMasters(); i++) {
659        demandMshrMissRate.subname(i, system->getMasterName(i));
660    }
661
662    overallMshrMissRate
663        .name(name() + ".overall_mshr_miss_rate")
664        .desc("mshr miss rate for overall accesses")
665        .flags(total | nozero | nonan)
666        ;
667    overallMshrMissRate = overallMshrMisses / overallAccesses;
668    for (int i = 0; i < system->maxMasters(); i++) {
669        overallMshrMissRate.subname(i, system->getMasterName(i));
670    }
671
672    // mshrMiss latency formulas
673    for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
674        MemCmd cmd(access_idx);
675        const string &cstr = cmd.toString();
676
677        avgMshrMissLatency[access_idx]
678            .name(name() + "." + cstr + "_avg_mshr_miss_latency")
679            .desc("average " + cstr + " mshr miss latency")
680            .flags(total | nozero | nonan)
681            ;
682        avgMshrMissLatency[access_idx] =
683            mshr_miss_latency[access_idx] / mshr_misses[access_idx];
684
685        for (int i = 0; i < system->maxMasters(); i++) {
686            avgMshrMissLatency[access_idx].subname(i, system->getMasterName(i));
687        }
688    }
689
690    demandAvgMshrMissLatency
691        .name(name() + ".demand_avg_mshr_miss_latency")
692        .desc("average overall mshr miss latency")
693        .flags(total | nozero | nonan)
694        ;
695    demandAvgMshrMissLatency = demandMshrMissLatency / demandMshrMisses;
696    for (int i = 0; i < system->maxMasters(); i++) {
697        demandAvgMshrMissLatency.subname(i, system->getMasterName(i));
698    }
699
700    overallAvgMshrMissLatency
701        .name(name() + ".overall_avg_mshr_miss_latency")
702        .desc("average overall mshr miss latency")
703        .flags(total | nozero | nonan)
704        ;
705    overallAvgMshrMissLatency = overallMshrMissLatency / overallMshrMisses;
706    for (int i = 0; i < system->maxMasters(); i++) {
707        overallAvgMshrMissLatency.subname(i, system->getMasterName(i));
708    }
709
710    // mshrUncacheable latency formulas
711    for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
712        MemCmd cmd(access_idx);
713        const string &cstr = cmd.toString();
714
715        avgMshrUncacheableLatency[access_idx]
716            .name(name() + "." + cstr + "_avg_mshr_uncacheable_latency")
717            .desc("average " + cstr + " mshr uncacheable latency")
718            .flags(total | nozero | nonan)
719            ;
720        avgMshrUncacheableLatency[access_idx] =
721            mshr_uncacheable_lat[access_idx] / mshr_uncacheable[access_idx];
722
723        for (int i = 0; i < system->maxMasters(); i++) {
724            avgMshrUncacheableLatency[access_idx].subname(i, system->getMasterName(i));
725        }
726    }
727
728    overallAvgMshrUncacheableLatency
729        .name(name() + ".overall_avg_mshr_uncacheable_latency")
730        .desc("average overall mshr uncacheable latency")
731        .flags(total | nozero | nonan)
732        ;
733    overallAvgMshrUncacheableLatency = overallMshrUncacheableLatency / overallMshrUncacheable;
734    for (int i = 0; i < system->maxMasters(); i++) {
735        overallAvgMshrUncacheableLatency.subname(i, system->getMasterName(i));
736    }
737
738    mshr_cap_events
739        .init(system->maxMasters())
740        .name(name() + ".mshr_cap_events")
741        .desc("number of times MSHR cap was activated")
742        .flags(total | nozero | nonan)
743        ;
744    for (int i = 0; i < system->maxMasters(); i++) {
745        mshr_cap_events.subname(i, system->getMasterName(i));
746    }
747
748    //software prefetching stats
749    soft_prefetch_mshr_full
750        .init(system->maxMasters())
751        .name(name() + ".soft_prefetch_mshr_full")
752        .desc("number of mshr full events for SW prefetching instrutions")
753        .flags(total | nozero | nonan)
754        ;
755    for (int i = 0; i < system->maxMasters(); i++) {
756        soft_prefetch_mshr_full.subname(i, system->getMasterName(i));
757    }
758
759    mshr_no_allocate_misses
760        .name(name() +".no_allocate_misses")
761        .desc("Number of misses that were no-allocate")
762        ;
763
764}
765
766unsigned int
767BaseCache::drain(DrainManager *dm)
768{
769    int count = memSidePort->drain(dm) + cpuSidePort->drain(dm) +
770        mshrQueue.drain(dm) + writeBuffer.drain(dm);
771
772    // Set status
773    if (count != 0) {
774        setDrainState(Drainable::Draining);
775        DPRINTF(Drain, "Cache not drained\n");
776        return count;
777    }
778
779    setDrainState(Drainable::Drained);
780    return 0;
781}
782
783BaseCache *
784BaseCacheParams::create()
785{
786    unsigned numSets = size / (assoc * system->cacheLineSize());
787
788    assert(tags);
789
790    if (dynamic_cast<FALRU*>(tags)) {
791        if (numSets != 1)
792            fatal("Got FALRU tags with more than one set\n");
793        return new Cache<FALRU>(this);
794    } else if (dynamic_cast<LRU*>(tags)) {
795        if (numSets == 1)
796            warn("Consider using FALRU tags for a fully associative cache\n");
797        return new Cache<LRU>(this);
798    } else if (dynamic_cast<RandomRepl*>(tags)) {
799        return new Cache<RandomRepl>(this);
800    } else {
801        fatal("No suitable tags selected\n");
802    }
803}
804