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