base.cc revision 10713
12810SN/A/*
29614Srene.dejong@arm.com * Copyright (c) 2012-2013 ARM Limited
38856Sandreas.hansson@arm.com * All rights reserved.
48856Sandreas.hansson@arm.com *
58856Sandreas.hansson@arm.com * The license below extends only to copyright in the software and shall
68856Sandreas.hansson@arm.com * not be construed as granting a license to any other intellectual
78856Sandreas.hansson@arm.com * property including but not limited to intellectual property relating
88856Sandreas.hansson@arm.com * to a hardware implementation of the functionality of the software
98856Sandreas.hansson@arm.com * licensed hereunder.  You may use the software subject to the license
108856Sandreas.hansson@arm.com * terms below provided that you ensure that this notice is replicated
118856Sandreas.hansson@arm.com * unmodified and in its entirety in all distributions of the software,
128856Sandreas.hansson@arm.com * modified or unmodified, in source code or in binary form.
138856Sandreas.hansson@arm.com *
142810SN/A * Copyright (c) 2003-2005 The Regents of The University of Michigan
152810SN/A * All rights reserved.
162810SN/A *
172810SN/A * Redistribution and use in source and binary forms, with or without
182810SN/A * modification, are permitted provided that the following conditions are
192810SN/A * met: redistributions of source code must retain the above copyright
202810SN/A * notice, this list of conditions and the following disclaimer;
212810SN/A * redistributions in binary form must reproduce the above copyright
222810SN/A * notice, this list of conditions and the following disclaimer in the
232810SN/A * documentation and/or other materials provided with the distribution;
242810SN/A * neither the name of the copyright holders nor the names of its
252810SN/A * contributors may be used to endorse or promote products derived from
262810SN/A * this software without specific prior written permission.
272810SN/A *
282810SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
292810SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
302810SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
312810SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
322810SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
332810SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
342810SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
352810SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
362810SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
372810SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
382810SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
392810SN/A *
402810SN/A * Authors: Erik Hallnor
412810SN/A */
422810SN/A
432810SN/A/**
442810SN/A * @file
452810SN/A * Definition of BaseCache functions.
462810SN/A */
472810SN/A
488232Snate@binkert.org#include "debug/Cache.hh"
499152Satgutier@umich.edu#include "debug/Drain.hh"
509795Sandreas.hansson@arm.com#include "mem/cache/tags/fa_lru.hh"
519795Sandreas.hansson@arm.com#include "mem/cache/tags/lru.hh"
5210263Satgutier@umich.edu#include "mem/cache/tags/random_repl.hh"
535338Sstever@gmail.com#include "mem/cache/base.hh"
549795Sandreas.hansson@arm.com#include "mem/cache/cache.hh"
555338Sstever@gmail.com#include "mem/cache/mshr.hh"
568786Sgblack@eecs.umich.edu#include "sim/full_system.hh"
572810SN/A
582810SN/Ausing namespace std;
592810SN/A
608856Sandreas.hansson@arm.comBaseCache::CacheSlavePort::CacheSlavePort(const std::string &_name,
618856Sandreas.hansson@arm.com                                          BaseCache *_cache,
628856Sandreas.hansson@arm.com                                          const std::string &_label)
638922Swilliam.wang@arm.com    : QueuedSlavePort(_name, _cache, queue), queue(*_cache, *this, _label),
648914Sandreas.hansson@arm.com      blocked(false), mustSendRetry(false), sendRetryEvent(this)
658856Sandreas.hansson@arm.com{
668856Sandreas.hansson@arm.com}
674475SN/A
6811053Sandreas.hansson@arm.comBaseCache::BaseCache(const Params *p)
695034SN/A    : MemObject(p),
7010360Sandreas.hansson@arm.com      cpuSidePort(nullptr), memSidePort(nullptr),
7111377Sandreas.hansson@arm.com      mshrQueue("MSHRs", p->mshrs, 4, p->demand_mshr_reserve, MSHRQueue_MSHRs),
7211377Sandreas.hansson@arm.com      writeBuffer("write buffer", p->write_buffers, p->mshrs+1000, 0,
7311053Sandreas.hansson@arm.com                  MSHRQueue_WriteBuffer),
7410693SMarco.Balboni@ARM.com      blkSize(p->system->cacheLineSize()),
7510693SMarco.Balboni@ARM.com      lookupLatency(p->hit_latency),
7610693SMarco.Balboni@ARM.com      forwardLatency(p->hit_latency),
779263Smrinmoy.ghosh@arm.com      fillLatency(p->response_latency),
785034SN/A      responseLatency(p->response_latency),
7911331Sandreas.hansson@arm.com      numTarget(p->tgts_per_mshr),
8010884Sandreas.hansson@arm.com      forwardSnoops(p->forward_snoops),
814626SN/A      isTopLevel(p->is_top_level),
8210360Sandreas.hansson@arm.com      blocked(0),
834626SN/A      order(0),
845034SN/A      noTargetMSHR(NULL),
858883SAli.Saidi@ARM.com      missCount(p->max_miss_count),
868833Sdam.sunwoo@arm.com      addrRanges(p->addr_ranges.begin(), p->addr_ranges.end()),
874458SN/A      system(p->system)
8811377Sandreas.hansson@arm.com{
8911377Sandreas.hansson@arm.com}
9011377Sandreas.hansson@arm.com
9111377Sandreas.hansson@arm.comvoid
9211377Sandreas.hansson@arm.comBaseCache::CacheSlavePort::setBlocked()
9311377Sandreas.hansson@arm.com{
9411331Sandreas.hansson@arm.com    assert(!blocked);
9511331Sandreas.hansson@arm.com    DPRINTF(CachePort, "Cache port %s blocking new requests\n", name());
962810SN/A    blocked = true;
972810SN/A    // if we already scheduled a retry in this cycle, but it has not yet
983013SN/A    // happened, cancel it
998856Sandreas.hansson@arm.com    if (sendRetryEvent.scheduled()) {
1002810SN/A        owner.deschedule(sendRetryEvent);
1013013SN/A        DPRINTF(CachePort, "Cache port %s deschedule retry\n", name());
10210714Sandreas.hansson@arm.com        mustSendRetry = true;
1032810SN/A    }
1049614Srene.dejong@arm.com}
1059614Srene.dejong@arm.com
1069614Srene.dejong@arm.comvoid
10710345SCurtis.Dunham@arm.comBaseCache::CacheSlavePort::clearBlocked()
10810714Sandreas.hansson@arm.com{
10910345SCurtis.Dunham@arm.com    assert(blocked);
1109614Srene.dejong@arm.com    DPRINTF(CachePort, "Cache port %s accepting new requests\n", name());
1112810SN/A    blocked = false;
1122810SN/A    if (mustSendRetry) {
1132810SN/A        // @TODO: need to find a better time (next bus cycle?)
1148856Sandreas.hansson@arm.com        owner.schedule(sendRetryEvent, curTick() + 1);
1152810SN/A    }
1163013SN/A}
11710714Sandreas.hansson@arm.com
1183013SN/Avoid
1198856Sandreas.hansson@arm.comBaseCache::CacheSlavePort::processSendRetry()
12010714Sandreas.hansson@arm.com{
1218922Swilliam.wang@arm.com    DPRINTF(CachePort, "Cache port %s sending retry\n", name());
1222897SN/A
1232810SN/A    // reset the flag and call retry
1242810SN/A    mustSendRetry = false;
12510344Sandreas.hansson@arm.com    sendRetryReq();
12610344Sandreas.hansson@arm.com}
12710344Sandreas.hansson@arm.com
12810714Sandreas.hansson@arm.comvoid
12910344Sandreas.hansson@arm.comBaseCache::init()
13010344Sandreas.hansson@arm.com{
13110344Sandreas.hansson@arm.com    if (!cpuSidePort->isConnected() || !memSidePort->isConnected())
13210713Sandreas.hansson@arm.com        fatal("Cache ports on %s are not connected\n", name());
13310344Sandreas.hansson@arm.com    cpuSidePort->sendRangeChange();
1342844SN/A}
1352810SN/A
1362858SN/ABaseMasterPort &
1372858SN/ABaseCache::getMasterPort(const std::string &if_name, PortID idx)
1388856Sandreas.hansson@arm.com{
1398922Swilliam.wang@arm.com    if (if_name == "mem_side") {
1408711Sandreas.hansson@arm.com        return *memSidePort;
14111331Sandreas.hansson@arm.com    }  else {
1422858SN/A        return MemObject::getMasterPort(if_name, idx);
1432858SN/A    }
1449294Sandreas.hansson@arm.com}
1459294Sandreas.hansson@arm.com
1468922Swilliam.wang@arm.comBaseSlavePort &
1478922Swilliam.wang@arm.comBaseCache::getSlavePort(const std::string &if_name, PortID idx)
1488922Swilliam.wang@arm.com{
1498922Swilliam.wang@arm.com    if (if_name == "cpu_side") {
1508922Swilliam.wang@arm.com        return *cpuSidePort;
1518922Swilliam.wang@arm.com    } else {
1528922Swilliam.wang@arm.com        return MemObject::getSlavePort(if_name, idx);
1538922Swilliam.wang@arm.com    }
1549294Sandreas.hansson@arm.com}
1559294Sandreas.hansson@arm.com
1568922Swilliam.wang@arm.comvoid
1578922Swilliam.wang@arm.comBaseCache::regStats()
1588922Swilliam.wang@arm.com{
1598922Swilliam.wang@arm.com    using namespace Stats;
1608922Swilliam.wang@arm.com
1618922Swilliam.wang@arm.com    // Hit statistics
1628922Swilliam.wang@arm.com    for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
1634628SN/A        MemCmd cmd(access_idx);
16410821Sandreas.hansson@arm.com        const string &cstr = cmd.toString();
16510821Sandreas.hansson@arm.com
16610821Sandreas.hansson@arm.com        hits[access_idx]
16710821Sandreas.hansson@arm.com            .init(system->maxMasters())
16810821Sandreas.hansson@arm.com            .name(name() + "." + cstr + "_hits")
16910821Sandreas.hansson@arm.com            .desc("number of " + cstr + " hits")
17010821Sandreas.hansson@arm.com            .flags(total | nozero | nonan)
17110821Sandreas.hansson@arm.com            ;
17210821Sandreas.hansson@arm.com        for (int i = 0; i < system->maxMasters(); i++) {
17310821Sandreas.hansson@arm.com            hits[access_idx].subname(i, system->getMasterName(i));
17410821Sandreas.hansson@arm.com        }
1752858SN/A    }
1762810SN/A
1772810SN/A// These macros make it easier to sum the right subset of commands and
1782810SN/A// to change the subset of commands that are considered "demand" vs
1792810SN/A// "non-demand"
1802810SN/A#define SUM_DEMAND(s) \
1814022SN/A    (s[MemCmd::ReadReq] + s[MemCmd::WriteReq] + s[MemCmd::ReadExReq])
1824022SN/A
1834022SN/A// should writebacks be included here?  prior code was inconsistent...
1842810SN/A#define SUM_NON_DEMAND(s) \
1852810SN/A    (s[MemCmd::SoftPFReq] + s[MemCmd::HardPFReq])
1868833Sdam.sunwoo@arm.com
1872810SN/A    demandHits
1882810SN/A        .name(name() + ".demand_hits")
1892810SN/A        .desc("number of demand (read+write) hits")
1902810SN/A        .flags(total | nozero | nonan)
1918833Sdam.sunwoo@arm.com        ;
1928833Sdam.sunwoo@arm.com    demandHits = SUM_DEMAND(hits);
1938833Sdam.sunwoo@arm.com    for (int i = 0; i < system->maxMasters(); i++) {
1942810SN/A        demandHits.subname(i, system->getMasterName(i));
1952810SN/A    }
1964871SN/A
1974871SN/A    overallHits
1984871SN/A        .name(name() + ".overall_hits")
1994871SN/A        .desc("number of overall hits")
20010885Sandreas.hansson@arm.com        .flags(total | nozero | nonan)
20110885Sandreas.hansson@arm.com        ;
2024871SN/A    overallHits = demandHits + SUM_NON_DEMAND(hits);
2034871SN/A    for (int i = 0; i < system->maxMasters(); i++) {
2044871SN/A        overallHits.subname(i, system->getMasterName(i));
2054871SN/A    }
2064871SN/A
2072810SN/A    // Miss statistics
2082810SN/A    for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
2092810SN/A        MemCmd cmd(access_idx);
2108833Sdam.sunwoo@arm.com        const string &cstr = cmd.toString();
2112810SN/A
2124871SN/A        misses[access_idx]
2138833Sdam.sunwoo@arm.com            .init(system->maxMasters())
2148833Sdam.sunwoo@arm.com            .name(name() + "." + cstr + "_misses")
2158833Sdam.sunwoo@arm.com            .desc("number of " + cstr + " misses")
2162810SN/A            .flags(total | nozero | nonan)
2172810SN/A            ;
2182810SN/A        for (int i = 0; i < system->maxMasters(); i++) {
2192810SN/A            misses[access_idx].subname(i, system->getMasterName(i));
2208833Sdam.sunwoo@arm.com        }
2212810SN/A    }
2224871SN/A
2238833Sdam.sunwoo@arm.com    demandMisses
2248833Sdam.sunwoo@arm.com        .name(name() + ".demand_misses")
2258833Sdam.sunwoo@arm.com        .desc("number of demand (read+write) misses")
2262810SN/A        .flags(total | nozero | nonan)
2272810SN/A        ;
2284022SN/A    demandMisses = SUM_DEMAND(misses);
2294022SN/A    for (int i = 0; i < system->maxMasters(); i++) {
2304022SN/A        demandMisses.subname(i, system->getMasterName(i));
2312810SN/A    }
2322810SN/A
2338833Sdam.sunwoo@arm.com    overallMisses
2342810SN/A        .name(name() + ".overall_misses")
2352810SN/A        .desc("number of overall misses")
2362810SN/A        .flags(total | nozero | nonan)
2372810SN/A        ;
2388833Sdam.sunwoo@arm.com    overallMisses = demandMisses + SUM_NON_DEMAND(misses);
2398833Sdam.sunwoo@arm.com    for (int i = 0; i < system->maxMasters(); i++) {
2408833Sdam.sunwoo@arm.com        overallMisses.subname(i, system->getMasterName(i));
2412810SN/A    }
2422810SN/A
2432810SN/A    // Miss latency statistics
2442810SN/A    for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
2452810SN/A        MemCmd cmd(access_idx);
2468833Sdam.sunwoo@arm.com        const string &cstr = cmd.toString();
2472810SN/A
2484871SN/A        missLatency[access_idx]
2498833Sdam.sunwoo@arm.com            .init(system->maxMasters())
2508833Sdam.sunwoo@arm.com            .name(name() + "." + cstr + "_miss_latency")
2518833Sdam.sunwoo@arm.com            .desc("number of " + cstr + " miss cycles")
2522810SN/A            .flags(total | nozero | nonan)
2532810SN/A            ;
2542810SN/A        for (int i = 0; i < system->maxMasters(); i++) {
2552810SN/A            missLatency[access_idx].subname(i, system->getMasterName(i));
2568833Sdam.sunwoo@arm.com        }
2572810SN/A    }
2584871SN/A
2598833Sdam.sunwoo@arm.com    demandMissLatency
2608833Sdam.sunwoo@arm.com        .name(name() + ".demand_miss_latency")
2618833Sdam.sunwoo@arm.com        .desc("number of demand (read+write) miss cycles")
2622810SN/A        .flags(total | nozero | nonan)
2632810SN/A        ;
2644022SN/A    demandMissLatency = SUM_DEMAND(missLatency);
2654022SN/A    for (int i = 0; i < system->maxMasters(); i++) {
2664022SN/A        demandMissLatency.subname(i, system->getMasterName(i));
2672810SN/A    }
2682810SN/A
2698833Sdam.sunwoo@arm.com    overallMissLatency
2702810SN/A        .name(name() + ".overall_miss_latency")
2712810SN/A        .desc("number of overall miss cycles")
2722810SN/A        .flags(total | nozero | nonan)
2732810SN/A        ;
2748833Sdam.sunwoo@arm.com    overallMissLatency = demandMissLatency + SUM_NON_DEMAND(missLatency);
2758833Sdam.sunwoo@arm.com    for (int i = 0; i < system->maxMasters(); i++) {
2768833Sdam.sunwoo@arm.com        overallMissLatency.subname(i, system->getMasterName(i));
2772810SN/A    }
2782810SN/A
2792810SN/A    // access formulas
2802810SN/A    for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
2812810SN/A        MemCmd cmd(access_idx);
2828833Sdam.sunwoo@arm.com        const string &cstr = cmd.toString();
2832810SN/A
2844871SN/A        accesses[access_idx]
2858833Sdam.sunwoo@arm.com            .name(name() + "." + cstr + "_accesses")
2868833Sdam.sunwoo@arm.com            .desc("number of " + cstr + " accesses(hits+misses)")
2878833Sdam.sunwoo@arm.com            .flags(total | nozero | nonan)
2882810SN/A            ;
2892810SN/A        accesses[access_idx] = hits[access_idx] + misses[access_idx];
2902810SN/A
2912810SN/A        for (int i = 0; i < system->maxMasters(); i++) {
2928833Sdam.sunwoo@arm.com            accesses[access_idx].subname(i, system->getMasterName(i));
2932810SN/A        }
2944871SN/A    }
2958833Sdam.sunwoo@arm.com
2968833Sdam.sunwoo@arm.com    demandAccesses
2978833Sdam.sunwoo@arm.com        .name(name() + ".demand_accesses")
2982810SN/A        .desc("number of demand (read+write) accesses")
2992810SN/A        .flags(total | nozero | nonan)
3004022SN/A        ;
3014022SN/A    demandAccesses = demandHits + demandMisses;
3024022SN/A    for (int i = 0; i < system->maxMasters(); i++) {
3032810SN/A        demandAccesses.subname(i, system->getMasterName(i));
3042810SN/A    }
3052810SN/A
3062810SN/A    overallAccesses
3072810SN/A        .name(name() + ".overall_accesses")
3082810SN/A        .desc("number of overall (read+write) accesses")
3098833Sdam.sunwoo@arm.com        .flags(total | nozero | nonan)
3102810SN/A        ;
3118833Sdam.sunwoo@arm.com    overallAccesses = overallHits + overallMisses;
3128833Sdam.sunwoo@arm.com    for (int i = 0; i < system->maxMasters(); i++) {
3138833Sdam.sunwoo@arm.com        overallAccesses.subname(i, system->getMasterName(i));
3142810SN/A    }
3152810SN/A
3162810SN/A    // miss rate formulas
3172810SN/A    for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
3182810SN/A        MemCmd cmd(access_idx);
3198833Sdam.sunwoo@arm.com        const string &cstr = cmd.toString();
3202810SN/A
3212810SN/A        missRate[access_idx]
3228833Sdam.sunwoo@arm.com            .name(name() + "." + cstr + "_miss_rate")
3238833Sdam.sunwoo@arm.com            .desc("miss rate for " + cstr + " accesses")
3248833Sdam.sunwoo@arm.com            .flags(total | nozero | nonan)
3252810SN/A            ;
3262810SN/A        missRate[access_idx] = misses[access_idx] / accesses[access_idx];
3272810SN/A
3282810SN/A        for (int i = 0; i < system->maxMasters(); i++) {
3298833Sdam.sunwoo@arm.com            missRate[access_idx].subname(i, system->getMasterName(i));
3302810SN/A        }
3312810SN/A    }
3328833Sdam.sunwoo@arm.com
3338833Sdam.sunwoo@arm.com    demandMissRate
3348833Sdam.sunwoo@arm.com        .name(name() + ".demand_miss_rate")
3352810SN/A        .desc("miss rate for demand accesses")
3362810SN/A        .flags(total | nozero | nonan)
3374022SN/A        ;
3384022SN/A    demandMissRate = demandMisses / demandAccesses;
3394022SN/A    for (int i = 0; i < system->maxMasters(); i++) {
3402810SN/A        demandMissRate.subname(i, system->getMasterName(i));
3412810SN/A    }
3422810SN/A
3432810SN/A    overallMissRate
3442810SN/A        .name(name() + ".overall_miss_rate")
3452810SN/A        .desc("miss rate for overall accesses")
3468833Sdam.sunwoo@arm.com        .flags(total | nozero | nonan)
3472810SN/A        ;
3488833Sdam.sunwoo@arm.com    overallMissRate = overallMisses / overallAccesses;
3498833Sdam.sunwoo@arm.com    for (int i = 0; i < system->maxMasters(); i++) {
3508833Sdam.sunwoo@arm.com        overallMissRate.subname(i, system->getMasterName(i));
3512810SN/A    }
3522810SN/A
3532810SN/A    // miss latency formulas
3542810SN/A    for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
3552810SN/A        MemCmd cmd(access_idx);
3568833Sdam.sunwoo@arm.com        const string &cstr = cmd.toString();
3572810SN/A
3582810SN/A        avgMissLatency[access_idx]
3598833Sdam.sunwoo@arm.com            .name(name() + "." + cstr + "_avg_miss_latency")
3608833Sdam.sunwoo@arm.com            .desc("average " + cstr + " miss latency")
3618833Sdam.sunwoo@arm.com            .flags(total | nozero | nonan)
3622810SN/A            ;
3632810SN/A        avgMissLatency[access_idx] =
3642810SN/A            missLatency[access_idx] / misses[access_idx];
3652810SN/A
3668833Sdam.sunwoo@arm.com        for (int i = 0; i < system->maxMasters(); i++) {
3672810SN/A            avgMissLatency[access_idx].subname(i, system->getMasterName(i));
3682810SN/A        }
3698833Sdam.sunwoo@arm.com    }
3708833Sdam.sunwoo@arm.com
3718833Sdam.sunwoo@arm.com    demandAvgMissLatency
3722810SN/A        .name(name() + ".demand_avg_miss_latency")
3732810SN/A        .desc("average overall miss latency")
3744022SN/A        .flags(total | nozero | nonan)
3754022SN/A        ;
3764022SN/A    demandAvgMissLatency = demandMissLatency / demandMisses;
3772810SN/A    for (int i = 0; i < system->maxMasters(); i++) {
3782810SN/A        demandAvgMissLatency.subname(i, system->getMasterName(i));
3792810SN/A    }
3802810SN/A
3812810SN/A    overallAvgMissLatency
3822810SN/A        .name(name() + ".overall_avg_miss_latency")
3832810SN/A        .desc("average overall miss latency")
3842810SN/A        .flags(total | nozero | nonan)
3858833Sdam.sunwoo@arm.com        ;
3868833Sdam.sunwoo@arm.com    overallAvgMissLatency = overallMissLatency / overallMisses;
3878833Sdam.sunwoo@arm.com    for (int i = 0; i < system->maxMasters(); i++) {
3888833Sdam.sunwoo@arm.com        overallAvgMissLatency.subname(i, system->getMasterName(i));
3892810SN/A    }
3902810SN/A
3912810SN/A    blocked_cycles.init(NUM_BLOCKED_CAUSES);
3922810SN/A    blocked_cycles
3932810SN/A        .name(name() + ".blocked_cycles")
3948833Sdam.sunwoo@arm.com        .desc("number of cycles access was blocked")
3952810SN/A        .subname(Blocked_NoMSHRs, "no_mshrs")
3962810SN/A        .subname(Blocked_NoTargets, "no_targets")
3978833Sdam.sunwoo@arm.com        ;
3988833Sdam.sunwoo@arm.com
3998833Sdam.sunwoo@arm.com
4002810SN/A    blocked_causes.init(NUM_BLOCKED_CAUSES);
4012810SN/A    blocked_causes
4022810SN/A        .name(name() + ".blocked")
4032810SN/A        .desc("number of cycles access was blocked")
4048833Sdam.sunwoo@arm.com        .subname(Blocked_NoMSHRs, "no_mshrs")
4052810SN/A        .subname(Blocked_NoTargets, "no_targets")
4062810SN/A        ;
4078833Sdam.sunwoo@arm.com
4088833Sdam.sunwoo@arm.com    avg_blocked
4098833Sdam.sunwoo@arm.com        .name(name() + ".avg_blocked_cycles")
4102810SN/A        .desc("average number of cycles each access was blocked")
4112810SN/A        .subname(Blocked_NoMSHRs, "no_mshrs")
4122810SN/A        .subname(Blocked_NoTargets, "no_targets")
4132810SN/A        ;
4142810SN/A
4152810SN/A    avg_blocked = blocked_cycles / blocked_causes;
4162810SN/A
4172810SN/A    fastWrites
4182810SN/A        .name(name() + ".fast_writes")
4192810SN/A        .desc("number of fast writes performed")
4202810SN/A        ;
4212810SN/A
4222810SN/A    cacheCopies
4232810SN/A        .name(name() + ".cache_copies")
4242810SN/A        .desc("number of cache copies performed")
4252810SN/A        ;
4262810SN/A
4272810SN/A    writebacks
4282810SN/A        .init(system->maxMasters())
4292810SN/A        .name(name() + ".writebacks")
4302810SN/A        .desc("number of writebacks")
4312810SN/A        .flags(total | nozero | nonan)
4322810SN/A        ;
4332810SN/A    for (int i = 0; i < system->maxMasters(); i++) {
4342810SN/A        writebacks.subname(i, system->getMasterName(i));
4352810SN/A    }
4362810SN/A
4372810SN/A    // MSHR statistics
4382810SN/A    // MSHR hit statistics
4392810SN/A    for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
4402810SN/A        MemCmd cmd(access_idx);
4412810SN/A        const string &cstr = cmd.toString();
4422810SN/A
4432810SN/A        mshr_hits[access_idx]
4442810SN/A            .init(system->maxMasters())
4452810SN/A            .name(name() + "." + cstr + "_mshr_hits")
4462826SN/A            .desc("number of " + cstr + " MSHR hits")
44711436SRekai.GonzalezAlberquilla@arm.com            .flags(total | nozero | nonan)
44811436SRekai.GonzalezAlberquilla@arm.com            ;
44911436SRekai.GonzalezAlberquilla@arm.com        for (int i = 0; i < system->maxMasters(); i++) {
45011436SRekai.GonzalezAlberquilla@arm.com            mshr_hits[access_idx].subname(i, system->getMasterName(i));
45111436SRekai.GonzalezAlberquilla@arm.com        }
45211436SRekai.GonzalezAlberquilla@arm.com    }
4534626SN/A
4548833Sdam.sunwoo@arm.com    demandMshrHits
4554626SN/A        .name(name() + ".demand_mshr_hits")
4564626SN/A        .desc("number of demand (read+write) MSHR hits")
4578833Sdam.sunwoo@arm.com        .flags(total | nozero | nonan)
4584626SN/A        ;
4598833Sdam.sunwoo@arm.com    demandMshrHits = SUM_DEMAND(mshr_hits);
4608833Sdam.sunwoo@arm.com    for (int i = 0; i < system->maxMasters(); i++) {
4618833Sdam.sunwoo@arm.com        demandMshrHits.subname(i, system->getMasterName(i));
4624626SN/A    }
4634626SN/A
4644626SN/A    overallMshrHits
4654626SN/A        .name(name() + ".overall_mshr_hits")
4664626SN/A        .desc("number of overall MSHR hits")
4674626SN/A        .flags(total | nozero | nonan)
4684626SN/A        ;
4694626SN/A    overallMshrHits = demandMshrHits + SUM_NON_DEMAND(mshr_hits);
4708833Sdam.sunwoo@arm.com    for (int i = 0; i < system->maxMasters(); i++) {
4714626SN/A        overallMshrHits.subname(i, system->getMasterName(i));
4724626SN/A    }
4734626SN/A
4744626SN/A    // MSHR miss statistics
4758833Sdam.sunwoo@arm.com    for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
4768833Sdam.sunwoo@arm.com        MemCmd cmd(access_idx);
4778833Sdam.sunwoo@arm.com        const string &cstr = cmd.toString();
4784626SN/A
4794626SN/A        mshr_misses[access_idx]
4804626SN/A            .init(system->maxMasters())
4814626SN/A            .name(name() + "." + cstr + "_mshr_misses")
4824626SN/A            .desc("number of " + cstr + " MSHR misses")
4838833Sdam.sunwoo@arm.com            .flags(total | nozero | nonan)
4844626SN/A            ;
4854871SN/A        for (int i = 0; i < system->maxMasters(); i++) {
4868833Sdam.sunwoo@arm.com            mshr_misses[access_idx].subname(i, system->getMasterName(i));
4878833Sdam.sunwoo@arm.com        }
4888833Sdam.sunwoo@arm.com    }
4894626SN/A
4904626SN/A    demandMshrMisses
4914626SN/A        .name(name() + ".demand_mshr_misses")
4924626SN/A        .desc("number of demand (read+write) MSHR misses")
4938833Sdam.sunwoo@arm.com        .flags(total | nozero | nonan)
4944626SN/A        ;
4954871SN/A    demandMshrMisses = SUM_DEMAND(mshr_misses);
4968833Sdam.sunwoo@arm.com    for (int i = 0; i < system->maxMasters(); i++) {
4978833Sdam.sunwoo@arm.com        demandMshrMisses.subname(i, system->getMasterName(i));
4988833Sdam.sunwoo@arm.com    }
4994626SN/A
5004626SN/A    overallMshrMisses
5014626SN/A        .name(name() + ".overall_mshr_misses")
5024626SN/A        .desc("number of overall MSHR misses")
5034626SN/A        .flags(total | nozero | nonan)
5044626SN/A        ;
5054626SN/A    overallMshrMisses = demandMshrMisses + SUM_NON_DEMAND(mshr_misses);
5068833Sdam.sunwoo@arm.com    for (int i = 0; i < system->maxMasters(); i++) {
5074626SN/A        overallMshrMisses.subname(i, system->getMasterName(i));
5084626SN/A    }
5094626SN/A
5104626SN/A    // MSHR miss latency statistics
5118833Sdam.sunwoo@arm.com    for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
5128833Sdam.sunwoo@arm.com        MemCmd cmd(access_idx);
5138833Sdam.sunwoo@arm.com        const string &cstr = cmd.toString();
5144626SN/A
5154626SN/A        mshr_miss_latency[access_idx]
5164626SN/A            .init(system->maxMasters())
5174626SN/A            .name(name() + "." + cstr + "_mshr_miss_latency")
5184626SN/A            .desc("number of " + cstr + " MSHR miss cycles")
5198833Sdam.sunwoo@arm.com            .flags(total | nozero | nonan)
5204626SN/A            ;
5214871SN/A        for (int i = 0; i < system->maxMasters(); i++) {
5228833Sdam.sunwoo@arm.com            mshr_miss_latency[access_idx].subname(i, system->getMasterName(i));
5238833Sdam.sunwoo@arm.com        }
5248833Sdam.sunwoo@arm.com    }
5254626SN/A
5264626SN/A    demandMshrMissLatency
5274626SN/A        .name(name() + ".demand_mshr_miss_latency")
5284626SN/A        .desc("number of demand (read+write) MSHR miss cycles")
5298833Sdam.sunwoo@arm.com        .flags(total | nozero | nonan)
5304626SN/A        ;
5314871SN/A    demandMshrMissLatency = SUM_DEMAND(mshr_miss_latency);
5328833Sdam.sunwoo@arm.com    for (int i = 0; i < system->maxMasters(); i++) {
5338833Sdam.sunwoo@arm.com        demandMshrMissLatency.subname(i, system->getMasterName(i));
5348833Sdam.sunwoo@arm.com    }
5354626SN/A
5364626SN/A    overallMshrMissLatency
5374626SN/A        .name(name() + ".overall_mshr_miss_latency")
5384626SN/A        .desc("number of overall MSHR miss cycles")
5394626SN/A        .flags(total | nozero | nonan)
5404626SN/A        ;
5414626SN/A    overallMshrMissLatency =
5428833Sdam.sunwoo@arm.com        demandMshrMissLatency + SUM_NON_DEMAND(mshr_miss_latency);
5434626SN/A    for (int i = 0; i < system->maxMasters(); i++) {
5444626SN/A        overallMshrMissLatency.subname(i, system->getMasterName(i));
5454626SN/A    }
5464626SN/A
5478833Sdam.sunwoo@arm.com    // MSHR uncacheable statistics
5488833Sdam.sunwoo@arm.com    for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
5498833Sdam.sunwoo@arm.com        MemCmd cmd(access_idx);
5504626SN/A        const string &cstr = cmd.toString();
5514626SN/A
5524626SN/A        mshr_uncacheable[access_idx]
5534626SN/A            .init(system->maxMasters())
5544626SN/A            .name(name() + "." + cstr + "_mshr_uncacheable")
5558833Sdam.sunwoo@arm.com            .desc("number of " + cstr + " MSHR uncacheable")
5564626SN/A            .flags(total | nozero | nonan)
5574871SN/A            ;
5588833Sdam.sunwoo@arm.com        for (int i = 0; i < system->maxMasters(); i++) {
5598833Sdam.sunwoo@arm.com            mshr_uncacheable[access_idx].subname(i, system->getMasterName(i));
5608833Sdam.sunwoo@arm.com        }
5614626SN/A    }
5624626SN/A
5634626SN/A    overallMshrUncacheable
5644626SN/A        .name(name() + ".overall_mshr_uncacheable_misses")
5658833Sdam.sunwoo@arm.com        .desc("number of overall MSHR uncacheable misses")
5664626SN/A        .flags(total | nozero | nonan)
5674871SN/A        ;
5684871SN/A    overallMshrUncacheable =
5698833Sdam.sunwoo@arm.com        SUM_DEMAND(mshr_uncacheable) + SUM_NON_DEMAND(mshr_uncacheable);
5708833Sdam.sunwoo@arm.com    for (int i = 0; i < system->maxMasters(); i++) {
5718833Sdam.sunwoo@arm.com        overallMshrUncacheable.subname(i, system->getMasterName(i));
5724626SN/A    }
5734626SN/A
5744626SN/A    // MSHR miss latency statistics
5754626SN/A    for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
5764626SN/A        MemCmd cmd(access_idx);
5774626SN/A        const string &cstr = cmd.toString();
5784626SN/A
5798833Sdam.sunwoo@arm.com        mshr_uncacheable_lat[access_idx]
5804626SN/A            .init(system->maxMasters())
5814626SN/A            .name(name() + "." + cstr + "_mshr_uncacheable_latency")
5824626SN/A            .desc("number of " + cstr + " MSHR uncacheable cycles")
5834626SN/A            .flags(total | nozero | nonan)
5848833Sdam.sunwoo@arm.com            ;
5858833Sdam.sunwoo@arm.com        for (int i = 0; i < system->maxMasters(); i++) {
5868833Sdam.sunwoo@arm.com            mshr_uncacheable_lat[access_idx].subname(i, system->getMasterName(i));
5874626SN/A        }
5884626SN/A    }
5894626SN/A
5904626SN/A    overallMshrUncacheableLatency
5914626SN/A        .name(name() + ".overall_mshr_uncacheable_latency")
5928833Sdam.sunwoo@arm.com        .desc("number of overall MSHR uncacheable cycles")
5934626SN/A        .flags(total | nozero | nonan)
5944871SN/A        ;
5954871SN/A    overallMshrUncacheableLatency =
5968833Sdam.sunwoo@arm.com        SUM_DEMAND(mshr_uncacheable_lat) +
5978833Sdam.sunwoo@arm.com        SUM_NON_DEMAND(mshr_uncacheable_lat);
5988833Sdam.sunwoo@arm.com    for (int i = 0; i < system->maxMasters(); i++) {
5994626SN/A        overallMshrUncacheableLatency.subname(i, system->getMasterName(i));
6004626SN/A    }
6014626SN/A
6024626SN/A#if 0
6034626SN/A    // MSHR access formulas
6044626SN/A    for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
6054626SN/A        MemCmd cmd(access_idx);
6068833Sdam.sunwoo@arm.com        const string &cstr = cmd.toString();
6074626SN/A
6084626SN/A        mshrAccesses[access_idx]
6094626SN/A            .name(name() + "." + cstr + "_mshr_accesses")
6104626SN/A            .desc("number of " + cstr + " mshr accesses(hits+misses)")
6118833Sdam.sunwoo@arm.com            .flags(total | nozero | nonan)
6128833Sdam.sunwoo@arm.com            ;
6138833Sdam.sunwoo@arm.com        mshrAccesses[access_idx] =
6144626SN/A            mshr_hits[access_idx] + mshr_misses[access_idx]
6154626SN/A            + mshr_uncacheable[access_idx];
6164626SN/A    }
6174626SN/A
6184626SN/A    demandMshrAccesses
6198833Sdam.sunwoo@arm.com        .name(name() + ".demand_mshr_accesses")
6204626SN/A        .desc("number of demand (read+write) mshr accesses")
6214871SN/A        .flags(total | nozero | nonan)
6224871SN/A        ;
6234871SN/A    demandMshrAccesses = demandMshrHits + demandMshrMisses;
6248833Sdam.sunwoo@arm.com
6258833Sdam.sunwoo@arm.com    overallMshrAccesses
6268833Sdam.sunwoo@arm.com        .name(name() + ".overall_mshr_accesses")
6274626SN/A        .desc("number of overall (read+write) mshr accesses")
6284626SN/A        .flags(total | nozero | nonan)
6294626SN/A        ;
6304626SN/A    overallMshrAccesses = overallMshrHits + overallMshrMisses
6314626SN/A        + overallMshrUncacheable;
6324626SN/A#endif
6334626SN/A
6344626SN/A    // MSHR miss rate formulas
6354626SN/A    for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
6364626SN/A        MemCmd cmd(access_idx);
6374626SN/A        const string &cstr = cmd.toString();
6384626SN/A
6394626SN/A        mshrMissRate[access_idx]
6404626SN/A            .name(name() + "." + cstr + "_mshr_miss_rate")
6414626SN/A            .desc("mshr miss rate for " + cstr + " accesses")
6424626SN/A            .flags(total | nozero | nonan)
6434626SN/A            ;
6444626SN/A        mshrMissRate[access_idx] =
6454626SN/A            mshr_misses[access_idx] / accesses[access_idx];
6464626SN/A
6474626SN/A        for (int i = 0; i < system->maxMasters(); i++) {
6484626SN/A            mshrMissRate[access_idx].subname(i, system->getMasterName(i));
6494626SN/A        }
6504626SN/A    }
6514626SN/A
6524626SN/A    demandMshrMissRate
6534626SN/A        .name(name() + ".demand_mshr_miss_rate")
6544626SN/A        .desc("mshr miss rate for demand accesses")
6554626SN/A        .flags(total | nozero | nonan)
6564626SN/A        ;
6574626SN/A    demandMshrMissRate = demandMshrMisses / demandAccesses;
6584626SN/A    for (int i = 0; i < system->maxMasters(); i++) {
6594626SN/A        demandMshrMissRate.subname(i, system->getMasterName(i));
6604626SN/A    }
6614626SN/A
6624626SN/A    overallMshrMissRate
6634626SN/A        .name(name() + ".overall_mshr_miss_rate")
6644626SN/A        .desc("mshr miss rate for overall accesses")
6654626SN/A        .flags(total | nozero | nonan)
6664626SN/A        ;
6674626SN/A    overallMshrMissRate = overallMshrMisses / overallAccesses;
6684626SN/A    for (int i = 0; i < system->maxMasters(); i++) {
6694626SN/A        overallMshrMissRate.subname(i, system->getMasterName(i));
6704626SN/A    }
6714626SN/A
6728833Sdam.sunwoo@arm.com    // mshrMiss latency formulas
6738833Sdam.sunwoo@arm.com    for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
6748833Sdam.sunwoo@arm.com        MemCmd cmd(access_idx);
6758833Sdam.sunwoo@arm.com        const string &cstr = cmd.toString();
6764626SN/A
6774626SN/A        avgMshrMissLatency[access_idx]
6784626SN/A            .name(name() + "." + cstr + "_avg_mshr_miss_latency")
6794626SN/A            .desc("average " + cstr + " mshr miss latency")
6804626SN/A            .flags(total | nozero | nonan)
6818833Sdam.sunwoo@arm.com            ;
6824626SN/A        avgMshrMissLatency[access_idx] =
6834626SN/A            mshr_miss_latency[access_idx] / mshr_misses[access_idx];
6848833Sdam.sunwoo@arm.com
6858833Sdam.sunwoo@arm.com        for (int i = 0; i < system->maxMasters(); i++) {
6868833Sdam.sunwoo@arm.com            avgMshrMissLatency[access_idx].subname(i, system->getMasterName(i));
6874626SN/A        }
6884626SN/A    }
6894626SN/A
6904626SN/A    demandAvgMshrMissLatency
6918833Sdam.sunwoo@arm.com        .name(name() + ".demand_avg_mshr_miss_latency")
6924626SN/A        .desc("average overall mshr miss latency")
6934626SN/A        .flags(total | nozero | nonan)
6948833Sdam.sunwoo@arm.com        ;
6958833Sdam.sunwoo@arm.com    demandAvgMshrMissLatency = demandMshrMissLatency / demandMshrMisses;
6968833Sdam.sunwoo@arm.com    for (int i = 0; i < system->maxMasters(); i++) {
6974626SN/A        demandAvgMshrMissLatency.subname(i, system->getMasterName(i));
6984626SN/A    }
6994626SN/A
7004626SN/A    overallAvgMshrMissLatency
7014626SN/A        .name(name() + ".overall_avg_mshr_miss_latency")
7024626SN/A        .desc("average overall mshr miss latency")
7034626SN/A        .flags(total | nozero | nonan)
7044626SN/A        ;
7054626SN/A    overallAvgMshrMissLatency = overallMshrMissLatency / overallMshrMisses;
7064626SN/A    for (int i = 0; i < system->maxMasters(); i++) {
7074626SN/A        overallAvgMshrMissLatency.subname(i, system->getMasterName(i));
7084626SN/A    }
7094626SN/A
7108833Sdam.sunwoo@arm.com    // mshrUncacheable latency formulas
7118833Sdam.sunwoo@arm.com    for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
7128833Sdam.sunwoo@arm.com        MemCmd cmd(access_idx);
7138833Sdam.sunwoo@arm.com        const string &cstr = cmd.toString();
7144626SN/A
7154626SN/A        avgMshrUncacheableLatency[access_idx]
7164626SN/A            .name(name() + "." + cstr + "_avg_mshr_uncacheable_latency")
7174626SN/A            .desc("average " + cstr + " mshr uncacheable latency")
7184626SN/A            .flags(total | nozero | nonan)
7198833Sdam.sunwoo@arm.com            ;
7204626SN/A        avgMshrUncacheableLatency[access_idx] =
7214626SN/A            mshr_uncacheable_lat[access_idx] / mshr_uncacheable[access_idx];
7228833Sdam.sunwoo@arm.com
7238833Sdam.sunwoo@arm.com        for (int i = 0; i < system->maxMasters(); i++) {
7248833Sdam.sunwoo@arm.com            avgMshrUncacheableLatency[access_idx].subname(i, system->getMasterName(i));
7254626SN/A        }
7264626SN/A    }
7274626SN/A
7284626SN/A    overallAvgMshrUncacheableLatency
7298833Sdam.sunwoo@arm.com        .name(name() + ".overall_avg_mshr_uncacheable_latency")
7304626SN/A        .desc("average overall mshr uncacheable latency")
7314626SN/A        .flags(total | nozero | nonan)
7328833Sdam.sunwoo@arm.com        ;
7338833Sdam.sunwoo@arm.com    overallAvgMshrUncacheableLatency = overallMshrUncacheableLatency / overallMshrUncacheable;
7348833Sdam.sunwoo@arm.com    for (int i = 0; i < system->maxMasters(); i++) {
7354626SN/A        overallAvgMshrUncacheableLatency.subname(i, system->getMasterName(i));
7364626SN/A    }
7374626SN/A
7384626SN/A    mshr_cap_events
7394626SN/A        .init(system->maxMasters())
7404626SN/A        .name(name() + ".mshr_cap_events")
7414626SN/A        .desc("number of times MSHR cap was activated")
7424626SN/A        .flags(total | nozero | nonan)
7434626SN/A        ;
7444626SN/A    for (int i = 0; i < system->maxMasters(); i++) {
7454626SN/A        mshr_cap_events.subname(i, system->getMasterName(i));
7464626SN/A    }
7474626SN/A
7488833Sdam.sunwoo@arm.com    //software prefetching stats
7498833Sdam.sunwoo@arm.com    soft_prefetch_mshr_full
7508833Sdam.sunwoo@arm.com        .init(system->maxMasters())
7518833Sdam.sunwoo@arm.com        .name(name() + ".soft_prefetch_mshr_full")
7524626SN/A        .desc("number of mshr full events for SW prefetching instrutions")
7534626SN/A        .flags(total | nozero | nonan)
7544626SN/A        ;
7554626SN/A    for (int i = 0; i < system->maxMasters(); i++) {
7564626SN/A        soft_prefetch_mshr_full.subname(i, system->getMasterName(i));
7578833Sdam.sunwoo@arm.com    }
7584626SN/A
7594626SN/A    mshr_no_allocate_misses
7608833Sdam.sunwoo@arm.com        .name(name() +".no_allocate_misses")
7618833Sdam.sunwoo@arm.com        .desc("Number of misses that were no-allocate")
7628833Sdam.sunwoo@arm.com        ;
7634626SN/A
7644626SN/A}
7658833Sdam.sunwoo@arm.com
7664626SN/Aunsigned int
7674626SN/ABaseCache::drain(DrainManager *dm)
7688833Sdam.sunwoo@arm.com{
7694626SN/A    int count = memSidePort->drain(dm) + cpuSidePort->drain(dm) +
7708833Sdam.sunwoo@arm.com        mshrQueue.drain(dm) + writeBuffer.drain(dm);
7718833Sdam.sunwoo@arm.com
7728833Sdam.sunwoo@arm.com    // Set status
7734626SN/A    if (count != 0) {
7744626SN/A        setDrainState(Drainable::Draining);
7754626SN/A        DPRINTF(Drain, "Cache not drained\n");
7768833Sdam.sunwoo@arm.com        return count;
7774626SN/A    }
7784626SN/A
7798833Sdam.sunwoo@arm.com    setDrainState(Drainable::Drained);
7804626SN/A    return 0;
7818833Sdam.sunwoo@arm.com}
7828833Sdam.sunwoo@arm.com
7838833Sdam.sunwoo@arm.comBaseCache *
7844626SN/ABaseCacheParams::create()
7854626SN/A{
7864626SN/A    unsigned numSets = size / (assoc * system->cacheLineSize());
7874626SN/A
7884626SN/A    assert(tags);
7894626SN/A
7902810SN/A    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