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