Deleted Added
sdiff udiff text old ( 8134:b01a51ff05fa ) new ( 8232:b28d06a175be )
full compact
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 "debug/Cache.hh"
39#include "mem/cache/base.hh"
40#include "mem/cache/mshr.hh"
41
42using namespace std;
43
44BaseCache::CachePort::CachePort(const std::string &_name, BaseCache *_cache,
45 const std::string &_label)
46 : SimpleTimingPort(_name, _cache), cache(_cache),
47 label(_label), otherPort(NULL),
48 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),
61 forwardSnoops(p->forward_snoops),
62 isTopLevel(p->is_top_level),
63 blocked(0),
64 noTargetMSHR(NULL),
65 missCount(p->max_miss_count),
66 drainEvent(NULL),
67 addrRange(p->addr_range),
68 _numCpus(p->num_cpus)
69{
70}
71
72void
73BaseCache::CachePort::recvStatusChange(Port::Status status)
74{
75 if (status == Port::RangeChange) {
76 otherPort->sendStatusChange(Port::RangeChange);
77 }
78}
79
80
81bool
82BaseCache::CachePort::checkFunctional(PacketPtr pkt)
83{
84 pkt->pushLabel(label);
85 bool done = SimpleTimingPort::checkFunctional(pkt);
86 pkt->popLabel();
87 return done;
88}
89
90
91unsigned
92BaseCache::CachePort::deviceBlockSize() const
93{
94 return cache->getBlockSize();
95}
96
97
98bool
99BaseCache::CachePort::recvRetryCommon()
100{
101 assert(waitingOnRetry);
102 waitingOnRetry = false;
103 return false;
104}
105
106
107void
108BaseCache::CachePort::setBlocked()
109{
110 assert(!blocked);
111 DPRINTF(Cache, "Cache Blocking\n");
112 blocked = true;
113 //Clear the retry flag
114 mustSendRetry = false;
115}
116
117void
118BaseCache::CachePort::clearBlocked()
119{
120 assert(blocked);
121 DPRINTF(Cache, "Cache Unblocking\n");
122 blocked = false;
123 if (mustSendRetry)
124 {
125 DPRINTF(Cache, "Cache Sending Retry\n");
126 mustSendRetry = false;
127 SendRetryEvent *ev = new SendRetryEvent(this, true);
128 // @TODO: need to find a better time (next bus cycle?)
129 schedule(ev, curTick() + 1);
130 }
131}
132
133
134void
135BaseCache::init()
136{
137 if (!cpuSidePort || !memSidePort)
138 panic("Cache not hooked up on both sides\n");
139 cpuSidePort->sendStatusChange(Port::RangeChange);
140}
141
142
143void
144BaseCache::regStats()
145{
146 using namespace Stats;
147
148 // Hit statistics
149 for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
150 MemCmd cmd(access_idx);
151 const string &cstr = cmd.toString();
152
153 hits[access_idx]
154#if FULL_SYSTEM
155 .init(_numCpus + 1)
156#else
157 .init(_numCpus)
158#endif
159 .name(name() + "." + cstr + "_hits")
160 .desc("number of " + cstr + " hits")
161 .flags(total | nozero | nonan)
162 ;
163 }
164
165// These macros make it easier to sum the right subset of commands and
166// to change the subset of commands that are considered "demand" vs
167// "non-demand"
168#define SUM_DEMAND(s) \
169 (s[MemCmd::ReadReq] + s[MemCmd::WriteReq] + s[MemCmd::ReadExReq])
170
171// should writebacks be included here? prior code was inconsistent...
172#define SUM_NON_DEMAND(s) \
173 (s[MemCmd::SoftPFReq] + s[MemCmd::HardPFReq])
174
175 demandHits
176 .name(name() + ".demand_hits")
177 .desc("number of demand (read+write) hits")
178 .flags(total)
179 ;
180 demandHits = SUM_DEMAND(hits);
181
182 overallHits
183 .name(name() + ".overall_hits")
184 .desc("number of overall hits")
185 .flags(total)
186 ;
187 overallHits = demandHits + SUM_NON_DEMAND(hits);
188
189 // Miss statistics
190 for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
191 MemCmd cmd(access_idx);
192 const string &cstr = cmd.toString();
193
194 misses[access_idx]
195#if FULL_SYSTEM
196 .init(_numCpus + 1)
197#else
198 .init(_numCpus)
199#endif
200 .name(name() + "." + cstr + "_misses")
201 .desc("number of " + cstr + " misses")
202 .flags(total | nozero | nonan)
203 ;
204 }
205
206 demandMisses
207 .name(name() + ".demand_misses")
208 .desc("number of demand (read+write) misses")
209 .flags(total)
210 ;
211 demandMisses = SUM_DEMAND(misses);
212
213 overallMisses
214 .name(name() + ".overall_misses")
215 .desc("number of overall misses")
216 .flags(total)
217 ;
218 overallMisses = demandMisses + SUM_NON_DEMAND(misses);
219
220 // Miss latency statistics
221 for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
222 MemCmd cmd(access_idx);
223 const string &cstr = cmd.toString();
224
225 missLatency[access_idx]
226 .init(maxThreadsPerCPU)
227 .name(name() + "." + cstr + "_miss_latency")
228 .desc("number of " + cstr + " miss cycles")
229 .flags(total | nozero | nonan)
230 ;
231 }
232
233 demandMissLatency
234 .name(name() + ".demand_miss_latency")
235 .desc("number of demand (read+write) miss cycles")
236 .flags(total)
237 ;
238 demandMissLatency = SUM_DEMAND(missLatency);
239
240 overallMissLatency
241 .name(name() + ".overall_miss_latency")
242 .desc("number of overall miss cycles")
243 .flags(total)
244 ;
245 overallMissLatency = demandMissLatency + SUM_NON_DEMAND(missLatency);
246
247 // access formulas
248 for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
249 MemCmd cmd(access_idx);
250 const string &cstr = cmd.toString();
251
252 accesses[access_idx]
253 .name(name() + "." + cstr + "_accesses")
254 .desc("number of " + cstr + " accesses(hits+misses)")
255 .flags(total | nozero | nonan)
256 ;
257
258 accesses[access_idx] = hits[access_idx] + misses[access_idx];
259 }
260
261 demandAccesses
262 .name(name() + ".demand_accesses")
263 .desc("number of demand (read+write) accesses")
264 .flags(total)
265 ;
266 demandAccesses = demandHits + demandMisses;
267
268 overallAccesses
269 .name(name() + ".overall_accesses")
270 .desc("number of overall (read+write) accesses")
271 .flags(total)
272 ;
273 overallAccesses = overallHits + overallMisses;
274
275 // miss rate formulas
276 for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
277 MemCmd cmd(access_idx);
278 const string &cstr = cmd.toString();
279
280 missRate[access_idx]
281 .name(name() + "." + cstr + "_miss_rate")
282 .desc("miss rate for " + cstr + " accesses")
283 .flags(total | nozero | nonan)
284 ;
285
286 missRate[access_idx] = misses[access_idx] / accesses[access_idx];
287 }
288
289 demandMissRate
290 .name(name() + ".demand_miss_rate")
291 .desc("miss rate for demand accesses")
292 .flags(total)
293 ;
294 demandMissRate = demandMisses / demandAccesses;
295
296 overallMissRate
297 .name(name() + ".overall_miss_rate")
298 .desc("miss rate for overall accesses")
299 .flags(total)
300 ;
301 overallMissRate = overallMisses / overallAccesses;
302
303 // miss latency formulas
304 for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
305 MemCmd cmd(access_idx);
306 const string &cstr = cmd.toString();
307
308 avgMissLatency[access_idx]
309 .name(name() + "." + cstr + "_avg_miss_latency")
310 .desc("average " + cstr + " miss latency")
311 .flags(total | nozero | nonan)
312 ;
313
314 avgMissLatency[access_idx] =
315 missLatency[access_idx] / misses[access_idx];
316 }
317
318 demandAvgMissLatency
319 .name(name() + ".demand_avg_miss_latency")
320 .desc("average overall miss latency")
321 .flags(total)
322 ;
323 demandAvgMissLatency = demandMissLatency / demandMisses;
324
325 overallAvgMissLatency
326 .name(name() + ".overall_avg_miss_latency")
327 .desc("average overall miss latency")
328 .flags(total)
329 ;
330 overallAvgMissLatency = overallMissLatency / overallMisses;
331
332 blocked_cycles.init(NUM_BLOCKED_CAUSES);
333 blocked_cycles
334 .name(name() + ".blocked_cycles")
335 .desc("number of cycles access was blocked")
336 .subname(Blocked_NoMSHRs, "no_mshrs")
337 .subname(Blocked_NoTargets, "no_targets")
338 ;
339
340
341 blocked_causes.init(NUM_BLOCKED_CAUSES);
342 blocked_causes
343 .name(name() + ".blocked")
344 .desc("number of cycles access was blocked")
345 .subname(Blocked_NoMSHRs, "no_mshrs")
346 .subname(Blocked_NoTargets, "no_targets")
347 ;
348
349 avg_blocked
350 .name(name() + ".avg_blocked_cycles")
351 .desc("average number of cycles each access was blocked")
352 .subname(Blocked_NoMSHRs, "no_mshrs")
353 .subname(Blocked_NoTargets, "no_targets")
354 ;
355
356 avg_blocked = blocked_cycles / blocked_causes;
357
358 fastWrites
359 .name(name() + ".fast_writes")
360 .desc("number of fast writes performed")
361 ;
362
363 cacheCopies
364 .name(name() + ".cache_copies")
365 .desc("number of cache copies performed")
366 ;
367
368 writebacks
369 .init(maxThreadsPerCPU)
370 .name(name() + ".writebacks")
371 .desc("number of writebacks")
372 .flags(total)
373 ;
374
375 // MSHR statistics
376 // MSHR hit statistics
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 mshr_hits[access_idx]
382 .init(maxThreadsPerCPU)
383 .name(name() + "." + cstr + "_mshr_hits")
384 .desc("number of " + cstr + " MSHR hits")
385 .flags(total | nozero | nonan)
386 ;
387 }
388
389 demandMshrHits
390 .name(name() + ".demand_mshr_hits")
391 .desc("number of demand (read+write) MSHR hits")
392 .flags(total)
393 ;
394 demandMshrHits = SUM_DEMAND(mshr_hits);
395
396 overallMshrHits
397 .name(name() + ".overall_mshr_hits")
398 .desc("number of overall MSHR hits")
399 .flags(total)
400 ;
401 overallMshrHits = demandMshrHits + SUM_NON_DEMAND(mshr_hits);
402
403 // MSHR miss statistics
404 for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
405 MemCmd cmd(access_idx);
406 const string &cstr = cmd.toString();
407
408 mshr_misses[access_idx]
409 .init(maxThreadsPerCPU)
410 .name(name() + "." + cstr + "_mshr_misses")
411 .desc("number of " + cstr + " MSHR misses")
412 .flags(total | nozero | nonan)
413 ;
414 }
415
416 demandMshrMisses
417 .name(name() + ".demand_mshr_misses")
418 .desc("number of demand (read+write) MSHR misses")
419 .flags(total)
420 ;
421 demandMshrMisses = SUM_DEMAND(mshr_misses);
422
423 overallMshrMisses
424 .name(name() + ".overall_mshr_misses")
425 .desc("number of overall MSHR misses")
426 .flags(total)
427 ;
428 overallMshrMisses = demandMshrMisses + SUM_NON_DEMAND(mshr_misses);
429
430 // MSHR miss latency statistics
431 for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
432 MemCmd cmd(access_idx);
433 const string &cstr = cmd.toString();
434
435 mshr_miss_latency[access_idx]
436 .init(maxThreadsPerCPU)
437 .name(name() + "." + cstr + "_mshr_miss_latency")
438 .desc("number of " + cstr + " MSHR miss cycles")
439 .flags(total | nozero | nonan)
440 ;
441 }
442
443 demandMshrMissLatency
444 .name(name() + ".demand_mshr_miss_latency")
445 .desc("number of demand (read+write) MSHR miss cycles")
446 .flags(total)
447 ;
448 demandMshrMissLatency = SUM_DEMAND(mshr_miss_latency);
449
450 overallMshrMissLatency
451 .name(name() + ".overall_mshr_miss_latency")
452 .desc("number of overall MSHR miss cycles")
453 .flags(total)
454 ;
455 overallMshrMissLatency =
456 demandMshrMissLatency + SUM_NON_DEMAND(mshr_miss_latency);
457
458 // MSHR uncacheable statistics
459 for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
460 MemCmd cmd(access_idx);
461 const string &cstr = cmd.toString();
462
463 mshr_uncacheable[access_idx]
464 .init(maxThreadsPerCPU)
465 .name(name() + "." + cstr + "_mshr_uncacheable")
466 .desc("number of " + cstr + " MSHR uncacheable")
467 .flags(total | nozero | nonan)
468 ;
469 }
470
471 overallMshrUncacheable
472 .name(name() + ".overall_mshr_uncacheable_misses")
473 .desc("number of overall MSHR uncacheable misses")
474 .flags(total)
475 ;
476 overallMshrUncacheable =
477 SUM_DEMAND(mshr_uncacheable) + SUM_NON_DEMAND(mshr_uncacheable);
478
479 // MSHR miss latency statistics
480 for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
481 MemCmd cmd(access_idx);
482 const string &cstr = cmd.toString();
483
484 mshr_uncacheable_lat[access_idx]
485 .init(maxThreadsPerCPU)
486 .name(name() + "." + cstr + "_mshr_uncacheable_latency")
487 .desc("number of " + cstr + " MSHR uncacheable cycles")
488 .flags(total | nozero | nonan)
489 ;
490 }
491
492 overallMshrUncacheableLatency
493 .name(name() + ".overall_mshr_uncacheable_latency")
494 .desc("number of overall MSHR uncacheable cycles")
495 .flags(total)
496 ;
497 overallMshrUncacheableLatency =
498 SUM_DEMAND(mshr_uncacheable_lat) +
499 SUM_NON_DEMAND(mshr_uncacheable_lat);
500
501#if 0
502 // MSHR access formulas
503 for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
504 MemCmd cmd(access_idx);
505 const string &cstr = cmd.toString();
506
507 mshrAccesses[access_idx]
508 .name(name() + "." + cstr + "_mshr_accesses")
509 .desc("number of " + cstr + " mshr accesses(hits+misses)")
510 .flags(total | nozero | nonan)
511 ;
512 mshrAccesses[access_idx] =
513 mshr_hits[access_idx] + mshr_misses[access_idx]
514 + mshr_uncacheable[access_idx];
515 }
516
517 demandMshrAccesses
518 .name(name() + ".demand_mshr_accesses")
519 .desc("number of demand (read+write) mshr accesses")
520 .flags(total | nozero | nonan)
521 ;
522 demandMshrAccesses = demandMshrHits + demandMshrMisses;
523
524 overallMshrAccesses
525 .name(name() + ".overall_mshr_accesses")
526 .desc("number of overall (read+write) mshr accesses")
527 .flags(total | nozero | nonan)
528 ;
529 overallMshrAccesses = overallMshrHits + overallMshrMisses
530 + overallMshrUncacheable;
531#endif
532
533 // MSHR miss rate formulas
534 for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
535 MemCmd cmd(access_idx);
536 const string &cstr = cmd.toString();
537
538 mshrMissRate[access_idx]
539 .name(name() + "." + cstr + "_mshr_miss_rate")
540 .desc("mshr miss rate for " + cstr + " accesses")
541 .flags(total | nozero | nonan)
542 ;
543
544 mshrMissRate[access_idx] =
545 mshr_misses[access_idx] / accesses[access_idx];
546 }
547
548 demandMshrMissRate
549 .name(name() + ".demand_mshr_miss_rate")
550 .desc("mshr miss rate for demand accesses")
551 .flags(total)
552 ;
553 demandMshrMissRate = demandMshrMisses / demandAccesses;
554
555 overallMshrMissRate
556 .name(name() + ".overall_mshr_miss_rate")
557 .desc("mshr miss rate for overall accesses")
558 .flags(total)
559 ;
560 overallMshrMissRate = overallMshrMisses / overallAccesses;
561
562 // mshrMiss latency formulas
563 for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
564 MemCmd cmd(access_idx);
565 const string &cstr = cmd.toString();
566
567 avgMshrMissLatency[access_idx]
568 .name(name() + "." + cstr + "_avg_mshr_miss_latency")
569 .desc("average " + cstr + " mshr miss latency")
570 .flags(total | nozero | nonan)
571 ;
572
573 avgMshrMissLatency[access_idx] =
574 mshr_miss_latency[access_idx] / mshr_misses[access_idx];
575 }
576
577 demandAvgMshrMissLatency
578 .name(name() + ".demand_avg_mshr_miss_latency")
579 .desc("average overall mshr miss latency")
580 .flags(total)
581 ;
582 demandAvgMshrMissLatency = demandMshrMissLatency / demandMshrMisses;
583
584 overallAvgMshrMissLatency
585 .name(name() + ".overall_avg_mshr_miss_latency")
586 .desc("average overall mshr miss latency")
587 .flags(total)
588 ;
589 overallAvgMshrMissLatency = overallMshrMissLatency / overallMshrMisses;
590
591 // mshrUncacheable latency formulas
592 for (int access_idx = 0; access_idx < MemCmd::NUM_MEM_CMDS; ++access_idx) {
593 MemCmd cmd(access_idx);
594 const string &cstr = cmd.toString();
595
596 avgMshrUncacheableLatency[access_idx]
597 .name(name() + "." + cstr + "_avg_mshr_uncacheable_latency")
598 .desc("average " + cstr + " mshr uncacheable latency")
599 .flags(total | nozero | nonan)
600 ;
601
602 avgMshrUncacheableLatency[access_idx] =
603 mshr_uncacheable_lat[access_idx] / mshr_uncacheable[access_idx];
604 }
605
606 overallAvgMshrUncacheableLatency
607 .name(name() + ".overall_avg_mshr_uncacheable_latency")
608 .desc("average overall mshr uncacheable latency")
609 .flags(total)
610 ;
611 overallAvgMshrUncacheableLatency = overallMshrUncacheableLatency / overallMshrUncacheable;
612
613 mshr_cap_events
614 .init(maxThreadsPerCPU)
615 .name(name() + ".mshr_cap_events")
616 .desc("number of times MSHR cap was activated")
617 .flags(total)
618 ;
619
620 //software prefetching stats
621 soft_prefetch_mshr_full
622 .init(maxThreadsPerCPU)
623 .name(name() + ".soft_prefetch_mshr_full")
624 .desc("number of mshr full events for SW prefetching instrutions")
625 .flags(total)
626 ;
627
628 mshr_no_allocate_misses
629 .name(name() +".no_allocate_misses")
630 .desc("Number of misses that were no-allocate")
631 ;
632
633}
634
635unsigned int
636BaseCache::drain(Event *de)
637{
638 int count = memSidePort->drain(de) + cpuSidePort->drain(de);
639
640 // Set status
641 if (count != 0) {
642 drainEvent = de;
643
644 changeState(SimObject::Draining);
645 return count;
646 }
647
648 changeState(SimObject::Drained);
649 return 0;
650}