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