base.cc (5606:6da7a58b0bc8) base.cc (6122:9af6fb59752f)
1/*
2 * Copyright (c) 2003-2005 The Regents of The University of Michigan
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met: redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer;
9 * redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution;
12 * neither the name of the copyright holders nor the names of its
13 * contributors may be used to endorse or promote products derived from
14 * this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 *
28 * Authors: Erik Hallnor
29 */
30
31/**
32 * @file
33 * Definition of BaseCache functions.
34 */
35
36#include "cpu/base.hh"
37#include "cpu/smt.hh"
38#include "mem/cache/base.hh"
39#include "mem/cache/mshr.hh"
40
41using namespace std;
42
43BaseCache::CachePort::CachePort(const std::string &_name, BaseCache *_cache,
1/*
2 * Copyright (c) 2003-2005 The Regents of The University of Michigan
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met: redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer;
9 * redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution;
12 * neither the name of the copyright holders nor the names of its
13 * contributors may be used to endorse or promote products derived from
14 * this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 *
28 * Authors: Erik Hallnor
29 */
30
31/**
32 * @file
33 * Definition of BaseCache functions.
34 */
35
36#include "cpu/base.hh"
37#include "cpu/smt.hh"
38#include "mem/cache/base.hh"
39#include "mem/cache/mshr.hh"
40
41using namespace std;
42
43BaseCache::CachePort::CachePort(const std::string &_name, BaseCache *_cache,
44 const std::string &_label,
45 std::vector<Range<Addr> > filter_ranges)
44 const std::string &_label)
46 : SimpleTimingPort(_name, _cache), cache(_cache),
47 label(_label), otherPort(NULL),
45 : SimpleTimingPort(_name, _cache), cache(_cache),
46 label(_label), otherPort(NULL),
48 blocked(false), mustSendRetry(false), filterRanges(filter_ranges)
47 blocked(false), mustSendRetry(false)
49{
50}
51
52
53BaseCache::BaseCache(const Params *p)
54 : MemObject(p),
55 mshrQueue("MSHRs", p->mshrs, 4, MSHRQueue_MSHRs),
56 writeBuffer("write buffer", p->write_buffers, p->mshrs+1000,
57 MSHRQueue_WriteBuffer),
58 blkSize(p->block_size),
59 hitLatency(p->latency),
60 numTarget(p->tgts_per_mshr),
48{
49}
50
51
52BaseCache::BaseCache(const Params *p)
53 : MemObject(p),
54 mshrQueue("MSHRs", p->mshrs, 4, MSHRQueue_MSHRs),
55 writeBuffer("write buffer", p->write_buffers, p->mshrs+1000,
56 MSHRQueue_WriteBuffer),
57 blkSize(p->block_size),
58 hitLatency(p->latency),
59 numTarget(p->tgts_per_mshr),
60 forwardSnoops(p->forward_snoops),
61 blocked(0),
62 noTargetMSHR(NULL),
63 missCount(p->max_miss_count),
61 blocked(0),
62 noTargetMSHR(NULL),
63 missCount(p->max_miss_count),
64 drainEvent(NULL)
64 drainEvent(NULL),
65 addrRange(p->addr_range)
65{
66}
67
68void
69BaseCache::CachePort::recvStatusChange(Port::Status status)
70{
71 if (status == Port::RangeChange) {
72 otherPort->sendStatusChange(Port::RangeChange);
73 }
74}
75
76
77bool
78BaseCache::CachePort::checkFunctional(PacketPtr pkt)
79{
80 pkt->pushLabel(label);
81 bool done = SimpleTimingPort::checkFunctional(pkt);
82 pkt->popLabel();
83 return done;
84}
85
86
87int
88BaseCache::CachePort::deviceBlockSize()
89{
90 return cache->getBlockSize();
91}
92
93
94bool
95BaseCache::CachePort::recvRetryCommon()
96{
97 assert(waitingOnRetry);
98 waitingOnRetry = false;
99 return false;
100}
101
102
103void
104BaseCache::CachePort::setBlocked()
105{
106 assert(!blocked);
107 DPRINTF(Cache, "Cache Blocking\n");
108 blocked = true;
109 //Clear the retry flag
110 mustSendRetry = false;
111}
112
113void
114BaseCache::CachePort::clearBlocked()
115{
116 assert(blocked);
117 DPRINTF(Cache, "Cache Unblocking\n");
118 blocked = false;
119 if (mustSendRetry)
120 {
121 DPRINTF(Cache, "Cache Sending Retry\n");
122 mustSendRetry = false;
123 SendRetryEvent *ev = new SendRetryEvent(this, true);
124 // @TODO: need to find a better time (next bus cycle?)
125 schedule(ev, curTick + 1);
126 }
127}
128
129
130void
131BaseCache::init()
132{
133 if (!cpuSidePort || !memSidePort)
134 panic("Cache not hooked up on both sides\n");
135 cpuSidePort->sendStatusChange(Port::RangeChange);
136}
137
138
139void
140BaseCache::regStats()
141{
142 using namespace Stats;
143
144 // Hit statistics
145 for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
146 MemCmd cmd(access_idx);
147 const string &cstr = cmd.toString();
148
149 hits[access_idx]
150 .init(maxThreadsPerCPU)
151 .name(name() + "." + cstr + "_hits")
152 .desc("number of " + cstr + " hits")
153 .flags(total | nozero | nonan)
154 ;
155 }
156
157// These macros make it easier to sum the right subset of commands and
158// to change the subset of commands that are considered "demand" vs
159// "non-demand"
160#define SUM_DEMAND(s) \
161 (s[MemCmd::ReadReq] + s[MemCmd::WriteReq] + s[MemCmd::ReadExReq])
162
163// should writebacks be included here? prior code was inconsistent...
164#define SUM_NON_DEMAND(s) \
165 (s[MemCmd::SoftPFReq] + s[MemCmd::HardPFReq])
166
167 demandHits
168 .name(name() + ".demand_hits")
169 .desc("number of demand (read+write) hits")
170 .flags(total)
171 ;
172 demandHits = SUM_DEMAND(hits);
173
174 overallHits
175 .name(name() + ".overall_hits")
176 .desc("number of overall hits")
177 .flags(total)
178 ;
179 overallHits = demandHits + SUM_NON_DEMAND(hits);
180
181 // Miss statistics
182 for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
183 MemCmd cmd(access_idx);
184 const string &cstr = cmd.toString();
185
186 misses[access_idx]
187 .init(maxThreadsPerCPU)
188 .name(name() + "." + cstr + "_misses")
189 .desc("number of " + cstr + " misses")
190 .flags(total | nozero | nonan)
191 ;
192 }
193
194 demandMisses
195 .name(name() + ".demand_misses")
196 .desc("number of demand (read+write) misses")
197 .flags(total)
198 ;
199 demandMisses = SUM_DEMAND(misses);
200
201 overallMisses
202 .name(name() + ".overall_misses")
203 .desc("number of overall misses")
204 .flags(total)
205 ;
206 overallMisses = demandMisses + SUM_NON_DEMAND(misses);
207
208 // Miss latency statistics
209 for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
210 MemCmd cmd(access_idx);
211 const string &cstr = cmd.toString();
212
213 missLatency[access_idx]
214 .init(maxThreadsPerCPU)
215 .name(name() + "." + cstr + "_miss_latency")
216 .desc("number of " + cstr + " miss cycles")
217 .flags(total | nozero | nonan)
218 ;
219 }
220
221 demandMissLatency
222 .name(name() + ".demand_miss_latency")
223 .desc("number of demand (read+write) miss cycles")
224 .flags(total)
225 ;
226 demandMissLatency = SUM_DEMAND(missLatency);
227
228 overallMissLatency
229 .name(name() + ".overall_miss_latency")
230 .desc("number of overall miss cycles")
231 .flags(total)
232 ;
233 overallMissLatency = demandMissLatency + SUM_NON_DEMAND(missLatency);
234
235 // access formulas
236 for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
237 MemCmd cmd(access_idx);
238 const string &cstr = cmd.toString();
239
240 accesses[access_idx]
241 .name(name() + "." + cstr + "_accesses")
242 .desc("number of " + cstr + " accesses(hits+misses)")
243 .flags(total | nozero | nonan)
244 ;
245
246 accesses[access_idx] = hits[access_idx] + misses[access_idx];
247 }
248
249 demandAccesses
250 .name(name() + ".demand_accesses")
251 .desc("number of demand (read+write) accesses")
252 .flags(total)
253 ;
254 demandAccesses = demandHits + demandMisses;
255
256 overallAccesses
257 .name(name() + ".overall_accesses")
258 .desc("number of overall (read+write) accesses")
259 .flags(total)
260 ;
261 overallAccesses = overallHits + overallMisses;
262
263 // miss rate formulas
264 for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
265 MemCmd cmd(access_idx);
266 const string &cstr = cmd.toString();
267
268 missRate[access_idx]
269 .name(name() + "." + cstr + "_miss_rate")
270 .desc("miss rate for " + cstr + " accesses")
271 .flags(total | nozero | nonan)
272 ;
273
274 missRate[access_idx] = misses[access_idx] / accesses[access_idx];
275 }
276
277 demandMissRate
278 .name(name() + ".demand_miss_rate")
279 .desc("miss rate for demand accesses")
280 .flags(total)
281 ;
282 demandMissRate = demandMisses / demandAccesses;
283
284 overallMissRate
285 .name(name() + ".overall_miss_rate")
286 .desc("miss rate for overall accesses")
287 .flags(total)
288 ;
289 overallMissRate = overallMisses / overallAccesses;
290
291 // miss latency formulas
292 for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
293 MemCmd cmd(access_idx);
294 const string &cstr = cmd.toString();
295
296 avgMissLatency[access_idx]
297 .name(name() + "." + cstr + "_avg_miss_latency")
298 .desc("average " + cstr + " miss latency")
299 .flags(total | nozero | nonan)
300 ;
301
302 avgMissLatency[access_idx] =
303 missLatency[access_idx] / misses[access_idx];
304 }
305
306 demandAvgMissLatency
307 .name(name() + ".demand_avg_miss_latency")
308 .desc("average overall miss latency")
309 .flags(total)
310 ;
311 demandAvgMissLatency = demandMissLatency / demandMisses;
312
313 overallAvgMissLatency
314 .name(name() + ".overall_avg_miss_latency")
315 .desc("average overall miss latency")
316 .flags(total)
317 ;
318 overallAvgMissLatency = overallMissLatency / overallMisses;
319
320 blocked_cycles.init(NUM_BLOCKED_CAUSES);
321 blocked_cycles
322 .name(name() + ".blocked_cycles")
323 .desc("number of cycles access was blocked")
324 .subname(Blocked_NoMSHRs, "no_mshrs")
325 .subname(Blocked_NoTargets, "no_targets")
326 ;
327
328
329 blocked_causes.init(NUM_BLOCKED_CAUSES);
330 blocked_causes
331 .name(name() + ".blocked")
332 .desc("number of cycles access was blocked")
333 .subname(Blocked_NoMSHRs, "no_mshrs")
334 .subname(Blocked_NoTargets, "no_targets")
335 ;
336
337 avg_blocked
338 .name(name() + ".avg_blocked_cycles")
339 .desc("average number of cycles each access was blocked")
340 .subname(Blocked_NoMSHRs, "no_mshrs")
341 .subname(Blocked_NoTargets, "no_targets")
342 ;
343
344 avg_blocked = blocked_cycles / blocked_causes;
345
346 fastWrites
347 .name(name() + ".fast_writes")
348 .desc("number of fast writes performed")
349 ;
350
351 cacheCopies
352 .name(name() + ".cache_copies")
353 .desc("number of cache copies performed")
354 ;
355
356 writebacks
357 .init(maxThreadsPerCPU)
358 .name(name() + ".writebacks")
359 .desc("number of writebacks")
360 .flags(total)
361 ;
362
363 // MSHR statistics
364 // MSHR hit statistics
365 for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
366 MemCmd cmd(access_idx);
367 const string &cstr = cmd.toString();
368
369 mshr_hits[access_idx]
370 .init(maxThreadsPerCPU)
371 .name(name() + "." + cstr + "_mshr_hits")
372 .desc("number of " + cstr + " MSHR hits")
373 .flags(total | nozero | nonan)
374 ;
375 }
376
377 demandMshrHits
378 .name(name() + ".demand_mshr_hits")
379 .desc("number of demand (read+write) MSHR hits")
380 .flags(total)
381 ;
382 demandMshrHits = SUM_DEMAND(mshr_hits);
383
384 overallMshrHits
385 .name(name() + ".overall_mshr_hits")
386 .desc("number of overall MSHR hits")
387 .flags(total)
388 ;
389 overallMshrHits = demandMshrHits + SUM_NON_DEMAND(mshr_hits);
390
391 // MSHR miss statistics
392 for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
393 MemCmd cmd(access_idx);
394 const string &cstr = cmd.toString();
395
396 mshr_misses[access_idx]
397 .init(maxThreadsPerCPU)
398 .name(name() + "." + cstr + "_mshr_misses")
399 .desc("number of " + cstr + " MSHR misses")
400 .flags(total | nozero | nonan)
401 ;
402 }
403
404 demandMshrMisses
405 .name(name() + ".demand_mshr_misses")
406 .desc("number of demand (read+write) MSHR misses")
407 .flags(total)
408 ;
409 demandMshrMisses = SUM_DEMAND(mshr_misses);
410
411 overallMshrMisses
412 .name(name() + ".overall_mshr_misses")
413 .desc("number of overall MSHR misses")
414 .flags(total)
415 ;
416 overallMshrMisses = demandMshrMisses + SUM_NON_DEMAND(mshr_misses);
417
418 // MSHR miss latency statistics
419 for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
420 MemCmd cmd(access_idx);
421 const string &cstr = cmd.toString();
422
423 mshr_miss_latency[access_idx]
424 .init(maxThreadsPerCPU)
425 .name(name() + "." + cstr + "_mshr_miss_latency")
426 .desc("number of " + cstr + " MSHR miss cycles")
427 .flags(total | nozero | nonan)
428 ;
429 }
430
431 demandMshrMissLatency
432 .name(name() + ".demand_mshr_miss_latency")
433 .desc("number of demand (read+write) MSHR miss cycles")
434 .flags(total)
435 ;
436 demandMshrMissLatency = SUM_DEMAND(mshr_miss_latency);
437
438 overallMshrMissLatency
439 .name(name() + ".overall_mshr_miss_latency")
440 .desc("number of overall MSHR miss cycles")
441 .flags(total)
442 ;
443 overallMshrMissLatency =
444 demandMshrMissLatency + SUM_NON_DEMAND(mshr_miss_latency);
445
446 // MSHR uncacheable statistics
447 for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
448 MemCmd cmd(access_idx);
449 const string &cstr = cmd.toString();
450
451 mshr_uncacheable[access_idx]
452 .init(maxThreadsPerCPU)
453 .name(name() + "." + cstr + "_mshr_uncacheable")
454 .desc("number of " + cstr + " MSHR uncacheable")
455 .flags(total | nozero | nonan)
456 ;
457 }
458
459 overallMshrUncacheable
460 .name(name() + ".overall_mshr_uncacheable_misses")
461 .desc("number of overall MSHR uncacheable misses")
462 .flags(total)
463 ;
464 overallMshrUncacheable =
465 SUM_DEMAND(mshr_uncacheable) + SUM_NON_DEMAND(mshr_uncacheable);
466
467 // MSHR miss latency statistics
468 for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
469 MemCmd cmd(access_idx);
470 const string &cstr = cmd.toString();
471
472 mshr_uncacheable_lat[access_idx]
473 .init(maxThreadsPerCPU)
474 .name(name() + "." + cstr + "_mshr_uncacheable_latency")
475 .desc("number of " + cstr + " MSHR uncacheable cycles")
476 .flags(total | nozero | nonan)
477 ;
478 }
479
480 overallMshrUncacheableLatency
481 .name(name() + ".overall_mshr_uncacheable_latency")
482 .desc("number of overall MSHR uncacheable cycles")
483 .flags(total)
484 ;
485 overallMshrUncacheableLatency =
486 SUM_DEMAND(mshr_uncacheable_lat) +
487 SUM_NON_DEMAND(mshr_uncacheable_lat);
488
489#if 0
490 // MSHR access formulas
491 for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
492 MemCmd cmd(access_idx);
493 const string &cstr = cmd.toString();
494
495 mshrAccesses[access_idx]
496 .name(name() + "." + cstr + "_mshr_accesses")
497 .desc("number of " + cstr + " mshr accesses(hits+misses)")
498 .flags(total | nozero | nonan)
499 ;
500 mshrAccesses[access_idx] =
501 mshr_hits[access_idx] + mshr_misses[access_idx]
502 + mshr_uncacheable[access_idx];
503 }
504
505 demandMshrAccesses
506 .name(name() + ".demand_mshr_accesses")
507 .desc("number of demand (read+write) mshr accesses")
508 .flags(total | nozero | nonan)
509 ;
510 demandMshrAccesses = demandMshrHits + demandMshrMisses;
511
512 overallMshrAccesses
513 .name(name() + ".overall_mshr_accesses")
514 .desc("number of overall (read+write) mshr accesses")
515 .flags(total | nozero | nonan)
516 ;
517 overallMshrAccesses = overallMshrHits + overallMshrMisses
518 + overallMshrUncacheable;
519#endif
520
521 // MSHR miss rate formulas
522 for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
523 MemCmd cmd(access_idx);
524 const string &cstr = cmd.toString();
525
526 mshrMissRate[access_idx]
527 .name(name() + "." + cstr + "_mshr_miss_rate")
528 .desc("mshr miss rate for " + cstr + " accesses")
529 .flags(total | nozero | nonan)
530 ;
531
532 mshrMissRate[access_idx] =
533 mshr_misses[access_idx] / accesses[access_idx];
534 }
535
536 demandMshrMissRate
537 .name(name() + ".demand_mshr_miss_rate")
538 .desc("mshr miss rate for demand accesses")
539 .flags(total)
540 ;
541 demandMshrMissRate = demandMshrMisses / demandAccesses;
542
543 overallMshrMissRate
544 .name(name() + ".overall_mshr_miss_rate")
545 .desc("mshr miss rate for overall accesses")
546 .flags(total)
547 ;
548 overallMshrMissRate = overallMshrMisses / overallAccesses;
549
550 // mshrMiss latency formulas
551 for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
552 MemCmd cmd(access_idx);
553 const string &cstr = cmd.toString();
554
555 avgMshrMissLatency[access_idx]
556 .name(name() + "." + cstr + "_avg_mshr_miss_latency")
557 .desc("average " + cstr + " mshr miss latency")
558 .flags(total | nozero | nonan)
559 ;
560
561 avgMshrMissLatency[access_idx] =
562 mshr_miss_latency[access_idx] / mshr_misses[access_idx];
563 }
564
565 demandAvgMshrMissLatency
566 .name(name() + ".demand_avg_mshr_miss_latency")
567 .desc("average overall mshr miss latency")
568 .flags(total)
569 ;
570 demandAvgMshrMissLatency = demandMshrMissLatency / demandMshrMisses;
571
572 overallAvgMshrMissLatency
573 .name(name() + ".overall_avg_mshr_miss_latency")
574 .desc("average overall mshr miss latency")
575 .flags(total)
576 ;
577 overallAvgMshrMissLatency = overallMshrMissLatency / overallMshrMisses;
578
579 // mshrUncacheable latency formulas
580 for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
581 MemCmd cmd(access_idx);
582 const string &cstr = cmd.toString();
583
584 avgMshrUncacheableLatency[access_idx]
585 .name(name() + "." + cstr + "_avg_mshr_uncacheable_latency")
586 .desc("average " + cstr + " mshr uncacheable latency")
587 .flags(total | nozero | nonan)
588 ;
589
590 avgMshrUncacheableLatency[access_idx] =
591 mshr_uncacheable_lat[access_idx] / mshr_uncacheable[access_idx];
592 }
593
594 overallAvgMshrUncacheableLatency
595 .name(name() + ".overall_avg_mshr_uncacheable_latency")
596 .desc("average overall mshr uncacheable latency")
597 .flags(total)
598 ;
599 overallAvgMshrUncacheableLatency = overallMshrUncacheableLatency / overallMshrUncacheable;
600
601 mshr_cap_events
602 .init(maxThreadsPerCPU)
603 .name(name() + ".mshr_cap_events")
604 .desc("number of times MSHR cap was activated")
605 .flags(total)
606 ;
607
608 //software prefetching stats
609 soft_prefetch_mshr_full
610 .init(maxThreadsPerCPU)
611 .name(name() + ".soft_prefetch_mshr_full")
612 .desc("number of mshr full events for SW prefetching instrutions")
613 .flags(total)
614 ;
615
616 mshr_no_allocate_misses
617 .name(name() +".no_allocate_misses")
618 .desc("Number of misses that were no-allocate")
619 ;
620
621}
622
623unsigned int
624BaseCache::drain(Event *de)
625{
626 int count = memSidePort->drain(de) + cpuSidePort->drain(de);
627
628 // Set status
629 if (count != 0) {
630 drainEvent = de;
631
632 changeState(SimObject::Draining);
633 return count;
634 }
635
636 changeState(SimObject::Drained);
637 return 0;
638}
66{
67}
68
69void
70BaseCache::CachePort::recvStatusChange(Port::Status status)
71{
72 if (status == Port::RangeChange) {
73 otherPort->sendStatusChange(Port::RangeChange);
74 }
75}
76
77
78bool
79BaseCache::CachePort::checkFunctional(PacketPtr pkt)
80{
81 pkt->pushLabel(label);
82 bool done = SimpleTimingPort::checkFunctional(pkt);
83 pkt->popLabel();
84 return done;
85}
86
87
88int
89BaseCache::CachePort::deviceBlockSize()
90{
91 return cache->getBlockSize();
92}
93
94
95bool
96BaseCache::CachePort::recvRetryCommon()
97{
98 assert(waitingOnRetry);
99 waitingOnRetry = false;
100 return false;
101}
102
103
104void
105BaseCache::CachePort::setBlocked()
106{
107 assert(!blocked);
108 DPRINTF(Cache, "Cache Blocking\n");
109 blocked = true;
110 //Clear the retry flag
111 mustSendRetry = false;
112}
113
114void
115BaseCache::CachePort::clearBlocked()
116{
117 assert(blocked);
118 DPRINTF(Cache, "Cache Unblocking\n");
119 blocked = false;
120 if (mustSendRetry)
121 {
122 DPRINTF(Cache, "Cache Sending Retry\n");
123 mustSendRetry = false;
124 SendRetryEvent *ev = new SendRetryEvent(this, true);
125 // @TODO: need to find a better time (next bus cycle?)
126 schedule(ev, curTick + 1);
127 }
128}
129
130
131void
132BaseCache::init()
133{
134 if (!cpuSidePort || !memSidePort)
135 panic("Cache not hooked up on both sides\n");
136 cpuSidePort->sendStatusChange(Port::RangeChange);
137}
138
139
140void
141BaseCache::regStats()
142{
143 using namespace Stats;
144
145 // Hit statistics
146 for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
147 MemCmd cmd(access_idx);
148 const string &cstr = cmd.toString();
149
150 hits[access_idx]
151 .init(maxThreadsPerCPU)
152 .name(name() + "." + cstr + "_hits")
153 .desc("number of " + cstr + " hits")
154 .flags(total | nozero | nonan)
155 ;
156 }
157
158// These macros make it easier to sum the right subset of commands and
159// to change the subset of commands that are considered "demand" vs
160// "non-demand"
161#define SUM_DEMAND(s) \
162 (s[MemCmd::ReadReq] + s[MemCmd::WriteReq] + s[MemCmd::ReadExReq])
163
164// should writebacks be included here? prior code was inconsistent...
165#define SUM_NON_DEMAND(s) \
166 (s[MemCmd::SoftPFReq] + s[MemCmd::HardPFReq])
167
168 demandHits
169 .name(name() + ".demand_hits")
170 .desc("number of demand (read+write) hits")
171 .flags(total)
172 ;
173 demandHits = SUM_DEMAND(hits);
174
175 overallHits
176 .name(name() + ".overall_hits")
177 .desc("number of overall hits")
178 .flags(total)
179 ;
180 overallHits = demandHits + SUM_NON_DEMAND(hits);
181
182 // Miss statistics
183 for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
184 MemCmd cmd(access_idx);
185 const string &cstr = cmd.toString();
186
187 misses[access_idx]
188 .init(maxThreadsPerCPU)
189 .name(name() + "." + cstr + "_misses")
190 .desc("number of " + cstr + " misses")
191 .flags(total | nozero | nonan)
192 ;
193 }
194
195 demandMisses
196 .name(name() + ".demand_misses")
197 .desc("number of demand (read+write) misses")
198 .flags(total)
199 ;
200 demandMisses = SUM_DEMAND(misses);
201
202 overallMisses
203 .name(name() + ".overall_misses")
204 .desc("number of overall misses")
205 .flags(total)
206 ;
207 overallMisses = demandMisses + SUM_NON_DEMAND(misses);
208
209 // Miss latency statistics
210 for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
211 MemCmd cmd(access_idx);
212 const string &cstr = cmd.toString();
213
214 missLatency[access_idx]
215 .init(maxThreadsPerCPU)
216 .name(name() + "." + cstr + "_miss_latency")
217 .desc("number of " + cstr + " miss cycles")
218 .flags(total | nozero | nonan)
219 ;
220 }
221
222 demandMissLatency
223 .name(name() + ".demand_miss_latency")
224 .desc("number of demand (read+write) miss cycles")
225 .flags(total)
226 ;
227 demandMissLatency = SUM_DEMAND(missLatency);
228
229 overallMissLatency
230 .name(name() + ".overall_miss_latency")
231 .desc("number of overall miss cycles")
232 .flags(total)
233 ;
234 overallMissLatency = demandMissLatency + SUM_NON_DEMAND(missLatency);
235
236 // access formulas
237 for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
238 MemCmd cmd(access_idx);
239 const string &cstr = cmd.toString();
240
241 accesses[access_idx]
242 .name(name() + "." + cstr + "_accesses")
243 .desc("number of " + cstr + " accesses(hits+misses)")
244 .flags(total | nozero | nonan)
245 ;
246
247 accesses[access_idx] = hits[access_idx] + misses[access_idx];
248 }
249
250 demandAccesses
251 .name(name() + ".demand_accesses")
252 .desc("number of demand (read+write) accesses")
253 .flags(total)
254 ;
255 demandAccesses = demandHits + demandMisses;
256
257 overallAccesses
258 .name(name() + ".overall_accesses")
259 .desc("number of overall (read+write) accesses")
260 .flags(total)
261 ;
262 overallAccesses = overallHits + overallMisses;
263
264 // miss rate formulas
265 for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
266 MemCmd cmd(access_idx);
267 const string &cstr = cmd.toString();
268
269 missRate[access_idx]
270 .name(name() + "." + cstr + "_miss_rate")
271 .desc("miss rate for " + cstr + " accesses")
272 .flags(total | nozero | nonan)
273 ;
274
275 missRate[access_idx] = misses[access_idx] / accesses[access_idx];
276 }
277
278 demandMissRate
279 .name(name() + ".demand_miss_rate")
280 .desc("miss rate for demand accesses")
281 .flags(total)
282 ;
283 demandMissRate = demandMisses / demandAccesses;
284
285 overallMissRate
286 .name(name() + ".overall_miss_rate")
287 .desc("miss rate for overall accesses")
288 .flags(total)
289 ;
290 overallMissRate = overallMisses / overallAccesses;
291
292 // miss latency formulas
293 for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
294 MemCmd cmd(access_idx);
295 const string &cstr = cmd.toString();
296
297 avgMissLatency[access_idx]
298 .name(name() + "." + cstr + "_avg_miss_latency")
299 .desc("average " + cstr + " miss latency")
300 .flags(total | nozero | nonan)
301 ;
302
303 avgMissLatency[access_idx] =
304 missLatency[access_idx] / misses[access_idx];
305 }
306
307 demandAvgMissLatency
308 .name(name() + ".demand_avg_miss_latency")
309 .desc("average overall miss latency")
310 .flags(total)
311 ;
312 demandAvgMissLatency = demandMissLatency / demandMisses;
313
314 overallAvgMissLatency
315 .name(name() + ".overall_avg_miss_latency")
316 .desc("average overall miss latency")
317 .flags(total)
318 ;
319 overallAvgMissLatency = overallMissLatency / overallMisses;
320
321 blocked_cycles.init(NUM_BLOCKED_CAUSES);
322 blocked_cycles
323 .name(name() + ".blocked_cycles")
324 .desc("number of cycles access was blocked")
325 .subname(Blocked_NoMSHRs, "no_mshrs")
326 .subname(Blocked_NoTargets, "no_targets")
327 ;
328
329
330 blocked_causes.init(NUM_BLOCKED_CAUSES);
331 blocked_causes
332 .name(name() + ".blocked")
333 .desc("number of cycles access was blocked")
334 .subname(Blocked_NoMSHRs, "no_mshrs")
335 .subname(Blocked_NoTargets, "no_targets")
336 ;
337
338 avg_blocked
339 .name(name() + ".avg_blocked_cycles")
340 .desc("average number of cycles each access was blocked")
341 .subname(Blocked_NoMSHRs, "no_mshrs")
342 .subname(Blocked_NoTargets, "no_targets")
343 ;
344
345 avg_blocked = blocked_cycles / blocked_causes;
346
347 fastWrites
348 .name(name() + ".fast_writes")
349 .desc("number of fast writes performed")
350 ;
351
352 cacheCopies
353 .name(name() + ".cache_copies")
354 .desc("number of cache copies performed")
355 ;
356
357 writebacks
358 .init(maxThreadsPerCPU)
359 .name(name() + ".writebacks")
360 .desc("number of writebacks")
361 .flags(total)
362 ;
363
364 // MSHR statistics
365 // MSHR hit statistics
366 for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
367 MemCmd cmd(access_idx);
368 const string &cstr = cmd.toString();
369
370 mshr_hits[access_idx]
371 .init(maxThreadsPerCPU)
372 .name(name() + "." + cstr + "_mshr_hits")
373 .desc("number of " + cstr + " MSHR hits")
374 .flags(total | nozero | nonan)
375 ;
376 }
377
378 demandMshrHits
379 .name(name() + ".demand_mshr_hits")
380 .desc("number of demand (read+write) MSHR hits")
381 .flags(total)
382 ;
383 demandMshrHits = SUM_DEMAND(mshr_hits);
384
385 overallMshrHits
386 .name(name() + ".overall_mshr_hits")
387 .desc("number of overall MSHR hits")
388 .flags(total)
389 ;
390 overallMshrHits = demandMshrHits + SUM_NON_DEMAND(mshr_hits);
391
392 // MSHR miss statistics
393 for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
394 MemCmd cmd(access_idx);
395 const string &cstr = cmd.toString();
396
397 mshr_misses[access_idx]
398 .init(maxThreadsPerCPU)
399 .name(name() + "." + cstr + "_mshr_misses")
400 .desc("number of " + cstr + " MSHR misses")
401 .flags(total | nozero | nonan)
402 ;
403 }
404
405 demandMshrMisses
406 .name(name() + ".demand_mshr_misses")
407 .desc("number of demand (read+write) MSHR misses")
408 .flags(total)
409 ;
410 demandMshrMisses = SUM_DEMAND(mshr_misses);
411
412 overallMshrMisses
413 .name(name() + ".overall_mshr_misses")
414 .desc("number of overall MSHR misses")
415 .flags(total)
416 ;
417 overallMshrMisses = demandMshrMisses + SUM_NON_DEMAND(mshr_misses);
418
419 // MSHR miss latency statistics
420 for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
421 MemCmd cmd(access_idx);
422 const string &cstr = cmd.toString();
423
424 mshr_miss_latency[access_idx]
425 .init(maxThreadsPerCPU)
426 .name(name() + "." + cstr + "_mshr_miss_latency")
427 .desc("number of " + cstr + " MSHR miss cycles")
428 .flags(total | nozero | nonan)
429 ;
430 }
431
432 demandMshrMissLatency
433 .name(name() + ".demand_mshr_miss_latency")
434 .desc("number of demand (read+write) MSHR miss cycles")
435 .flags(total)
436 ;
437 demandMshrMissLatency = SUM_DEMAND(mshr_miss_latency);
438
439 overallMshrMissLatency
440 .name(name() + ".overall_mshr_miss_latency")
441 .desc("number of overall MSHR miss cycles")
442 .flags(total)
443 ;
444 overallMshrMissLatency =
445 demandMshrMissLatency + SUM_NON_DEMAND(mshr_miss_latency);
446
447 // MSHR uncacheable statistics
448 for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
449 MemCmd cmd(access_idx);
450 const string &cstr = cmd.toString();
451
452 mshr_uncacheable[access_idx]
453 .init(maxThreadsPerCPU)
454 .name(name() + "." + cstr + "_mshr_uncacheable")
455 .desc("number of " + cstr + " MSHR uncacheable")
456 .flags(total | nozero | nonan)
457 ;
458 }
459
460 overallMshrUncacheable
461 .name(name() + ".overall_mshr_uncacheable_misses")
462 .desc("number of overall MSHR uncacheable misses")
463 .flags(total)
464 ;
465 overallMshrUncacheable =
466 SUM_DEMAND(mshr_uncacheable) + SUM_NON_DEMAND(mshr_uncacheable);
467
468 // MSHR miss latency statistics
469 for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
470 MemCmd cmd(access_idx);
471 const string &cstr = cmd.toString();
472
473 mshr_uncacheable_lat[access_idx]
474 .init(maxThreadsPerCPU)
475 .name(name() + "." + cstr + "_mshr_uncacheable_latency")
476 .desc("number of " + cstr + " MSHR uncacheable cycles")
477 .flags(total | nozero | nonan)
478 ;
479 }
480
481 overallMshrUncacheableLatency
482 .name(name() + ".overall_mshr_uncacheable_latency")
483 .desc("number of overall MSHR uncacheable cycles")
484 .flags(total)
485 ;
486 overallMshrUncacheableLatency =
487 SUM_DEMAND(mshr_uncacheable_lat) +
488 SUM_NON_DEMAND(mshr_uncacheable_lat);
489
490#if 0
491 // MSHR access formulas
492 for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
493 MemCmd cmd(access_idx);
494 const string &cstr = cmd.toString();
495
496 mshrAccesses[access_idx]
497 .name(name() + "." + cstr + "_mshr_accesses")
498 .desc("number of " + cstr + " mshr accesses(hits+misses)")
499 .flags(total | nozero | nonan)
500 ;
501 mshrAccesses[access_idx] =
502 mshr_hits[access_idx] + mshr_misses[access_idx]
503 + mshr_uncacheable[access_idx];
504 }
505
506 demandMshrAccesses
507 .name(name() + ".demand_mshr_accesses")
508 .desc("number of demand (read+write) mshr accesses")
509 .flags(total | nozero | nonan)
510 ;
511 demandMshrAccesses = demandMshrHits + demandMshrMisses;
512
513 overallMshrAccesses
514 .name(name() + ".overall_mshr_accesses")
515 .desc("number of overall (read+write) mshr accesses")
516 .flags(total | nozero | nonan)
517 ;
518 overallMshrAccesses = overallMshrHits + overallMshrMisses
519 + overallMshrUncacheable;
520#endif
521
522 // MSHR miss rate formulas
523 for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
524 MemCmd cmd(access_idx);
525 const string &cstr = cmd.toString();
526
527 mshrMissRate[access_idx]
528 .name(name() + "." + cstr + "_mshr_miss_rate")
529 .desc("mshr miss rate for " + cstr + " accesses")
530 .flags(total | nozero | nonan)
531 ;
532
533 mshrMissRate[access_idx] =
534 mshr_misses[access_idx] / accesses[access_idx];
535 }
536
537 demandMshrMissRate
538 .name(name() + ".demand_mshr_miss_rate")
539 .desc("mshr miss rate for demand accesses")
540 .flags(total)
541 ;
542 demandMshrMissRate = demandMshrMisses / demandAccesses;
543
544 overallMshrMissRate
545 .name(name() + ".overall_mshr_miss_rate")
546 .desc("mshr miss rate for overall accesses")
547 .flags(total)
548 ;
549 overallMshrMissRate = overallMshrMisses / overallAccesses;
550
551 // mshrMiss latency formulas
552 for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
553 MemCmd cmd(access_idx);
554 const string &cstr = cmd.toString();
555
556 avgMshrMissLatency[access_idx]
557 .name(name() + "." + cstr + "_avg_mshr_miss_latency")
558 .desc("average " + cstr + " mshr miss latency")
559 .flags(total | nozero | nonan)
560 ;
561
562 avgMshrMissLatency[access_idx] =
563 mshr_miss_latency[access_idx] / mshr_misses[access_idx];
564 }
565
566 demandAvgMshrMissLatency
567 .name(name() + ".demand_avg_mshr_miss_latency")
568 .desc("average overall mshr miss latency")
569 .flags(total)
570 ;
571 demandAvgMshrMissLatency = demandMshrMissLatency / demandMshrMisses;
572
573 overallAvgMshrMissLatency
574 .name(name() + ".overall_avg_mshr_miss_latency")
575 .desc("average overall mshr miss latency")
576 .flags(total)
577 ;
578 overallAvgMshrMissLatency = overallMshrMissLatency / overallMshrMisses;
579
580 // mshrUncacheable latency formulas
581 for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
582 MemCmd cmd(access_idx);
583 const string &cstr = cmd.toString();
584
585 avgMshrUncacheableLatency[access_idx]
586 .name(name() + "." + cstr + "_avg_mshr_uncacheable_latency")
587 .desc("average " + cstr + " mshr uncacheable latency")
588 .flags(total | nozero | nonan)
589 ;
590
591 avgMshrUncacheableLatency[access_idx] =
592 mshr_uncacheable_lat[access_idx] / mshr_uncacheable[access_idx];
593 }
594
595 overallAvgMshrUncacheableLatency
596 .name(name() + ".overall_avg_mshr_uncacheable_latency")
597 .desc("average overall mshr uncacheable latency")
598 .flags(total)
599 ;
600 overallAvgMshrUncacheableLatency = overallMshrUncacheableLatency / overallMshrUncacheable;
601
602 mshr_cap_events
603 .init(maxThreadsPerCPU)
604 .name(name() + ".mshr_cap_events")
605 .desc("number of times MSHR cap was activated")
606 .flags(total)
607 ;
608
609 //software prefetching stats
610 soft_prefetch_mshr_full
611 .init(maxThreadsPerCPU)
612 .name(name() + ".soft_prefetch_mshr_full")
613 .desc("number of mshr full events for SW prefetching instrutions")
614 .flags(total)
615 ;
616
617 mshr_no_allocate_misses
618 .name(name() +".no_allocate_misses")
619 .desc("Number of misses that were no-allocate")
620 ;
621
622}
623
624unsigned int
625BaseCache::drain(Event *de)
626{
627 int count = memSidePort->drain(de) + cpuSidePort->drain(de);
628
629 // Set status
630 if (count != 0) {
631 drainEvent = de;
632
633 changeState(SimObject::Draining);
634 return count;
635 }
636
637 changeState(SimObject::Drained);
638 return 0;
639}