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