base.cc revision 10344:fa9ef374075f
1545SN/A/*
29814Sandreas.hansson@arm.com * Copyright (c) 2012-2013 ARM Limited
38948SN/A * All rights reserved.
48948SN/A *
58948SN/A * The license below extends only to copyright in the software and shall
68948SN/A * not be construed as granting a license to any other intellectual
78948SN/A * property including but not limited to intellectual property relating
88948SN/A * to a hardware implementation of the functionality of the software
98948SN/A * licensed hereunder.  You may use the software subject to the license
108948SN/A * terms below provided that you ensure that this notice is replicated
118948SN/A * unmodified and in its entirety in all distributions of the software,
128948SN/A * modified or unmodified, in source code or in binary form.
138948SN/A *
141762SN/A * Copyright (c) 2003-2005 The Regents of The University of Michigan
15545SN/A * All rights reserved.
16545SN/A *
17545SN/A * Redistribution and use in source and binary forms, with or without
18545SN/A * modification, are permitted provided that the following conditions are
19545SN/A * met: redistributions of source code must retain the above copyright
20545SN/A * notice, this list of conditions and the following disclaimer;
21545SN/A * redistributions in binary form must reproduce the above copyright
22545SN/A * notice, this list of conditions and the following disclaimer in the
23545SN/A * documentation and/or other materials provided with the distribution;
24545SN/A * neither the name of the copyright holders nor the names of its
25545SN/A * contributors may be used to endorse or promote products derived from
26545SN/A * this software without specific prior written permission.
27545SN/A *
28545SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
29545SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
30545SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
31545SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
32545SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
33545SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
34545SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
35545SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
36545SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
37545SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
38545SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
392665SN/A *
402665SN/A * Authors: Erik Hallnor
412665SN/A */
42545SN/A
43545SN/A/**
449016Sandreas.hansson@arm.com * @file
459016Sandreas.hansson@arm.com * Definition of BaseCache functions.
46545SN/A */
479166Sandreas.hansson@arm.com
489166Sandreas.hansson@arm.com#include "debug/Cache.hh"
499016Sandreas.hansson@arm.com#include "debug/Drain.hh"
504762SN/A#include "mem/cache/tags/fa_lru.hh"
519342SAndreas.Sandberg@arm.com#include "mem/cache/tags/lru.hh"
529814Sandreas.hansson@arm.com#include "mem/cache/tags/random_repl.hh"
532565SN/A#include "mem/cache/base.hh"
5410912Sandreas.sandberg@arm.com#include "mem/cache/cache.hh"
552384SN/A#include "mem/cache/mshr.hh"
569307Sandreas.hansson@arm.com#include "sim/full_system.hh"
572784SN/A
589307Sandreas.hansson@arm.comusing namespace std;
599307Sandreas.hansson@arm.com
609307Sandreas.hansson@arm.comBaseCache::CacheSlavePort::CacheSlavePort(const std::string &_name,
619307Sandreas.hansson@arm.com                                          BaseCache *_cache,
629307Sandreas.hansson@arm.com                                          const std::string &_label)
639307Sandreas.hansson@arm.com    : QueuedSlavePort(_name, _cache, queue), queue(*_cache, *this, _label),
649307Sandreas.hansson@arm.com      blocked(false), mustSendRetry(false), sendRetryEvent(this)
652784SN/A{
669307Sandreas.hansson@arm.com}
679307Sandreas.hansson@arm.com
689307Sandreas.hansson@arm.comBaseCache::BaseCache(const Params *p)
699307Sandreas.hansson@arm.com    : MemObject(p),
709307Sandreas.hansson@arm.com      mshrQueue("MSHRs", p->mshrs, 4, MSHRQueue_MSHRs),
719307Sandreas.hansson@arm.com      writeBuffer("write buffer", p->write_buffers, p->mshrs+1000,
729307Sandreas.hansson@arm.com                  MSHRQueue_WriteBuffer),
739307Sandreas.hansson@arm.com      blkSize(p->system->cacheLineSize()),
744435SN/A      hitLatency(p->hit_latency),
759166Sandreas.hansson@arm.com      responseLatency(p->response_latency),
769166Sandreas.hansson@arm.com      numTarget(p->tgts_per_mshr),
779166Sandreas.hansson@arm.com      forwardSnoops(p->forward_snoops),
789166Sandreas.hansson@arm.com      isTopLevel(p->is_top_level),
799166Sandreas.hansson@arm.com      blocked(0),
809166Sandreas.hansson@arm.com      noTargetMSHR(NULL),
819166Sandreas.hansson@arm.com      missCount(p->max_miss_count),
829166Sandreas.hansson@arm.com      addrRanges(p->addr_ranges.begin(), p->addr_ranges.end()),
839166Sandreas.hansson@arm.com      system(p->system)
849166Sandreas.hansson@arm.com{
859166Sandreas.hansson@arm.com}
868948SN/A
879307Sandreas.hansson@arm.comvoid
889307Sandreas.hansson@arm.comBaseCache::CacheSlavePort::setBlocked()
899307Sandreas.hansson@arm.com{
909307Sandreas.hansson@arm.com    assert(!blocked);
919307Sandreas.hansson@arm.com    DPRINTF(CachePort, "Cache port %s blocking new requests\n", name());
929307Sandreas.hansson@arm.com    blocked = true;
939307Sandreas.hansson@arm.com    // if we already scheduled a retry in this cycle, but it has not yet
949307Sandreas.hansson@arm.com    // happened, cancel it
959307Sandreas.hansson@arm.com    if (sendRetryEvent.scheduled()) {
969307Sandreas.hansson@arm.com       owner.deschedule(sendRetryEvent);
979307Sandreas.hansson@arm.com       DPRINTF(CachePort, "Cache port %s deschedule retry\n", name());
989307Sandreas.hansson@arm.com       mustSendRetry = true;
999307Sandreas.hansson@arm.com    }
1009307Sandreas.hansson@arm.com}
1019307Sandreas.hansson@arm.com
1029307Sandreas.hansson@arm.comvoid
1039307Sandreas.hansson@arm.comBaseCache::CacheSlavePort::clearBlocked()
1049307Sandreas.hansson@arm.com{
1059307Sandreas.hansson@arm.com    assert(blocked);
1069307Sandreas.hansson@arm.com    DPRINTF(CachePort, "Cache port %s accepting new requests\n", name());
1079307Sandreas.hansson@arm.com    blocked = false;
1089307Sandreas.hansson@arm.com    if (mustSendRetry) {
1099307Sandreas.hansson@arm.com        // @TODO: need to find a better time (next bus cycle?)
1109307Sandreas.hansson@arm.com        owner.schedule(sendRetryEvent, curTick() + 1);
1119307Sandreas.hansson@arm.com    }
1129307Sandreas.hansson@arm.com}
1139307Sandreas.hansson@arm.com
1149307Sandreas.hansson@arm.comvoid
1159307Sandreas.hansson@arm.comBaseCache::CacheSlavePort::processSendRetry()
1169307Sandreas.hansson@arm.com{
1179307Sandreas.hansson@arm.com    DPRINTF(CachePort, "Cache port %s sending retry\n", name());
1189307Sandreas.hansson@arm.com
1199307Sandreas.hansson@arm.com    // reset the flag and call retry
1209307Sandreas.hansson@arm.com    mustSendRetry = false;
1219307Sandreas.hansson@arm.com    sendRetry();
1229307Sandreas.hansson@arm.com}
1239307Sandreas.hansson@arm.com
1249307Sandreas.hansson@arm.comvoid
1259307Sandreas.hansson@arm.comBaseCache::init()
1269307Sandreas.hansson@arm.com{
1279307Sandreas.hansson@arm.com    if (!cpuSidePort->isConnected() || !memSidePort->isConnected())
1289307Sandreas.hansson@arm.com        fatal("Cache ports on %s are not connected\n", name());
1299307Sandreas.hansson@arm.com    cpuSidePort->sendRangeChange();
1309307Sandreas.hansson@arm.com}
1319307Sandreas.hansson@arm.com
1329166Sandreas.hansson@arm.comBaseMasterPort &
13310713Sandreas.hansson@arm.comBaseCache::getMasterPort(const std::string &if_name, PortID idx)
1342384SN/A{
1359166Sandreas.hansson@arm.com    if (if_name == "mem_side") {
1364435SN/A        return *memSidePort;
1379165Sandreas.hansson@arm.com    }  else {
1382489SN/A        return MemObject::getMasterPort(if_name, idx);
1399165Sandreas.hansson@arm.com    }
1402565SN/A}
14110621SCurtis.Dunham@arm.com
14210621SCurtis.Dunham@arm.comBaseSlavePort &
1432565SN/ABaseCache::getSlavePort(const std::string &if_name, PortID idx)
1449166Sandreas.hansson@arm.com{
1452384SN/A    if (if_name == "cpu_side") {
14610913Sandreas.sandberg@arm.com        return *cpuSidePort;
1472384SN/A    } else {
1482384SN/A        return MemObject::getSlavePort(if_name, idx);
149545SN/A    }
150545SN/A}
1514435SN/A
1528851SN/Avoid
153545SN/ABaseCache::regStats()
154545SN/A{
1554762SN/A    using namespace Stats;
1564762SN/A
1579166Sandreas.hansson@arm.com    // Hit statistics
1584762SN/A    for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
1598851SN/A        MemCmd cmd(access_idx);
1608851SN/A        const string &cstr = cmd.toString();
1614022SN/A
1628851SN/A        hits[access_idx]
1634022SN/A            .init(system->maxMasters())
1642565SN/A            .name(name() + "." + cstr + "_hits")
1658851SN/A            .desc("number of " + cstr + " hits")
1668851SN/A            .flags(total | nozero | nonan)
1674263SN/A            ;
1688851SN/A        for (int i = 0; i < system->maxMasters(); i++) {
1694263SN/A            hits[access_idx].subname(i, system->getMasterName(i));
1702565SN/A        }
1719307Sandreas.hansson@arm.com    }
1728851SN/A
1738851SN/A// These macros make it easier to sum the right subset of commands and
1742565SN/A// to change the subset of commands that are considered "demand" vs
1759814Sandreas.hansson@arm.com// "non-demand"
1764263SN/A#define SUM_DEMAND(s) \
1779294Sandreas.hansson@arm.com    (s[MemCmd::ReadReq] + s[MemCmd::WriteReq] + s[MemCmd::ReadExReq])
1789294Sandreas.hansson@arm.com
1792489SN/A// should writebacks be included here?  prior code was inconsistent...
180545SN/A#define SUM_NON_DEMAND(s) \
181545SN/A    (s[MemCmd::SoftPFReq] + s[MemCmd::HardPFReq])
1829016Sandreas.hansson@arm.com
183    demandHits
184        .name(name() + ".demand_hits")
185        .desc("number of demand (read+write) hits")
186        .flags(total | nozero | nonan)
187        ;
188    demandHits = SUM_DEMAND(hits);
189    for (int i = 0; i < system->maxMasters(); i++) {
190        demandHits.subname(i, system->getMasterName(i));
191    }
192
193    overallHits
194        .name(name() + ".overall_hits")
195        .desc("number of overall hits")
196        .flags(total | nozero | nonan)
197        ;
198    overallHits = demandHits + SUM_NON_DEMAND(hits);
199    for (int i = 0; i < system->maxMasters(); i++) {
200        overallHits.subname(i, system->getMasterName(i));
201    }
202
203    // Miss statistics
204    for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
205        MemCmd cmd(access_idx);
206        const string &cstr = cmd.toString();
207
208        misses[access_idx]
209            .init(system->maxMasters())
210            .name(name() + "." + cstr + "_misses")
211            .desc("number of " + cstr + " misses")
212            .flags(total | nozero | nonan)
213            ;
214        for (int i = 0; i < system->maxMasters(); i++) {
215            misses[access_idx].subname(i, system->getMasterName(i));
216        }
217    }
218
219    demandMisses
220        .name(name() + ".demand_misses")
221        .desc("number of demand (read+write) misses")
222        .flags(total | nozero | nonan)
223        ;
224    demandMisses = SUM_DEMAND(misses);
225    for (int i = 0; i < system->maxMasters(); i++) {
226        demandMisses.subname(i, system->getMasterName(i));
227    }
228
229    overallMisses
230        .name(name() + ".overall_misses")
231        .desc("number of overall misses")
232        .flags(total | nozero | nonan)
233        ;
234    overallMisses = demandMisses + SUM_NON_DEMAND(misses);
235    for (int i = 0; i < system->maxMasters(); i++) {
236        overallMisses.subname(i, system->getMasterName(i));
237    }
238
239    // Miss latency statistics
240    for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
241        MemCmd cmd(access_idx);
242        const string &cstr = cmd.toString();
243
244        missLatency[access_idx]
245            .init(system->maxMasters())
246            .name(name() + "." + cstr + "_miss_latency")
247            .desc("number of " + cstr + " miss cycles")
248            .flags(total | nozero | nonan)
249            ;
250        for (int i = 0; i < system->maxMasters(); i++) {
251            missLatency[access_idx].subname(i, system->getMasterName(i));
252        }
253    }
254
255    demandMissLatency
256        .name(name() + ".demand_miss_latency")
257        .desc("number of demand (read+write) miss cycles")
258        .flags(total | nozero | nonan)
259        ;
260    demandMissLatency = SUM_DEMAND(missLatency);
261    for (int i = 0; i < system->maxMasters(); i++) {
262        demandMissLatency.subname(i, system->getMasterName(i));
263    }
264
265    overallMissLatency
266        .name(name() + ".overall_miss_latency")
267        .desc("number of overall miss cycles")
268        .flags(total | nozero | nonan)
269        ;
270    overallMissLatency = demandMissLatency + SUM_NON_DEMAND(missLatency);
271    for (int i = 0; i < system->maxMasters(); i++) {
272        overallMissLatency.subname(i, system->getMasterName(i));
273    }
274
275    // access formulas
276    for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
277        MemCmd cmd(access_idx);
278        const string &cstr = cmd.toString();
279
280        accesses[access_idx]
281            .name(name() + "." + cstr + "_accesses")
282            .desc("number of " + cstr + " accesses(hits+misses)")
283            .flags(total | nozero | nonan)
284            ;
285        accesses[access_idx] = hits[access_idx] + misses[access_idx];
286
287        for (int i = 0; i < system->maxMasters(); i++) {
288            accesses[access_idx].subname(i, system->getMasterName(i));
289        }
290    }
291
292    demandAccesses
293        .name(name() + ".demand_accesses")
294        .desc("number of demand (read+write) accesses")
295        .flags(total | nozero | nonan)
296        ;
297    demandAccesses = demandHits + demandMisses;
298    for (int i = 0; i < system->maxMasters(); i++) {
299        demandAccesses.subname(i, system->getMasterName(i));
300    }
301
302    overallAccesses
303        .name(name() + ".overall_accesses")
304        .desc("number of overall (read+write) accesses")
305        .flags(total | nozero | nonan)
306        ;
307    overallAccesses = overallHits + overallMisses;
308    for (int i = 0; i < system->maxMasters(); i++) {
309        overallAccesses.subname(i, system->getMasterName(i));
310    }
311
312    // miss rate formulas
313    for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
314        MemCmd cmd(access_idx);
315        const string &cstr = cmd.toString();
316
317        missRate[access_idx]
318            .name(name() + "." + cstr + "_miss_rate")
319            .desc("miss rate for " + cstr + " accesses")
320            .flags(total | nozero | nonan)
321            ;
322        missRate[access_idx] = misses[access_idx] / accesses[access_idx];
323
324        for (int i = 0; i < system->maxMasters(); i++) {
325            missRate[access_idx].subname(i, system->getMasterName(i));
326        }
327    }
328
329    demandMissRate
330        .name(name() + ".demand_miss_rate")
331        .desc("miss rate for demand accesses")
332        .flags(total | nozero | nonan)
333        ;
334    demandMissRate = demandMisses / demandAccesses;
335    for (int i = 0; i < system->maxMasters(); i++) {
336        demandMissRate.subname(i, system->getMasterName(i));
337    }
338
339    overallMissRate
340        .name(name() + ".overall_miss_rate")
341        .desc("miss rate for overall accesses")
342        .flags(total | nozero | nonan)
343        ;
344    overallMissRate = overallMisses / overallAccesses;
345    for (int i = 0; i < system->maxMasters(); i++) {
346        overallMissRate.subname(i, system->getMasterName(i));
347    }
348
349    // miss latency formulas
350    for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
351        MemCmd cmd(access_idx);
352        const string &cstr = cmd.toString();
353
354        avgMissLatency[access_idx]
355            .name(name() + "." + cstr + "_avg_miss_latency")
356            .desc("average " + cstr + " miss latency")
357            .flags(total | nozero | nonan)
358            ;
359        avgMissLatency[access_idx] =
360            missLatency[access_idx] / misses[access_idx];
361
362        for (int i = 0; i < system->maxMasters(); i++) {
363            avgMissLatency[access_idx].subname(i, system->getMasterName(i));
364        }
365    }
366
367    demandAvgMissLatency
368        .name(name() + ".demand_avg_miss_latency")
369        .desc("average overall miss latency")
370        .flags(total | nozero | nonan)
371        ;
372    demandAvgMissLatency = demandMissLatency / demandMisses;
373    for (int i = 0; i < system->maxMasters(); i++) {
374        demandAvgMissLatency.subname(i, system->getMasterName(i));
375    }
376
377    overallAvgMissLatency
378        .name(name() + ".overall_avg_miss_latency")
379        .desc("average overall miss latency")
380        .flags(total | nozero | nonan)
381        ;
382    overallAvgMissLatency = overallMissLatency / overallMisses;
383    for (int i = 0; i < system->maxMasters(); i++) {
384        overallAvgMissLatency.subname(i, system->getMasterName(i));
385    }
386
387    blocked_cycles.init(NUM_BLOCKED_CAUSES);
388    blocked_cycles
389        .name(name() + ".blocked_cycles")
390        .desc("number of cycles access was blocked")
391        .subname(Blocked_NoMSHRs, "no_mshrs")
392        .subname(Blocked_NoTargets, "no_targets")
393        ;
394
395
396    blocked_causes.init(NUM_BLOCKED_CAUSES);
397    blocked_causes
398        .name(name() + ".blocked")
399        .desc("number of cycles access was blocked")
400        .subname(Blocked_NoMSHRs, "no_mshrs")
401        .subname(Blocked_NoTargets, "no_targets")
402        ;
403
404    avg_blocked
405        .name(name() + ".avg_blocked_cycles")
406        .desc("average number of cycles each access was blocked")
407        .subname(Blocked_NoMSHRs, "no_mshrs")
408        .subname(Blocked_NoTargets, "no_targets")
409        ;
410
411    avg_blocked = blocked_cycles / blocked_causes;
412
413    fastWrites
414        .name(name() + ".fast_writes")
415        .desc("number of fast writes performed")
416        ;
417
418    cacheCopies
419        .name(name() + ".cache_copies")
420        .desc("number of cache copies performed")
421        ;
422
423    writebacks
424        .init(system->maxMasters())
425        .name(name() + ".writebacks")
426        .desc("number of writebacks")
427        .flags(total | nozero | nonan)
428        ;
429    for (int i = 0; i < system->maxMasters(); i++) {
430        writebacks.subname(i, system->getMasterName(i));
431    }
432
433    // MSHR statistics
434    // MSHR hit statistics
435    for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
436        MemCmd cmd(access_idx);
437        const string &cstr = cmd.toString();
438
439        mshr_hits[access_idx]
440            .init(system->maxMasters())
441            .name(name() + "." + cstr + "_mshr_hits")
442            .desc("number of " + cstr + " MSHR hits")
443            .flags(total | nozero | nonan)
444            ;
445        for (int i = 0; i < system->maxMasters(); i++) {
446            mshr_hits[access_idx].subname(i, system->getMasterName(i));
447        }
448    }
449
450    demandMshrHits
451        .name(name() + ".demand_mshr_hits")
452        .desc("number of demand (read+write) MSHR hits")
453        .flags(total | nozero | nonan)
454        ;
455    demandMshrHits = SUM_DEMAND(mshr_hits);
456    for (int i = 0; i < system->maxMasters(); i++) {
457        demandMshrHits.subname(i, system->getMasterName(i));
458    }
459
460    overallMshrHits
461        .name(name() + ".overall_mshr_hits")
462        .desc("number of overall MSHR hits")
463        .flags(total | nozero | nonan)
464        ;
465    overallMshrHits = demandMshrHits + SUM_NON_DEMAND(mshr_hits);
466    for (int i = 0; i < system->maxMasters(); i++) {
467        overallMshrHits.subname(i, system->getMasterName(i));
468    }
469
470    // MSHR miss statistics
471    for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
472        MemCmd cmd(access_idx);
473        const string &cstr = cmd.toString();
474
475        mshr_misses[access_idx]
476            .init(system->maxMasters())
477            .name(name() + "." + cstr + "_mshr_misses")
478            .desc("number of " + cstr + " MSHR misses")
479            .flags(total | nozero | nonan)
480            ;
481        for (int i = 0; i < system->maxMasters(); i++) {
482            mshr_misses[access_idx].subname(i, system->getMasterName(i));
483        }
484    }
485
486    demandMshrMisses
487        .name(name() + ".demand_mshr_misses")
488        .desc("number of demand (read+write) MSHR misses")
489        .flags(total | nozero | nonan)
490        ;
491    demandMshrMisses = SUM_DEMAND(mshr_misses);
492    for (int i = 0; i < system->maxMasters(); i++) {
493        demandMshrMisses.subname(i, system->getMasterName(i));
494    }
495
496    overallMshrMisses
497        .name(name() + ".overall_mshr_misses")
498        .desc("number of overall MSHR misses")
499        .flags(total | nozero | nonan)
500        ;
501    overallMshrMisses = demandMshrMisses + SUM_NON_DEMAND(mshr_misses);
502    for (int i = 0; i < system->maxMasters(); i++) {
503        overallMshrMisses.subname(i, system->getMasterName(i));
504    }
505
506    // MSHR miss latency statistics
507    for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
508        MemCmd cmd(access_idx);
509        const string &cstr = cmd.toString();
510
511        mshr_miss_latency[access_idx]
512            .init(system->maxMasters())
513            .name(name() + "." + cstr + "_mshr_miss_latency")
514            .desc("number of " + cstr + " MSHR miss cycles")
515            .flags(total | nozero | nonan)
516            ;
517        for (int i = 0; i < system->maxMasters(); i++) {
518            mshr_miss_latency[access_idx].subname(i, system->getMasterName(i));
519        }
520    }
521
522    demandMshrMissLatency
523        .name(name() + ".demand_mshr_miss_latency")
524        .desc("number of demand (read+write) MSHR miss cycles")
525        .flags(total | nozero | nonan)
526        ;
527    demandMshrMissLatency = SUM_DEMAND(mshr_miss_latency);
528    for (int i = 0; i < system->maxMasters(); i++) {
529        demandMshrMissLatency.subname(i, system->getMasterName(i));
530    }
531
532    overallMshrMissLatency
533        .name(name() + ".overall_mshr_miss_latency")
534        .desc("number of overall MSHR miss cycles")
535        .flags(total | nozero | nonan)
536        ;
537    overallMshrMissLatency =
538        demandMshrMissLatency + SUM_NON_DEMAND(mshr_miss_latency);
539    for (int i = 0; i < system->maxMasters(); i++) {
540        overallMshrMissLatency.subname(i, system->getMasterName(i));
541    }
542
543    // MSHR uncacheable statistics
544    for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
545        MemCmd cmd(access_idx);
546        const string &cstr = cmd.toString();
547
548        mshr_uncacheable[access_idx]
549            .init(system->maxMasters())
550            .name(name() + "." + cstr + "_mshr_uncacheable")
551            .desc("number of " + cstr + " MSHR uncacheable")
552            .flags(total | nozero | nonan)
553            ;
554        for (int i = 0; i < system->maxMasters(); i++) {
555            mshr_uncacheable[access_idx].subname(i, system->getMasterName(i));
556        }
557    }
558
559    overallMshrUncacheable
560        .name(name() + ".overall_mshr_uncacheable_misses")
561        .desc("number of overall MSHR uncacheable misses")
562        .flags(total | nozero | nonan)
563        ;
564    overallMshrUncacheable =
565        SUM_DEMAND(mshr_uncacheable) + SUM_NON_DEMAND(mshr_uncacheable);
566    for (int i = 0; i < system->maxMasters(); i++) {
567        overallMshrUncacheable.subname(i, system->getMasterName(i));
568    }
569
570    // MSHR miss latency statistics
571    for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
572        MemCmd cmd(access_idx);
573        const string &cstr = cmd.toString();
574
575        mshr_uncacheable_lat[access_idx]
576            .init(system->maxMasters())
577            .name(name() + "." + cstr + "_mshr_uncacheable_latency")
578            .desc("number of " + cstr + " MSHR uncacheable cycles")
579            .flags(total | nozero | nonan)
580            ;
581        for (int i = 0; i < system->maxMasters(); i++) {
582            mshr_uncacheable_lat[access_idx].subname(i, system->getMasterName(i));
583        }
584    }
585
586    overallMshrUncacheableLatency
587        .name(name() + ".overall_mshr_uncacheable_latency")
588        .desc("number of overall MSHR uncacheable cycles")
589        .flags(total | nozero | nonan)
590        ;
591    overallMshrUncacheableLatency =
592        SUM_DEMAND(mshr_uncacheable_lat) +
593        SUM_NON_DEMAND(mshr_uncacheable_lat);
594    for (int i = 0; i < system->maxMasters(); i++) {
595        overallMshrUncacheableLatency.subname(i, system->getMasterName(i));
596    }
597
598#if 0
599    // MSHR access formulas
600    for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
601        MemCmd cmd(access_idx);
602        const string &cstr = cmd.toString();
603
604        mshrAccesses[access_idx]
605            .name(name() + "." + cstr + "_mshr_accesses")
606            .desc("number of " + cstr + " mshr accesses(hits+misses)")
607            .flags(total | nozero | nonan)
608            ;
609        mshrAccesses[access_idx] =
610            mshr_hits[access_idx] + mshr_misses[access_idx]
611            + mshr_uncacheable[access_idx];
612    }
613
614    demandMshrAccesses
615        .name(name() + ".demand_mshr_accesses")
616        .desc("number of demand (read+write) mshr accesses")
617        .flags(total | nozero | nonan)
618        ;
619    demandMshrAccesses = demandMshrHits + demandMshrMisses;
620
621    overallMshrAccesses
622        .name(name() + ".overall_mshr_accesses")
623        .desc("number of overall (read+write) mshr accesses")
624        .flags(total | nozero | nonan)
625        ;
626    overallMshrAccesses = overallMshrHits + overallMshrMisses
627        + overallMshrUncacheable;
628#endif
629
630    // MSHR miss rate formulas
631    for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
632        MemCmd cmd(access_idx);
633        const string &cstr = cmd.toString();
634
635        mshrMissRate[access_idx]
636            .name(name() + "." + cstr + "_mshr_miss_rate")
637            .desc("mshr miss rate for " + cstr + " accesses")
638            .flags(total | nozero | nonan)
639            ;
640        mshrMissRate[access_idx] =
641            mshr_misses[access_idx] / accesses[access_idx];
642
643        for (int i = 0; i < system->maxMasters(); i++) {
644            mshrMissRate[access_idx].subname(i, system->getMasterName(i));
645        }
646    }
647
648    demandMshrMissRate
649        .name(name() + ".demand_mshr_miss_rate")
650        .desc("mshr miss rate for demand accesses")
651        .flags(total | nozero | nonan)
652        ;
653    demandMshrMissRate = demandMshrMisses / demandAccesses;
654    for (int i = 0; i < system->maxMasters(); i++) {
655        demandMshrMissRate.subname(i, system->getMasterName(i));
656    }
657
658    overallMshrMissRate
659        .name(name() + ".overall_mshr_miss_rate")
660        .desc("mshr miss rate for overall accesses")
661        .flags(total | nozero | nonan)
662        ;
663    overallMshrMissRate = overallMshrMisses / overallAccesses;
664    for (int i = 0; i < system->maxMasters(); i++) {
665        overallMshrMissRate.subname(i, system->getMasterName(i));
666    }
667
668    // mshrMiss latency formulas
669    for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
670        MemCmd cmd(access_idx);
671        const string &cstr = cmd.toString();
672
673        avgMshrMissLatency[access_idx]
674            .name(name() + "." + cstr + "_avg_mshr_miss_latency")
675            .desc("average " + cstr + " mshr miss latency")
676            .flags(total | nozero | nonan)
677            ;
678        avgMshrMissLatency[access_idx] =
679            mshr_miss_latency[access_idx] / mshr_misses[access_idx];
680
681        for (int i = 0; i < system->maxMasters(); i++) {
682            avgMshrMissLatency[access_idx].subname(i, system->getMasterName(i));
683        }
684    }
685
686    demandAvgMshrMissLatency
687        .name(name() + ".demand_avg_mshr_miss_latency")
688        .desc("average overall mshr miss latency")
689        .flags(total | nozero | nonan)
690        ;
691    demandAvgMshrMissLatency = demandMshrMissLatency / demandMshrMisses;
692    for (int i = 0; i < system->maxMasters(); i++) {
693        demandAvgMshrMissLatency.subname(i, system->getMasterName(i));
694    }
695
696    overallAvgMshrMissLatency
697        .name(name() + ".overall_avg_mshr_miss_latency")
698        .desc("average overall mshr miss latency")
699        .flags(total | nozero | nonan)
700        ;
701    overallAvgMshrMissLatency = overallMshrMissLatency / overallMshrMisses;
702    for (int i = 0; i < system->maxMasters(); i++) {
703        overallAvgMshrMissLatency.subname(i, system->getMasterName(i));
704    }
705
706    // mshrUncacheable latency formulas
707    for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
708        MemCmd cmd(access_idx);
709        const string &cstr = cmd.toString();
710
711        avgMshrUncacheableLatency[access_idx]
712            .name(name() + "." + cstr + "_avg_mshr_uncacheable_latency")
713            .desc("average " + cstr + " mshr uncacheable latency")
714            .flags(total | nozero | nonan)
715            ;
716        avgMshrUncacheableLatency[access_idx] =
717            mshr_uncacheable_lat[access_idx] / mshr_uncacheable[access_idx];
718
719        for (int i = 0; i < system->maxMasters(); i++) {
720            avgMshrUncacheableLatency[access_idx].subname(i, system->getMasterName(i));
721        }
722    }
723
724    overallAvgMshrUncacheableLatency
725        .name(name() + ".overall_avg_mshr_uncacheable_latency")
726        .desc("average overall mshr uncacheable latency")
727        .flags(total | nozero | nonan)
728        ;
729    overallAvgMshrUncacheableLatency = overallMshrUncacheableLatency / overallMshrUncacheable;
730    for (int i = 0; i < system->maxMasters(); i++) {
731        overallAvgMshrUncacheableLatency.subname(i, system->getMasterName(i));
732    }
733
734    mshr_cap_events
735        .init(system->maxMasters())
736        .name(name() + ".mshr_cap_events")
737        .desc("number of times MSHR cap was activated")
738        .flags(total | nozero | nonan)
739        ;
740    for (int i = 0; i < system->maxMasters(); i++) {
741        mshr_cap_events.subname(i, system->getMasterName(i));
742    }
743
744    //software prefetching stats
745    soft_prefetch_mshr_full
746        .init(system->maxMasters())
747        .name(name() + ".soft_prefetch_mshr_full")
748        .desc("number of mshr full events for SW prefetching instrutions")
749        .flags(total | nozero | nonan)
750        ;
751    for (int i = 0; i < system->maxMasters(); i++) {
752        soft_prefetch_mshr_full.subname(i, system->getMasterName(i));
753    }
754
755    mshr_no_allocate_misses
756        .name(name() +".no_allocate_misses")
757        .desc("Number of misses that were no-allocate")
758        ;
759
760}
761
762unsigned int
763BaseCache::drain(DrainManager *dm)
764{
765    int count = memSidePort->drain(dm) + cpuSidePort->drain(dm) +
766        mshrQueue.drain(dm) + writeBuffer.drain(dm);
767
768    // Set status
769    if (count != 0) {
770        setDrainState(Drainable::Draining);
771        DPRINTF(Drain, "Cache not drained\n");
772        return count;
773    }
774
775    setDrainState(Drainable::Drained);
776    return 0;
777}
778
779BaseCache *
780BaseCacheParams::create()
781{
782    unsigned numSets = size / (assoc * system->cacheLineSize());
783
784    assert(tags);
785
786    if (dynamic_cast<FALRU*>(tags)) {
787        if (numSets != 1)
788            fatal("Got FALRU tags with more than one set\n");
789        return new Cache<FALRU>(this);
790    } else if (dynamic_cast<LRU*>(tags)) {
791        if (numSets == 1)
792            warn("Consider using FALRU tags for a fully associative cache\n");
793        return new Cache<LRU>(this);
794    } else if (dynamic_cast<RandomRepl*>(tags)) {
795        return new Cache<RandomRepl>(this);
796    } else {
797        fatal("No suitable tags selected\n");
798    }
799}
800