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