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