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