base.cc revision 9796:485399270ca1
1/*
2 * Copyright (c) 2012-2013 ARM Limited
3 * All rights reserved.
4 *
5 * The license below extends only to copyright in the software and shall
6 * not be construed as granting a license to any other intellectual
7 * property including but not limited to intellectual property relating
8 * to a hardware implementation of the functionality of the software
9 * licensed hereunder.  You may use the software subject to the license
10 * terms below provided that you ensure that this notice is replicated
11 * unmodified and in its entirety in all distributions of the software,
12 * modified or unmodified, in source code or in binary form.
13 *
14 * Copyright (c) 2003-2005 The Regents of The University of Michigan
15 * All rights reserved.
16 *
17 * Redistribution and use in source and binary forms, with or without
18 * modification, are permitted provided that the following conditions are
19 * met: redistributions of source code must retain the above copyright
20 * notice, this list of conditions and the following disclaimer;
21 * redistributions in binary form must reproduce the above copyright
22 * notice, this list of conditions and the following disclaimer in the
23 * documentation and/or other materials provided with the distribution;
24 * neither the name of the copyright holders nor the names of its
25 * contributors may be used to endorse or promote products derived from
26 * this software without specific prior written permission.
27 *
28 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
29 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
30 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
31 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
32 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
33 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
34 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
35 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
36 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
37 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
38 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
39 *
40 * Authors: Erik Hallnor
41 */
42
43/**
44 * @file
45 * Definition of BaseCache functions.
46 */
47
48#include "cpu/base.hh"
49#include "cpu/smt.hh"
50#include "debug/Cache.hh"
51#include "debug/Drain.hh"
52#include "mem/cache/tags/fa_lru.hh"
53#include "mem/cache/tags/lru.hh"
54#include "mem/cache/base.hh"
55#include "mem/cache/cache.hh"
56#include "mem/cache/mshr.hh"
57#include "sim/full_system.hh"
58
59using namespace std;
60
61BaseCache::CacheSlavePort::CacheSlavePort(const std::string &_name,
62                                          BaseCache *_cache,
63                                          const std::string &_label)
64    : QueuedSlavePort(_name, _cache, queue), queue(*_cache, *this, _label),
65      blocked(false), mustSendRetry(false), sendRetryEvent(this)
66{
67}
68
69BaseCache::BaseCache(const Params *p)
70    : MemObject(p),
71      mshrQueue("MSHRs", p->mshrs, 4, MSHRQueue_MSHRs),
72      writeBuffer("write buffer", p->write_buffers, p->mshrs+1000,
73                  MSHRQueue_WriteBuffer),
74      blkSize(p->block_size),
75      hitLatency(p->hit_latency),
76      responseLatency(p->response_latency),
77      numTarget(p->tgts_per_mshr),
78      forwardSnoops(p->forward_snoops),
79      isTopLevel(p->is_top_level),
80      blocked(0),
81      noTargetMSHR(NULL),
82      missCount(p->max_miss_count),
83      addrRanges(p->addr_ranges.begin(), p->addr_ranges.end()),
84      system(p->system)
85{
86}
87
88void
89BaseCache::CacheSlavePort::setBlocked()
90{
91    assert(!blocked);
92    DPRINTF(CachePort, "Cache port %s blocking new requests\n", name());
93    blocked = true;
94    // if we already scheduled a retry in this cycle, but it has not yet
95    // happened, cancel it
96    if (sendRetryEvent.scheduled()) {
97       owner.deschedule(sendRetryEvent);
98       DPRINTF(CachePort, "Cache port %s deschedule retry\n", name());
99       mustSendRetry = true;
100    }
101}
102
103void
104BaseCache::CacheSlavePort::clearBlocked()
105{
106    assert(blocked);
107    DPRINTF(CachePort, "Cache port %s accepting new requests\n", name());
108    blocked = false;
109    if (mustSendRetry) {
110        DPRINTF(CachePort, "Cache port %s sending retry\n", name());
111        mustSendRetry = false;
112        // @TODO: need to find a better time (next bus cycle?)
113        owner.schedule(sendRetryEvent, curTick() + 1);
114    }
115}
116
117
118void
119BaseCache::init()
120{
121    if (!cpuSidePort->isConnected() || !memSidePort->isConnected())
122        fatal("Cache ports on %s are not connected\n", name());
123    cpuSidePort->sendRangeChange();
124}
125
126BaseMasterPort &
127BaseCache::getMasterPort(const std::string &if_name, PortID idx)
128{
129    if (if_name == "mem_side") {
130        return *memSidePort;
131    }  else {
132        return MemObject::getMasterPort(if_name, idx);
133    }
134}
135
136BaseSlavePort &
137BaseCache::getSlavePort(const std::string &if_name, PortID idx)
138{
139    if (if_name == "cpu_side") {
140        return *cpuSidePort;
141    } else {
142        return MemObject::getSlavePort(if_name, idx);
143    }
144}
145
146void
147BaseCache::regStats()
148{
149    using namespace Stats;
150
151    // Hit statistics
152    for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
153        MemCmd cmd(access_idx);
154        const string &cstr = cmd.toString();
155
156        hits[access_idx]
157            .init(system->maxMasters())
158            .name(name() + "." + cstr + "_hits")
159            .desc("number of " + cstr + " hits")
160            .flags(total | nozero | nonan)
161            ;
162        for (int i = 0; i < system->maxMasters(); i++) {
163            hits[access_idx].subname(i, system->getMasterName(i));
164        }
165    }
166
167// These macros make it easier to sum the right subset of commands and
168// to change the subset of commands that are considered "demand" vs
169// "non-demand"
170#define SUM_DEMAND(s) \
171    (s[MemCmd::ReadReq] + s[MemCmd::WriteReq] + s[MemCmd::ReadExReq])
172
173// should writebacks be included here?  prior code was inconsistent...
174#define SUM_NON_DEMAND(s) \
175    (s[MemCmd::SoftPFReq] + s[MemCmd::HardPFReq])
176
177    demandHits
178        .name(name() + ".demand_hits")
179        .desc("number of demand (read+write) hits")
180        .flags(total | nozero | nonan)
181        ;
182    demandHits = SUM_DEMAND(hits);
183    for (int i = 0; i < system->maxMasters(); i++) {
184        demandHits.subname(i, system->getMasterName(i));
185    }
186
187    overallHits
188        .name(name() + ".overall_hits")
189        .desc("number of overall hits")
190        .flags(total | nozero | nonan)
191        ;
192    overallHits = demandHits + SUM_NON_DEMAND(hits);
193    for (int i = 0; i < system->maxMasters(); i++) {
194        overallHits.subname(i, system->getMasterName(i));
195    }
196
197    // Miss statistics
198    for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
199        MemCmd cmd(access_idx);
200        const string &cstr = cmd.toString();
201
202        misses[access_idx]
203            .init(system->maxMasters())
204            .name(name() + "." + cstr + "_misses")
205            .desc("number of " + cstr + " misses")
206            .flags(total | nozero | nonan)
207            ;
208        for (int i = 0; i < system->maxMasters(); i++) {
209            misses[access_idx].subname(i, system->getMasterName(i));
210        }
211    }
212
213    demandMisses
214        .name(name() + ".demand_misses")
215        .desc("number of demand (read+write) misses")
216        .flags(total | nozero | nonan)
217        ;
218    demandMisses = SUM_DEMAND(misses);
219    for (int i = 0; i < system->maxMasters(); i++) {
220        demandMisses.subname(i, system->getMasterName(i));
221    }
222
223    overallMisses
224        .name(name() + ".overall_misses")
225        .desc("number of overall misses")
226        .flags(total | nozero | nonan)
227        ;
228    overallMisses = demandMisses + SUM_NON_DEMAND(misses);
229    for (int i = 0; i < system->maxMasters(); i++) {
230        overallMisses.subname(i, system->getMasterName(i));
231    }
232
233    // Miss latency statistics
234    for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
235        MemCmd cmd(access_idx);
236        const string &cstr = cmd.toString();
237
238        missLatency[access_idx]
239            .init(system->maxMasters())
240            .name(name() + "." + cstr + "_miss_latency")
241            .desc("number of " + cstr + " miss cycles")
242            .flags(total | nozero | nonan)
243            ;
244        for (int i = 0; i < system->maxMasters(); i++) {
245            missLatency[access_idx].subname(i, system->getMasterName(i));
246        }
247    }
248
249    demandMissLatency
250        .name(name() + ".demand_miss_latency")
251        .desc("number of demand (read+write) miss cycles")
252        .flags(total | nozero | nonan)
253        ;
254    demandMissLatency = SUM_DEMAND(missLatency);
255    for (int i = 0; i < system->maxMasters(); i++) {
256        demandMissLatency.subname(i, system->getMasterName(i));
257    }
258
259    overallMissLatency
260        .name(name() + ".overall_miss_latency")
261        .desc("number of overall miss cycles")
262        .flags(total | nozero | nonan)
263        ;
264    overallMissLatency = demandMissLatency + SUM_NON_DEMAND(missLatency);
265    for (int i = 0; i < system->maxMasters(); i++) {
266        overallMissLatency.subname(i, system->getMasterName(i));
267    }
268
269    // access formulas
270    for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
271        MemCmd cmd(access_idx);
272        const string &cstr = cmd.toString();
273
274        accesses[access_idx]
275            .name(name() + "." + cstr + "_accesses")
276            .desc("number of " + cstr + " accesses(hits+misses)")
277            .flags(total | nozero | nonan)
278            ;
279        accesses[access_idx] = hits[access_idx] + misses[access_idx];
280
281        for (int i = 0; i < system->maxMasters(); i++) {
282            accesses[access_idx].subname(i, system->getMasterName(i));
283        }
284    }
285
286    demandAccesses
287        .name(name() + ".demand_accesses")
288        .desc("number of demand (read+write) accesses")
289        .flags(total | nozero | nonan)
290        ;
291    demandAccesses = demandHits + demandMisses;
292    for (int i = 0; i < system->maxMasters(); i++) {
293        demandAccesses.subname(i, system->getMasterName(i));
294    }
295
296    overallAccesses
297        .name(name() + ".overall_accesses")
298        .desc("number of overall (read+write) accesses")
299        .flags(total | nozero | nonan)
300        ;
301    overallAccesses = overallHits + overallMisses;
302    for (int i = 0; i < system->maxMasters(); i++) {
303        overallAccesses.subname(i, system->getMasterName(i));
304    }
305
306    // miss rate formulas
307    for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
308        MemCmd cmd(access_idx);
309        const string &cstr = cmd.toString();
310
311        missRate[access_idx]
312            .name(name() + "." + cstr + "_miss_rate")
313            .desc("miss rate for " + cstr + " accesses")
314            .flags(total | nozero | nonan)
315            ;
316        missRate[access_idx] = misses[access_idx] / accesses[access_idx];
317
318        for (int i = 0; i < system->maxMasters(); i++) {
319            missRate[access_idx].subname(i, system->getMasterName(i));
320        }
321    }
322
323    demandMissRate
324        .name(name() + ".demand_miss_rate")
325        .desc("miss rate for demand accesses")
326        .flags(total | nozero | nonan)
327        ;
328    demandMissRate = demandMisses / demandAccesses;
329    for (int i = 0; i < system->maxMasters(); i++) {
330        demandMissRate.subname(i, system->getMasterName(i));
331    }
332
333    overallMissRate
334        .name(name() + ".overall_miss_rate")
335        .desc("miss rate for overall accesses")
336        .flags(total | nozero | nonan)
337        ;
338    overallMissRate = overallMisses / overallAccesses;
339    for (int i = 0; i < system->maxMasters(); i++) {
340        overallMissRate.subname(i, system->getMasterName(i));
341    }
342
343    // miss latency formulas
344    for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
345        MemCmd cmd(access_idx);
346        const string &cstr = cmd.toString();
347
348        avgMissLatency[access_idx]
349            .name(name() + "." + cstr + "_avg_miss_latency")
350            .desc("average " + cstr + " miss latency")
351            .flags(total | nozero | nonan)
352            ;
353        avgMissLatency[access_idx] =
354            missLatency[access_idx] / misses[access_idx];
355
356        for (int i = 0; i < system->maxMasters(); i++) {
357            avgMissLatency[access_idx].subname(i, system->getMasterName(i));
358        }
359    }
360
361    demandAvgMissLatency
362        .name(name() + ".demand_avg_miss_latency")
363        .desc("average overall miss latency")
364        .flags(total | nozero | nonan)
365        ;
366    demandAvgMissLatency = demandMissLatency / demandMisses;
367    for (int i = 0; i < system->maxMasters(); i++) {
368        demandAvgMissLatency.subname(i, system->getMasterName(i));
369    }
370
371    overallAvgMissLatency
372        .name(name() + ".overall_avg_miss_latency")
373        .desc("average overall miss latency")
374        .flags(total | nozero | nonan)
375        ;
376    overallAvgMissLatency = overallMissLatency / overallMisses;
377    for (int i = 0; i < system->maxMasters(); i++) {
378        overallAvgMissLatency.subname(i, system->getMasterName(i));
379    }
380
381    blocked_cycles.init(NUM_BLOCKED_CAUSES);
382    blocked_cycles
383        .name(name() + ".blocked_cycles")
384        .desc("number of cycles access was blocked")
385        .subname(Blocked_NoMSHRs, "no_mshrs")
386        .subname(Blocked_NoTargets, "no_targets")
387        ;
388
389
390    blocked_causes.init(NUM_BLOCKED_CAUSES);
391    blocked_causes
392        .name(name() + ".blocked")
393        .desc("number of cycles access was blocked")
394        .subname(Blocked_NoMSHRs, "no_mshrs")
395        .subname(Blocked_NoTargets, "no_targets")
396        ;
397
398    avg_blocked
399        .name(name() + ".avg_blocked_cycles")
400        .desc("average number of cycles each access was blocked")
401        .subname(Blocked_NoMSHRs, "no_mshrs")
402        .subname(Blocked_NoTargets, "no_targets")
403        ;
404
405    avg_blocked = blocked_cycles / blocked_causes;
406
407    fastWrites
408        .name(name() + ".fast_writes")
409        .desc("number of fast writes performed")
410        ;
411
412    cacheCopies
413        .name(name() + ".cache_copies")
414        .desc("number of cache copies performed")
415        ;
416
417    writebacks
418        .init(system->maxMasters())
419        .name(name() + ".writebacks")
420        .desc("number of writebacks")
421        .flags(total | nozero | nonan)
422        ;
423    for (int i = 0; i < system->maxMasters(); i++) {
424        writebacks.subname(i, system->getMasterName(i));
425    }
426
427    // MSHR statistics
428    // MSHR hit statistics
429    for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
430        MemCmd cmd(access_idx);
431        const string &cstr = cmd.toString();
432
433        mshr_hits[access_idx]
434            .init(system->maxMasters())
435            .name(name() + "." + cstr + "_mshr_hits")
436            .desc("number of " + cstr + " MSHR hits")
437            .flags(total | nozero | nonan)
438            ;
439        for (int i = 0; i < system->maxMasters(); i++) {
440            mshr_hits[access_idx].subname(i, system->getMasterName(i));
441        }
442    }
443
444    demandMshrHits
445        .name(name() + ".demand_mshr_hits")
446        .desc("number of demand (read+write) MSHR hits")
447        .flags(total | nozero | nonan)
448        ;
449    demandMshrHits = SUM_DEMAND(mshr_hits);
450    for (int i = 0; i < system->maxMasters(); i++) {
451        demandMshrHits.subname(i, system->getMasterName(i));
452    }
453
454    overallMshrHits
455        .name(name() + ".overall_mshr_hits")
456        .desc("number of overall MSHR hits")
457        .flags(total | nozero | nonan)
458        ;
459    overallMshrHits = demandMshrHits + SUM_NON_DEMAND(mshr_hits);
460    for (int i = 0; i < system->maxMasters(); i++) {
461        overallMshrHits.subname(i, system->getMasterName(i));
462    }
463
464    // MSHR miss statistics
465    for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
466        MemCmd cmd(access_idx);
467        const string &cstr = cmd.toString();
468
469        mshr_misses[access_idx]
470            .init(system->maxMasters())
471            .name(name() + "." + cstr + "_mshr_misses")
472            .desc("number of " + cstr + " MSHR misses")
473            .flags(total | nozero | nonan)
474            ;
475        for (int i = 0; i < system->maxMasters(); i++) {
476            mshr_misses[access_idx].subname(i, system->getMasterName(i));
477        }
478    }
479
480    demandMshrMisses
481        .name(name() + ".demand_mshr_misses")
482        .desc("number of demand (read+write) MSHR misses")
483        .flags(total | nozero | nonan)
484        ;
485    demandMshrMisses = SUM_DEMAND(mshr_misses);
486    for (int i = 0; i < system->maxMasters(); i++) {
487        demandMshrMisses.subname(i, system->getMasterName(i));
488    }
489
490    overallMshrMisses
491        .name(name() + ".overall_mshr_misses")
492        .desc("number of overall MSHR misses")
493        .flags(total | nozero | nonan)
494        ;
495    overallMshrMisses = demandMshrMisses + SUM_NON_DEMAND(mshr_misses);
496    for (int i = 0; i < system->maxMasters(); i++) {
497        overallMshrMisses.subname(i, system->getMasterName(i));
498    }
499
500    // MSHR miss latency statistics
501    for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
502        MemCmd cmd(access_idx);
503        const string &cstr = cmd.toString();
504
505        mshr_miss_latency[access_idx]
506            .init(system->maxMasters())
507            .name(name() + "." + cstr + "_mshr_miss_latency")
508            .desc("number of " + cstr + " MSHR miss cycles")
509            .flags(total | nozero | nonan)
510            ;
511        for (int i = 0; i < system->maxMasters(); i++) {
512            mshr_miss_latency[access_idx].subname(i, system->getMasterName(i));
513        }
514    }
515
516    demandMshrMissLatency
517        .name(name() + ".demand_mshr_miss_latency")
518        .desc("number of demand (read+write) MSHR miss cycles")
519        .flags(total | nozero | nonan)
520        ;
521    demandMshrMissLatency = SUM_DEMAND(mshr_miss_latency);
522    for (int i = 0; i < system->maxMasters(); i++) {
523        demandMshrMissLatency.subname(i, system->getMasterName(i));
524    }
525
526    overallMshrMissLatency
527        .name(name() + ".overall_mshr_miss_latency")
528        .desc("number of overall MSHR miss cycles")
529        .flags(total | nozero | nonan)
530        ;
531    overallMshrMissLatency =
532        demandMshrMissLatency + SUM_NON_DEMAND(mshr_miss_latency);
533    for (int i = 0; i < system->maxMasters(); i++) {
534        overallMshrMissLatency.subname(i, system->getMasterName(i));
535    }
536
537    // MSHR uncacheable statistics
538    for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
539        MemCmd cmd(access_idx);
540        const string &cstr = cmd.toString();
541
542        mshr_uncacheable[access_idx]
543            .init(system->maxMasters())
544            .name(name() + "." + cstr + "_mshr_uncacheable")
545            .desc("number of " + cstr + " MSHR uncacheable")
546            .flags(total | nozero | nonan)
547            ;
548        for (int i = 0; i < system->maxMasters(); i++) {
549            mshr_uncacheable[access_idx].subname(i, system->getMasterName(i));
550        }
551    }
552
553    overallMshrUncacheable
554        .name(name() + ".overall_mshr_uncacheable_misses")
555        .desc("number of overall MSHR uncacheable misses")
556        .flags(total | nozero | nonan)
557        ;
558    overallMshrUncacheable =
559        SUM_DEMAND(mshr_uncacheable) + SUM_NON_DEMAND(mshr_uncacheable);
560    for (int i = 0; i < system->maxMasters(); i++) {
561        overallMshrUncacheable.subname(i, system->getMasterName(i));
562    }
563
564    // MSHR miss latency statistics
565    for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
566        MemCmd cmd(access_idx);
567        const string &cstr = cmd.toString();
568
569        mshr_uncacheable_lat[access_idx]
570            .init(system->maxMasters())
571            .name(name() + "." + cstr + "_mshr_uncacheable_latency")
572            .desc("number of " + cstr + " MSHR uncacheable cycles")
573            .flags(total | nozero | nonan)
574            ;
575        for (int i = 0; i < system->maxMasters(); i++) {
576            mshr_uncacheable_lat[access_idx].subname(i, system->getMasterName(i));
577        }
578    }
579
580    overallMshrUncacheableLatency
581        .name(name() + ".overall_mshr_uncacheable_latency")
582        .desc("number of overall MSHR uncacheable cycles")
583        .flags(total | nozero | nonan)
584        ;
585    overallMshrUncacheableLatency =
586        SUM_DEMAND(mshr_uncacheable_lat) +
587        SUM_NON_DEMAND(mshr_uncacheable_lat);
588    for (int i = 0; i < system->maxMasters(); i++) {
589        overallMshrUncacheableLatency.subname(i, system->getMasterName(i));
590    }
591
592#if 0
593    // MSHR access formulas
594    for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
595        MemCmd cmd(access_idx);
596        const string &cstr = cmd.toString();
597
598        mshrAccesses[access_idx]
599            .name(name() + "." + cstr + "_mshr_accesses")
600            .desc("number of " + cstr + " mshr accesses(hits+misses)")
601            .flags(total | nozero | nonan)
602            ;
603        mshrAccesses[access_idx] =
604            mshr_hits[access_idx] + mshr_misses[access_idx]
605            + mshr_uncacheable[access_idx];
606    }
607
608    demandMshrAccesses
609        .name(name() + ".demand_mshr_accesses")
610        .desc("number of demand (read+write) mshr accesses")
611        .flags(total | nozero | nonan)
612        ;
613    demandMshrAccesses = demandMshrHits + demandMshrMisses;
614
615    overallMshrAccesses
616        .name(name() + ".overall_mshr_accesses")
617        .desc("number of overall (read+write) mshr accesses")
618        .flags(total | nozero | nonan)
619        ;
620    overallMshrAccesses = overallMshrHits + overallMshrMisses
621        + overallMshrUncacheable;
622#endif
623
624    // MSHR miss rate formulas
625    for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
626        MemCmd cmd(access_idx);
627        const string &cstr = cmd.toString();
628
629        mshrMissRate[access_idx]
630            .name(name() + "." + cstr + "_mshr_miss_rate")
631            .desc("mshr miss rate for " + cstr + " accesses")
632            .flags(total | nozero | nonan)
633            ;
634        mshrMissRate[access_idx] =
635            mshr_misses[access_idx] / accesses[access_idx];
636
637        for (int i = 0; i < system->maxMasters(); i++) {
638            mshrMissRate[access_idx].subname(i, system->getMasterName(i));
639        }
640    }
641
642    demandMshrMissRate
643        .name(name() + ".demand_mshr_miss_rate")
644        .desc("mshr miss rate for demand accesses")
645        .flags(total | nozero | nonan)
646        ;
647    demandMshrMissRate = demandMshrMisses / demandAccesses;
648    for (int i = 0; i < system->maxMasters(); i++) {
649        demandMshrMissRate.subname(i, system->getMasterName(i));
650    }
651
652    overallMshrMissRate
653        .name(name() + ".overall_mshr_miss_rate")
654        .desc("mshr miss rate for overall accesses")
655        .flags(total | nozero | nonan)
656        ;
657    overallMshrMissRate = overallMshrMisses / overallAccesses;
658    for (int i = 0; i < system->maxMasters(); i++) {
659        overallMshrMissRate.subname(i, system->getMasterName(i));
660    }
661
662    // mshrMiss latency formulas
663    for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
664        MemCmd cmd(access_idx);
665        const string &cstr = cmd.toString();
666
667        avgMshrMissLatency[access_idx]
668            .name(name() + "." + cstr + "_avg_mshr_miss_latency")
669            .desc("average " + cstr + " mshr miss latency")
670            .flags(total | nozero | nonan)
671            ;
672        avgMshrMissLatency[access_idx] =
673            mshr_miss_latency[access_idx] / mshr_misses[access_idx];
674
675        for (int i = 0; i < system->maxMasters(); i++) {
676            avgMshrMissLatency[access_idx].subname(i, system->getMasterName(i));
677        }
678    }
679
680    demandAvgMshrMissLatency
681        .name(name() + ".demand_avg_mshr_miss_latency")
682        .desc("average overall mshr miss latency")
683        .flags(total | nozero | nonan)
684        ;
685    demandAvgMshrMissLatency = demandMshrMissLatency / demandMshrMisses;
686    for (int i = 0; i < system->maxMasters(); i++) {
687        demandAvgMshrMissLatency.subname(i, system->getMasterName(i));
688    }
689
690    overallAvgMshrMissLatency
691        .name(name() + ".overall_avg_mshr_miss_latency")
692        .desc("average overall mshr miss latency")
693        .flags(total | nozero | nonan)
694        ;
695    overallAvgMshrMissLatency = overallMshrMissLatency / overallMshrMisses;
696    for (int i = 0; i < system->maxMasters(); i++) {
697        overallAvgMshrMissLatency.subname(i, system->getMasterName(i));
698    }
699
700    // mshrUncacheable latency formulas
701    for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
702        MemCmd cmd(access_idx);
703        const string &cstr = cmd.toString();
704
705        avgMshrUncacheableLatency[access_idx]
706            .name(name() + "." + cstr + "_avg_mshr_uncacheable_latency")
707            .desc("average " + cstr + " mshr uncacheable latency")
708            .flags(total | nozero | nonan)
709            ;
710        avgMshrUncacheableLatency[access_idx] =
711            mshr_uncacheable_lat[access_idx] / mshr_uncacheable[access_idx];
712
713        for (int i = 0; i < system->maxMasters(); i++) {
714            avgMshrUncacheableLatency[access_idx].subname(i, system->getMasterName(i));
715        }
716    }
717
718    overallAvgMshrUncacheableLatency
719        .name(name() + ".overall_avg_mshr_uncacheable_latency")
720        .desc("average overall mshr uncacheable latency")
721        .flags(total | nozero | nonan)
722        ;
723    overallAvgMshrUncacheableLatency = overallMshrUncacheableLatency / overallMshrUncacheable;
724    for (int i = 0; i < system->maxMasters(); i++) {
725        overallAvgMshrUncacheableLatency.subname(i, system->getMasterName(i));
726    }
727
728    mshr_cap_events
729        .init(system->maxMasters())
730        .name(name() + ".mshr_cap_events")
731        .desc("number of times MSHR cap was activated")
732        .flags(total | nozero | nonan)
733        ;
734    for (int i = 0; i < system->maxMasters(); i++) {
735        mshr_cap_events.subname(i, system->getMasterName(i));
736    }
737
738    //software prefetching stats
739    soft_prefetch_mshr_full
740        .init(system->maxMasters())
741        .name(name() + ".soft_prefetch_mshr_full")
742        .desc("number of mshr full events for SW prefetching instrutions")
743        .flags(total | nozero | nonan)
744        ;
745    for (int i = 0; i < system->maxMasters(); i++) {
746        soft_prefetch_mshr_full.subname(i, system->getMasterName(i));
747    }
748
749    mshr_no_allocate_misses
750        .name(name() +".no_allocate_misses")
751        .desc("Number of misses that were no-allocate")
752        ;
753
754}
755
756unsigned int
757BaseCache::drain(DrainManager *dm)
758{
759    int count = memSidePort->drain(dm) + cpuSidePort->drain(dm) +
760        mshrQueue.drain(dm) + writeBuffer.drain(dm);
761
762    // Set status
763    if (count != 0) {
764        setDrainState(Drainable::Draining);
765        DPRINTF(Drain, "Cache not drained\n");
766        return count;
767    }
768
769    setDrainState(Drainable::Drained);
770    return 0;
771}
772
773BaseCache *
774BaseCacheParams::create()
775{
776    unsigned numSets = size / (assoc * block_size);
777
778    assert(tags);
779
780    if (dynamic_cast<FALRU*>(tags)) {
781        if (numSets != 1)
782            fatal("Got FALRU tags with more than one set\n");
783        return new Cache<FALRU>(this);
784    } else if (dynamic_cast<LRU*>(tags)) {
785        if (numSets == 1)
786            warn("Consider using FALRU tags for a fully associative cache\n");
787        return new Cache<LRU>(this);
788    } else {
789        fatal("No suitable tags selected\n");
790    }
791}
792