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