base.cc revision 9263
113540Sandrea.mondelli@ucf.edu/*
210235Syasuko.eckert@amd.com * Copyright (c) 2012 ARM Limited
310235Syasuko.eckert@amd.com * All rights reserved.
410235Syasuko.eckert@amd.com *
510235Syasuko.eckert@amd.com * The license below extends only to copyright in the software and shall
610235Syasuko.eckert@amd.com * not be construed as granting a license to any other intellectual
710235Syasuko.eckert@amd.com * property including but not limited to intellectual property relating
810235Syasuko.eckert@amd.com * to a hardware implementation of the functionality of the software
910235Syasuko.eckert@amd.com * licensed hereunder.  You may use the software subject to the license
1010235Syasuko.eckert@amd.com * terms below provided that you ensure that this notice is replicated
1110235Syasuko.eckert@amd.com * unmodified and in its entirety in all distributions of the software,
1210235Syasuko.eckert@amd.com * modified or unmodified, in source code or in binary form.
1310235Syasuko.eckert@amd.com *
1410235Syasuko.eckert@amd.com * Copyright (c) 2003-2005 The Regents of The University of Michigan
1510235Syasuko.eckert@amd.com * All rights reserved.
1610235Syasuko.eckert@amd.com *
1710235Syasuko.eckert@amd.com * Redistribution and use in source and binary forms, with or without
1810235Syasuko.eckert@amd.com * modification, are permitted provided that the following conditions are
1910235Syasuko.eckert@amd.com * met: redistributions of source code must retain the above copyright
2010235Syasuko.eckert@amd.com * notice, this list of conditions and the following disclaimer;
2110235Syasuko.eckert@amd.com * redistributions in binary form must reproduce the above copyright
2210235Syasuko.eckert@amd.com * notice, this list of conditions and the following disclaimer in the
2310235Syasuko.eckert@amd.com * documentation and/or other materials provided with the distribution;
2410235Syasuko.eckert@amd.com * neither the name of the copyright holders nor the names of its
2510235Syasuko.eckert@amd.com * contributors may be used to endorse or promote products derived from
2610235Syasuko.eckert@amd.com * this software without specific prior written permission.
2710235Syasuko.eckert@amd.com *
2810235Syasuko.eckert@amd.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
2910235Syasuko.eckert@amd.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
3010235Syasuko.eckert@amd.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
3110235Syasuko.eckert@amd.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
3210235Syasuko.eckert@amd.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
3310235Syasuko.eckert@amd.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
3410235Syasuko.eckert@amd.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
3510235Syasuko.eckert@amd.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
3610235Syasuko.eckert@amd.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
3710235Syasuko.eckert@amd.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
3810235Syasuko.eckert@amd.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3910235Syasuko.eckert@amd.com *
4010235Syasuko.eckert@amd.com * Authors: Erik Hallnor
4110235Syasuko.eckert@amd.com */
4210235Syasuko.eckert@amd.com
4310235Syasuko.eckert@amd.com/**
4410235Syasuko.eckert@amd.com * @file
4510235Syasuko.eckert@amd.com * Definition of BaseCache functions.
4610235Syasuko.eckert@amd.com */
4710235Syasuko.eckert@amd.com
4810235Syasuko.eckert@amd.com#include "cpu/base.hh"
4910235Syasuko.eckert@amd.com#include "cpu/smt.hh"
5010235Syasuko.eckert@amd.com#include "debug/Cache.hh"
5110235Syasuko.eckert@amd.com#include "debug/Drain.hh"
5210235Syasuko.eckert@amd.com#include "mem/cache/base.hh"
5310235Syasuko.eckert@amd.com#include "mem/cache/mshr.hh"
5410235Syasuko.eckert@amd.com#include "sim/full_system.hh"
5510235Syasuko.eckert@amd.com
5610235Syasuko.eckert@amd.comusing namespace std;
5710235Syasuko.eckert@amd.com
5810235Syasuko.eckert@amd.comBaseCache::CacheSlavePort::CacheSlavePort(const std::string &_name,
5910235Syasuko.eckert@amd.com                                          BaseCache *_cache,
6010235Syasuko.eckert@amd.com                                          const std::string &_label)
6110235Syasuko.eckert@amd.com    : QueuedSlavePort(_name, _cache, queue), queue(*_cache, *this, _label),
6210235Syasuko.eckert@amd.com      blocked(false), mustSendRetry(false), sendRetryEvent(this)
6310235Syasuko.eckert@amd.com{
6410235Syasuko.eckert@amd.com}
6510235Syasuko.eckert@amd.com
6610235Syasuko.eckert@amd.comBaseCache::BaseCache(const Params *p)
6710235Syasuko.eckert@amd.com    : MemObject(p),
6810235Syasuko.eckert@amd.com      mshrQueue("MSHRs", p->mshrs, 4, MSHRQueue_MSHRs),
6910235Syasuko.eckert@amd.com      writeBuffer("write buffer", p->write_buffers, p->mshrs+1000,
7010235Syasuko.eckert@amd.com                  MSHRQueue_WriteBuffer),
7110235Syasuko.eckert@amd.com      blkSize(p->block_size),
7210235Syasuko.eckert@amd.com      hitLatency(p->hit_latency),
7310235Syasuko.eckert@amd.com      responseLatency(p->response_latency),
7410235Syasuko.eckert@amd.com      numTarget(p->tgts_per_mshr),
7510235Syasuko.eckert@amd.com      forwardSnoops(p->forward_snoops),
7610235Syasuko.eckert@amd.com      isTopLevel(p->is_top_level),
7710235Syasuko.eckert@amd.com      blocked(0),
7810235Syasuko.eckert@amd.com      noTargetMSHR(NULL),
7910235Syasuko.eckert@amd.com      missCount(p->max_miss_count),
8010235Syasuko.eckert@amd.com      drainEvent(NULL),
8110235Syasuko.eckert@amd.com      addrRanges(p->addr_ranges.begin(), p->addr_ranges.end()),
8210235Syasuko.eckert@amd.com      system(p->system)
8310235Syasuko.eckert@amd.com{
8410235Syasuko.eckert@amd.com}
8510235Syasuko.eckert@amd.com
8610235Syasuko.eckert@amd.comvoid
8710235Syasuko.eckert@amd.comBaseCache::CacheSlavePort::setBlocked()
8810235Syasuko.eckert@amd.com{
8910235Syasuko.eckert@amd.com    assert(!blocked);
9010235Syasuko.eckert@amd.com    DPRINTF(CachePort, "Cache port %s blocking new requests\n", name());
9110235Syasuko.eckert@amd.com    blocked = true;
9210235Syasuko.eckert@amd.com}
9310235Syasuko.eckert@amd.com
9410235Syasuko.eckert@amd.comvoid
9510235Syasuko.eckert@amd.comBaseCache::CacheSlavePort::clearBlocked()
9610235Syasuko.eckert@amd.com{
9710235Syasuko.eckert@amd.com    assert(blocked);
9810235Syasuko.eckert@amd.com    DPRINTF(CachePort, "Cache port %s accepting new requests\n", name());
9910235Syasuko.eckert@amd.com    blocked = false;
10010235Syasuko.eckert@amd.com    if (mustSendRetry) {
10110235Syasuko.eckert@amd.com        DPRINTF(CachePort, "Cache port %s sending retry\n", name());
10210235Syasuko.eckert@amd.com        mustSendRetry = false;
10310235Syasuko.eckert@amd.com        // @TODO: need to find a better time (next bus cycle?)
10410235Syasuko.eckert@amd.com        owner.schedule(sendRetryEvent, curTick() + 1);
10510235Syasuko.eckert@amd.com    }
10610235Syasuko.eckert@amd.com}
10710235Syasuko.eckert@amd.com
10810235Syasuko.eckert@amd.com
10910235Syasuko.eckert@amd.comvoid
11010235Syasuko.eckert@amd.comBaseCache::init()
11110235Syasuko.eckert@amd.com{
11210235Syasuko.eckert@amd.com    if (!cpuSidePort->isConnected() || !memSidePort->isConnected())
11310235Syasuko.eckert@amd.com        fatal("Cache ports on %s are not connected\n", name());
11410235Syasuko.eckert@amd.com    cpuSidePort->sendRangeChange();
11510235Syasuko.eckert@amd.com}
11610235Syasuko.eckert@amd.com
11710235Syasuko.eckert@amd.comMasterPort &
11810235Syasuko.eckert@amd.comBaseCache::getMasterPort(const std::string &if_name, int idx)
11910235Syasuko.eckert@amd.com{
12010235Syasuko.eckert@amd.com    if (if_name == "mem_side") {
12110235Syasuko.eckert@amd.com        return *memSidePort;
12210235Syasuko.eckert@amd.com    }  else {
12310235Syasuko.eckert@amd.com        return MemObject::getMasterPort(if_name, idx);
12410235Syasuko.eckert@amd.com    }
12510235Syasuko.eckert@amd.com}
12610235Syasuko.eckert@amd.com
12710235Syasuko.eckert@amd.comSlavePort &
12810235Syasuko.eckert@amd.comBaseCache::getSlavePort(const std::string &if_name, int idx)
12910235Syasuko.eckert@amd.com{
13010235Syasuko.eckert@amd.com    if (if_name == "cpu_side") {
13110235Syasuko.eckert@amd.com        return *cpuSidePort;
13210235Syasuko.eckert@amd.com    } else {
13310235Syasuko.eckert@amd.com        return MemObject::getSlavePort(if_name, idx);
13410235Syasuko.eckert@amd.com    }
13510235Syasuko.eckert@amd.com}
13610235Syasuko.eckert@amd.com
13710235Syasuko.eckert@amd.comvoid
13810235Syasuko.eckert@amd.comBaseCache::regStats()
13910235Syasuko.eckert@amd.com{
14010235Syasuko.eckert@amd.com    using namespace Stats;
14110235Syasuko.eckert@amd.com
14210235Syasuko.eckert@amd.com    // Hit statistics
14310235Syasuko.eckert@amd.com    for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
14410235Syasuko.eckert@amd.com        MemCmd cmd(access_idx);
14510235Syasuko.eckert@amd.com        const string &cstr = cmd.toString();
14610235Syasuko.eckert@amd.com
14710235Syasuko.eckert@amd.com        hits[access_idx]
14810235Syasuko.eckert@amd.com            .init(system->maxMasters())
14910235Syasuko.eckert@amd.com            .name(name() + "." + cstr + "_hits")
15010235Syasuko.eckert@amd.com            .desc("number of " + cstr + " hits")
15110235Syasuko.eckert@amd.com            .flags(total | nozero | nonan)
15210235Syasuko.eckert@amd.com            ;
15310235Syasuko.eckert@amd.com        for (int i = 0; i < system->maxMasters(); i++) {
15410235Syasuko.eckert@amd.com            hits[access_idx].subname(i, system->getMasterName(i));
15510235Syasuko.eckert@amd.com        }
15610235Syasuko.eckert@amd.com    }
15710235Syasuko.eckert@amd.com
15810235Syasuko.eckert@amd.com// These macros make it easier to sum the right subset of commands and
15910235Syasuko.eckert@amd.com// to change the subset of commands that are considered "demand" vs
16010235Syasuko.eckert@amd.com// "non-demand"
16110235Syasuko.eckert@amd.com#define SUM_DEMAND(s) \
16210235Syasuko.eckert@amd.com    (s[MemCmd::ReadReq] + s[MemCmd::WriteReq] + s[MemCmd::ReadExReq])
16310235Syasuko.eckert@amd.com
16410235Syasuko.eckert@amd.com// should writebacks be included here?  prior code was inconsistent...
16510235Syasuko.eckert@amd.com#define SUM_NON_DEMAND(s) \
16610235Syasuko.eckert@amd.com    (s[MemCmd::SoftPFReq] + s[MemCmd::HardPFReq])
16710235Syasuko.eckert@amd.com
16810235Syasuko.eckert@amd.com    demandHits
16910235Syasuko.eckert@amd.com        .name(name() + ".demand_hits")
17010235Syasuko.eckert@amd.com        .desc("number of demand (read+write) hits")
17110235Syasuko.eckert@amd.com        .flags(total | nozero | nonan)
17210235Syasuko.eckert@amd.com        ;
17310235Syasuko.eckert@amd.com    demandHits = SUM_DEMAND(hits);
17410235Syasuko.eckert@amd.com    for (int i = 0; i < system->maxMasters(); i++) {
17510235Syasuko.eckert@amd.com        demandHits.subname(i, system->getMasterName(i));
17610235Syasuko.eckert@amd.com    }
17710235Syasuko.eckert@amd.com
17810235Syasuko.eckert@amd.com    overallHits
17910235Syasuko.eckert@amd.com        .name(name() + ".overall_hits")
18010235Syasuko.eckert@amd.com        .desc("number of overall hits")
18110235Syasuko.eckert@amd.com        .flags(total | nozero | nonan)
18210235Syasuko.eckert@amd.com        ;
18310235Syasuko.eckert@amd.com    overallHits = demandHits + SUM_NON_DEMAND(hits);
18410235Syasuko.eckert@amd.com    for (int i = 0; i < system->maxMasters(); i++) {
18510235Syasuko.eckert@amd.com        overallHits.subname(i, system->getMasterName(i));
18610235Syasuko.eckert@amd.com    }
18710235Syasuko.eckert@amd.com
18810235Syasuko.eckert@amd.com    // Miss statistics
18910235Syasuko.eckert@amd.com    for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
19010235Syasuko.eckert@amd.com        MemCmd cmd(access_idx);
19110235Syasuko.eckert@amd.com        const string &cstr = cmd.toString();
19210235Syasuko.eckert@amd.com
19310235Syasuko.eckert@amd.com        misses[access_idx]
19410235Syasuko.eckert@amd.com            .init(system->maxMasters())
19510235Syasuko.eckert@amd.com            .name(name() + "." + cstr + "_misses")
19610235Syasuko.eckert@amd.com            .desc("number of " + cstr + " misses")
19710235Syasuko.eckert@amd.com            .flags(total | nozero | nonan)
19810235Syasuko.eckert@amd.com            ;
19910235Syasuko.eckert@amd.com        for (int i = 0; i < system->maxMasters(); i++) {
20010235Syasuko.eckert@amd.com            misses[access_idx].subname(i, system->getMasterName(i));
20110235Syasuko.eckert@amd.com        }
20210235Syasuko.eckert@amd.com    }
20310235Syasuko.eckert@amd.com
20410235Syasuko.eckert@amd.com    demandMisses
20510235Syasuko.eckert@amd.com        .name(name() + ".demand_misses")
20610235Syasuko.eckert@amd.com        .desc("number of demand (read+write) misses")
20710235Syasuko.eckert@amd.com        .flags(total | nozero | nonan)
20810235Syasuko.eckert@amd.com        ;
20910235Syasuko.eckert@amd.com    demandMisses = SUM_DEMAND(misses);
21010235Syasuko.eckert@amd.com    for (int i = 0; i < system->maxMasters(); i++) {
21110235Syasuko.eckert@amd.com        demandMisses.subname(i, system->getMasterName(i));
21210235Syasuko.eckert@amd.com    }
21310235Syasuko.eckert@amd.com
21410235Syasuko.eckert@amd.com    overallMisses
21510235Syasuko.eckert@amd.com        .name(name() + ".overall_misses")
21610235Syasuko.eckert@amd.com        .desc("number of overall misses")
21710235Syasuko.eckert@amd.com        .flags(total | nozero | nonan)
21810235Syasuko.eckert@amd.com        ;
21910235Syasuko.eckert@amd.com    overallMisses = demandMisses + SUM_NON_DEMAND(misses);
22010235Syasuko.eckert@amd.com    for (int i = 0; i < system->maxMasters(); i++) {
22110235Syasuko.eckert@amd.com        overallMisses.subname(i, system->getMasterName(i));
22210235Syasuko.eckert@amd.com    }
22310235Syasuko.eckert@amd.com
22410235Syasuko.eckert@amd.com    // Miss latency statistics
22510235Syasuko.eckert@amd.com    for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
22610235Syasuko.eckert@amd.com        MemCmd cmd(access_idx);
22710235Syasuko.eckert@amd.com        const string &cstr = cmd.toString();
22810235Syasuko.eckert@amd.com
22910235Syasuko.eckert@amd.com        missLatency[access_idx]
23010235Syasuko.eckert@amd.com            .init(system->maxMasters())
23110235Syasuko.eckert@amd.com            .name(name() + "." + cstr + "_miss_latency")
23210235Syasuko.eckert@amd.com            .desc("number of " + cstr + " miss cycles")
23310235Syasuko.eckert@amd.com            .flags(total | nozero | nonan)
23410235Syasuko.eckert@amd.com            ;
23510235Syasuko.eckert@amd.com        for (int i = 0; i < system->maxMasters(); i++) {
23610235Syasuko.eckert@amd.com            missLatency[access_idx].subname(i, system->getMasterName(i));
23710235Syasuko.eckert@amd.com        }
23810235Syasuko.eckert@amd.com    }
23910235Syasuko.eckert@amd.com
24010235Syasuko.eckert@amd.com    demandMissLatency
24110235Syasuko.eckert@amd.com        .name(name() + ".demand_miss_latency")
242        .desc("number of demand (read+write) miss cycles")
243        .flags(total | nozero | nonan)
244        ;
245    demandMissLatency = SUM_DEMAND(missLatency);
246    for (int i = 0; i < system->maxMasters(); i++) {
247        demandMissLatency.subname(i, system->getMasterName(i));
248    }
249
250    overallMissLatency
251        .name(name() + ".overall_miss_latency")
252        .desc("number of overall miss cycles")
253        .flags(total | nozero | nonan)
254        ;
255    overallMissLatency = demandMissLatency + SUM_NON_DEMAND(missLatency);
256    for (int i = 0; i < system->maxMasters(); i++) {
257        overallMissLatency.subname(i, system->getMasterName(i));
258    }
259
260    // access formulas
261    for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
262        MemCmd cmd(access_idx);
263        const string &cstr = cmd.toString();
264
265        accesses[access_idx]
266            .name(name() + "." + cstr + "_accesses")
267            .desc("number of " + cstr + " accesses(hits+misses)")
268            .flags(total | nozero | nonan)
269            ;
270        accesses[access_idx] = hits[access_idx] + misses[access_idx];
271
272        for (int i = 0; i < system->maxMasters(); i++) {
273            accesses[access_idx].subname(i, system->getMasterName(i));
274        }
275    }
276
277    demandAccesses
278        .name(name() + ".demand_accesses")
279        .desc("number of demand (read+write) accesses")
280        .flags(total | nozero | nonan)
281        ;
282    demandAccesses = demandHits + demandMisses;
283    for (int i = 0; i < system->maxMasters(); i++) {
284        demandAccesses.subname(i, system->getMasterName(i));
285    }
286
287    overallAccesses
288        .name(name() + ".overall_accesses")
289        .desc("number of overall (read+write) accesses")
290        .flags(total | nozero | nonan)
291        ;
292    overallAccesses = overallHits + overallMisses;
293    for (int i = 0; i < system->maxMasters(); i++) {
294        overallAccesses.subname(i, system->getMasterName(i));
295    }
296
297    // miss rate formulas
298    for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
299        MemCmd cmd(access_idx);
300        const string &cstr = cmd.toString();
301
302        missRate[access_idx]
303            .name(name() + "." + cstr + "_miss_rate")
304            .desc("miss rate for " + cstr + " accesses")
305            .flags(total | nozero | nonan)
306            ;
307        missRate[access_idx] = misses[access_idx] / accesses[access_idx];
308
309        for (int i = 0; i < system->maxMasters(); i++) {
310            missRate[access_idx].subname(i, system->getMasterName(i));
311        }
312    }
313
314    demandMissRate
315        .name(name() + ".demand_miss_rate")
316        .desc("miss rate for demand accesses")
317        .flags(total | nozero | nonan)
318        ;
319    demandMissRate = demandMisses / demandAccesses;
320    for (int i = 0; i < system->maxMasters(); i++) {
321        demandMissRate.subname(i, system->getMasterName(i));
322    }
323
324    overallMissRate
325        .name(name() + ".overall_miss_rate")
326        .desc("miss rate for overall accesses")
327        .flags(total | nozero | nonan)
328        ;
329    overallMissRate = overallMisses / overallAccesses;
330    for (int i = 0; i < system->maxMasters(); i++) {
331        overallMissRate.subname(i, system->getMasterName(i));
332    }
333
334    // miss latency formulas
335    for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
336        MemCmd cmd(access_idx);
337        const string &cstr = cmd.toString();
338
339        avgMissLatency[access_idx]
340            .name(name() + "." + cstr + "_avg_miss_latency")
341            .desc("average " + cstr + " miss latency")
342            .flags(total | nozero | nonan)
343            ;
344        avgMissLatency[access_idx] =
345            missLatency[access_idx] / misses[access_idx];
346
347        for (int i = 0; i < system->maxMasters(); i++) {
348            avgMissLatency[access_idx].subname(i, system->getMasterName(i));
349        }
350    }
351
352    demandAvgMissLatency
353        .name(name() + ".demand_avg_miss_latency")
354        .desc("average overall miss latency")
355        .flags(total | nozero | nonan)
356        ;
357    demandAvgMissLatency = demandMissLatency / demandMisses;
358    for (int i = 0; i < system->maxMasters(); i++) {
359        demandAvgMissLatency.subname(i, system->getMasterName(i));
360    }
361
362    overallAvgMissLatency
363        .name(name() + ".overall_avg_miss_latency")
364        .desc("average overall miss latency")
365        .flags(total | nozero | nonan)
366        ;
367    overallAvgMissLatency = overallMissLatency / overallMisses;
368    for (int i = 0; i < system->maxMasters(); i++) {
369        overallAvgMissLatency.subname(i, system->getMasterName(i));
370    }
371
372    blocked_cycles.init(NUM_BLOCKED_CAUSES);
373    blocked_cycles
374        .name(name() + ".blocked_cycles")
375        .desc("number of cycles access was blocked")
376        .subname(Blocked_NoMSHRs, "no_mshrs")
377        .subname(Blocked_NoTargets, "no_targets")
378        ;
379
380
381    blocked_causes.init(NUM_BLOCKED_CAUSES);
382    blocked_causes
383        .name(name() + ".blocked")
384        .desc("number of cycles access was blocked")
385        .subname(Blocked_NoMSHRs, "no_mshrs")
386        .subname(Blocked_NoTargets, "no_targets")
387        ;
388
389    avg_blocked
390        .name(name() + ".avg_blocked_cycles")
391        .desc("average number of cycles each access was blocked")
392        .subname(Blocked_NoMSHRs, "no_mshrs")
393        .subname(Blocked_NoTargets, "no_targets")
394        ;
395
396    avg_blocked = blocked_cycles / blocked_causes;
397
398    fastWrites
399        .name(name() + ".fast_writes")
400        .desc("number of fast writes performed")
401        ;
402
403    cacheCopies
404        .name(name() + ".cache_copies")
405        .desc("number of cache copies performed")
406        ;
407
408    writebacks
409        .init(system->maxMasters())
410        .name(name() + ".writebacks")
411        .desc("number of writebacks")
412        .flags(total | nozero | nonan)
413        ;
414    for (int i = 0; i < system->maxMasters(); i++) {
415        writebacks.subname(i, system->getMasterName(i));
416    }
417
418    // MSHR statistics
419    // MSHR hit statistics
420    for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
421        MemCmd cmd(access_idx);
422        const string &cstr = cmd.toString();
423
424        mshr_hits[access_idx]
425            .init(system->maxMasters())
426            .name(name() + "." + cstr + "_mshr_hits")
427            .desc("number of " + cstr + " MSHR hits")
428            .flags(total | nozero | nonan)
429            ;
430        for (int i = 0; i < system->maxMasters(); i++) {
431            mshr_hits[access_idx].subname(i, system->getMasterName(i));
432        }
433    }
434
435    demandMshrHits
436        .name(name() + ".demand_mshr_hits")
437        .desc("number of demand (read+write) MSHR hits")
438        .flags(total | nozero | nonan)
439        ;
440    demandMshrHits = SUM_DEMAND(mshr_hits);
441    for (int i = 0; i < system->maxMasters(); i++) {
442        demandMshrHits.subname(i, system->getMasterName(i));
443    }
444
445    overallMshrHits
446        .name(name() + ".overall_mshr_hits")
447        .desc("number of overall MSHR hits")
448        .flags(total | nozero | nonan)
449        ;
450    overallMshrHits = demandMshrHits + SUM_NON_DEMAND(mshr_hits);
451    for (int i = 0; i < system->maxMasters(); i++) {
452        overallMshrHits.subname(i, system->getMasterName(i));
453    }
454
455    // MSHR miss statistics
456    for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
457        MemCmd cmd(access_idx);
458        const string &cstr = cmd.toString();
459
460        mshr_misses[access_idx]
461            .init(system->maxMasters())
462            .name(name() + "." + cstr + "_mshr_misses")
463            .desc("number of " + cstr + " MSHR misses")
464            .flags(total | nozero | nonan)
465            ;
466        for (int i = 0; i < system->maxMasters(); i++) {
467            mshr_misses[access_idx].subname(i, system->getMasterName(i));
468        }
469    }
470
471    demandMshrMisses
472        .name(name() + ".demand_mshr_misses")
473        .desc("number of demand (read+write) MSHR misses")
474        .flags(total | nozero | nonan)
475        ;
476    demandMshrMisses = SUM_DEMAND(mshr_misses);
477    for (int i = 0; i < system->maxMasters(); i++) {
478        demandMshrMisses.subname(i, system->getMasterName(i));
479    }
480
481    overallMshrMisses
482        .name(name() + ".overall_mshr_misses")
483        .desc("number of overall MSHR misses")
484        .flags(total | nozero | nonan)
485        ;
486    overallMshrMisses = demandMshrMisses + SUM_NON_DEMAND(mshr_misses);
487    for (int i = 0; i < system->maxMasters(); i++) {
488        overallMshrMisses.subname(i, system->getMasterName(i));
489    }
490
491    // MSHR miss latency statistics
492    for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
493        MemCmd cmd(access_idx);
494        const string &cstr = cmd.toString();
495
496        mshr_miss_latency[access_idx]
497            .init(system->maxMasters())
498            .name(name() + "." + cstr + "_mshr_miss_latency")
499            .desc("number of " + cstr + " MSHR miss cycles")
500            .flags(total | nozero | nonan)
501            ;
502        for (int i = 0; i < system->maxMasters(); i++) {
503            mshr_miss_latency[access_idx].subname(i, system->getMasterName(i));
504        }
505    }
506
507    demandMshrMissLatency
508        .name(name() + ".demand_mshr_miss_latency")
509        .desc("number of demand (read+write) MSHR miss cycles")
510        .flags(total | nozero | nonan)
511        ;
512    demandMshrMissLatency = SUM_DEMAND(mshr_miss_latency);
513    for (int i = 0; i < system->maxMasters(); i++) {
514        demandMshrMissLatency.subname(i, system->getMasterName(i));
515    }
516
517    overallMshrMissLatency
518        .name(name() + ".overall_mshr_miss_latency")
519        .desc("number of overall MSHR miss cycles")
520        .flags(total | nozero | nonan)
521        ;
522    overallMshrMissLatency =
523        demandMshrMissLatency + SUM_NON_DEMAND(mshr_miss_latency);
524    for (int i = 0; i < system->maxMasters(); i++) {
525        overallMshrMissLatency.subname(i, system->getMasterName(i));
526    }
527
528    // MSHR uncacheable statistics
529    for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
530        MemCmd cmd(access_idx);
531        const string &cstr = cmd.toString();
532
533        mshr_uncacheable[access_idx]
534            .init(system->maxMasters())
535            .name(name() + "." + cstr + "_mshr_uncacheable")
536            .desc("number of " + cstr + " MSHR uncacheable")
537            .flags(total | nozero | nonan)
538            ;
539        for (int i = 0; i < system->maxMasters(); i++) {
540            mshr_uncacheable[access_idx].subname(i, system->getMasterName(i));
541        }
542    }
543
544    overallMshrUncacheable
545        .name(name() + ".overall_mshr_uncacheable_misses")
546        .desc("number of overall MSHR uncacheable misses")
547        .flags(total | nozero | nonan)
548        ;
549    overallMshrUncacheable =
550        SUM_DEMAND(mshr_uncacheable) + SUM_NON_DEMAND(mshr_uncacheable);
551    for (int i = 0; i < system->maxMasters(); i++) {
552        overallMshrUncacheable.subname(i, system->getMasterName(i));
553    }
554
555    // MSHR miss latency statistics
556    for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
557        MemCmd cmd(access_idx);
558        const string &cstr = cmd.toString();
559
560        mshr_uncacheable_lat[access_idx]
561            .init(system->maxMasters())
562            .name(name() + "." + cstr + "_mshr_uncacheable_latency")
563            .desc("number of " + cstr + " MSHR uncacheable cycles")
564            .flags(total | nozero | nonan)
565            ;
566        for (int i = 0; i < system->maxMasters(); i++) {
567            mshr_uncacheable_lat[access_idx].subname(i, system->getMasterName(i));
568        }
569    }
570
571    overallMshrUncacheableLatency
572        .name(name() + ".overall_mshr_uncacheable_latency")
573        .desc("number of overall MSHR uncacheable cycles")
574        .flags(total | nozero | nonan)
575        ;
576    overallMshrUncacheableLatency =
577        SUM_DEMAND(mshr_uncacheable_lat) +
578        SUM_NON_DEMAND(mshr_uncacheable_lat);
579    for (int i = 0; i < system->maxMasters(); i++) {
580        overallMshrUncacheableLatency.subname(i, system->getMasterName(i));
581    }
582
583#if 0
584    // MSHR access formulas
585    for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
586        MemCmd cmd(access_idx);
587        const string &cstr = cmd.toString();
588
589        mshrAccesses[access_idx]
590            .name(name() + "." + cstr + "_mshr_accesses")
591            .desc("number of " + cstr + " mshr accesses(hits+misses)")
592            .flags(total | nozero | nonan)
593            ;
594        mshrAccesses[access_idx] =
595            mshr_hits[access_idx] + mshr_misses[access_idx]
596            + mshr_uncacheable[access_idx];
597    }
598
599    demandMshrAccesses
600        .name(name() + ".demand_mshr_accesses")
601        .desc("number of demand (read+write) mshr accesses")
602        .flags(total | nozero | nonan)
603        ;
604    demandMshrAccesses = demandMshrHits + demandMshrMisses;
605
606    overallMshrAccesses
607        .name(name() + ".overall_mshr_accesses")
608        .desc("number of overall (read+write) mshr accesses")
609        .flags(total | nozero | nonan)
610        ;
611    overallMshrAccesses = overallMshrHits + overallMshrMisses
612        + overallMshrUncacheable;
613#endif
614
615    // MSHR miss rate formulas
616    for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
617        MemCmd cmd(access_idx);
618        const string &cstr = cmd.toString();
619
620        mshrMissRate[access_idx]
621            .name(name() + "." + cstr + "_mshr_miss_rate")
622            .desc("mshr miss rate for " + cstr + " accesses")
623            .flags(total | nozero | nonan)
624            ;
625        mshrMissRate[access_idx] =
626            mshr_misses[access_idx] / accesses[access_idx];
627
628        for (int i = 0; i < system->maxMasters(); i++) {
629            mshrMissRate[access_idx].subname(i, system->getMasterName(i));
630        }
631    }
632
633    demandMshrMissRate
634        .name(name() + ".demand_mshr_miss_rate")
635        .desc("mshr miss rate for demand accesses")
636        .flags(total | nozero | nonan)
637        ;
638    demandMshrMissRate = demandMshrMisses / demandAccesses;
639    for (int i = 0; i < system->maxMasters(); i++) {
640        demandMshrMissRate.subname(i, system->getMasterName(i));
641    }
642
643    overallMshrMissRate
644        .name(name() + ".overall_mshr_miss_rate")
645        .desc("mshr miss rate for overall accesses")
646        .flags(total | nozero | nonan)
647        ;
648    overallMshrMissRate = overallMshrMisses / overallAccesses;
649    for (int i = 0; i < system->maxMasters(); i++) {
650        overallMshrMissRate.subname(i, system->getMasterName(i));
651    }
652
653    // mshrMiss latency formulas
654    for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
655        MemCmd cmd(access_idx);
656        const string &cstr = cmd.toString();
657
658        avgMshrMissLatency[access_idx]
659            .name(name() + "." + cstr + "_avg_mshr_miss_latency")
660            .desc("average " + cstr + " mshr miss latency")
661            .flags(total | nozero | nonan)
662            ;
663        avgMshrMissLatency[access_idx] =
664            mshr_miss_latency[access_idx] / mshr_misses[access_idx];
665
666        for (int i = 0; i < system->maxMasters(); i++) {
667            avgMshrMissLatency[access_idx].subname(i, system->getMasterName(i));
668        }
669    }
670
671    demandAvgMshrMissLatency
672        .name(name() + ".demand_avg_mshr_miss_latency")
673        .desc("average overall mshr miss latency")
674        .flags(total | nozero | nonan)
675        ;
676    demandAvgMshrMissLatency = demandMshrMissLatency / demandMshrMisses;
677    for (int i = 0; i < system->maxMasters(); i++) {
678        demandAvgMshrMissLatency.subname(i, system->getMasterName(i));
679    }
680
681    overallAvgMshrMissLatency
682        .name(name() + ".overall_avg_mshr_miss_latency")
683        .desc("average overall mshr miss latency")
684        .flags(total | nozero | nonan)
685        ;
686    overallAvgMshrMissLatency = overallMshrMissLatency / overallMshrMisses;
687    for (int i = 0; i < system->maxMasters(); i++) {
688        overallAvgMshrMissLatency.subname(i, system->getMasterName(i));
689    }
690
691    // mshrUncacheable latency formulas
692    for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
693        MemCmd cmd(access_idx);
694        const string &cstr = cmd.toString();
695
696        avgMshrUncacheableLatency[access_idx]
697            .name(name() + "." + cstr + "_avg_mshr_uncacheable_latency")
698            .desc("average " + cstr + " mshr uncacheable latency")
699            .flags(total | nozero | nonan)
700            ;
701        avgMshrUncacheableLatency[access_idx] =
702            mshr_uncacheable_lat[access_idx] / mshr_uncacheable[access_idx];
703
704        for (int i = 0; i < system->maxMasters(); i++) {
705            avgMshrUncacheableLatency[access_idx].subname(i, system->getMasterName(i));
706        }
707    }
708
709    overallAvgMshrUncacheableLatency
710        .name(name() + ".overall_avg_mshr_uncacheable_latency")
711        .desc("average overall mshr uncacheable latency")
712        .flags(total | nozero | nonan)
713        ;
714    overallAvgMshrUncacheableLatency = overallMshrUncacheableLatency / overallMshrUncacheable;
715    for (int i = 0; i < system->maxMasters(); i++) {
716        overallAvgMshrUncacheableLatency.subname(i, system->getMasterName(i));
717    }
718
719    mshr_cap_events
720        .init(system->maxMasters())
721        .name(name() + ".mshr_cap_events")
722        .desc("number of times MSHR cap was activated")
723        .flags(total | nozero | nonan)
724        ;
725    for (int i = 0; i < system->maxMasters(); i++) {
726        mshr_cap_events.subname(i, system->getMasterName(i));
727    }
728
729    //software prefetching stats
730    soft_prefetch_mshr_full
731        .init(system->maxMasters())
732        .name(name() + ".soft_prefetch_mshr_full")
733        .desc("number of mshr full events for SW prefetching instrutions")
734        .flags(total | nozero | nonan)
735        ;
736    for (int i = 0; i < system->maxMasters(); i++) {
737        soft_prefetch_mshr_full.subname(i, system->getMasterName(i));
738    }
739
740    mshr_no_allocate_misses
741        .name(name() +".no_allocate_misses")
742        .desc("Number of misses that were no-allocate")
743        ;
744
745}
746
747unsigned int
748BaseCache::drain(Event *de)
749{
750    int count = memSidePort->drain(de) + cpuSidePort->drain(de);
751
752    // Set status
753    if (count != 0) {
754        drainEvent = de;
755
756        changeState(SimObject::Draining);
757        DPRINTF(Drain, "Cache not drained\n");
758        return count;
759    }
760
761    changeState(SimObject::Drained);
762    return 0;
763}
764