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