base.cc revision 2810
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 "mem/cache/base_cache.hh"
37#include "cpu/smt.hh"
38#include "cpu/base.hh"
39
40using namespace std;
41
42BaseCache::CachePort::CachePort(const std::string &_name, BaseCache *_cache,
43                                bool _isCpuSide)
44    : Port(_name), cache(_cache), isCpuSide(_isCpuSide)
45{
46    blocked = false;
47    //Start ports at null if more than one is created we should panic
48    cpuSidePort = NULL;
49    memSidePort = NULL;
50}
51
52bool
53BaseCache::CachePort::recvStatusChange(Port::Status status)
54{
55    cache->recvStatusChange(status, isCpuSide);
56}
57
58void
59BaseCache::CachePort::getDeviceAddressRanges(AddrRangeList &resp,
60                                       AddrRangeList &snoop)
61{
62    cache->getAddressRanges(resp, snoop);
63}
64
65int
66BaseCache::CachePort::deviceBlockSize()
67{
68    return cache->getBlockSize();
69}
70
71bool
72BaseCache::CachePort::recvTiming(Packet *pkt)
73{
74    return cache->doTimingAccess(pkt, this, isCpuSide);
75}
76
77Tick
78BaseCache::CachePort::recvAtomic(Packet *pkt)
79{
80    return cache->doAtomicAccess(pkt, isCpuSide);
81}
82
83void
84BaseCache::CachePort::recvFunctional(Packet *pkt)
85{
86    cache->doFunctionalAccess(pkt, isCpuSide);
87}
88
89void
90BaseCache::CachePort::setBlocked()
91{
92    blocked = true;
93}
94
95void
96BaseCache::CachePort::clearBlocked()
97{
98    blocked = false;
99}
100
101Port*
102BaseCache::getPort(const std::string &if_name)
103{
104    if(if_name == "cpu_side")
105    {
106        if(cpuSidePort != NULL)
107            panic("Already have a cpu side for this cache\n");
108        cpuSidePort = new CachePort(name() + "-cpu_side_port", this, true);
109        return cpuSidePort;
110    }
111    else if(if_name == "mem_side")
112    {
113        if(memSidePort != NULL)
114            panic("Already have a mem side for this cache\n");
115        memSidePort = new CachePort(name() + "-mem_side_port", this, false);
116        return memSidePort;
117    }
118    else panic("Port name %s unrecognized\n", if_name);
119}
120
121void
122BaseCache::regStats()
123{
124    using namespace Stats;
125
126    // Hit statistics
127    for (int access_idx = 0; access_idx < NUM_MEM_CMDS; ++access_idx) {
128        Packet::Command cmd = (Packet::CommandEnum)access_idx;
129        const string &cstr = cmd.toString();
130
131        hits[access_idx]
132            .init(maxThreadsPerCPU)
133            .name(name() + "." + cstr + "_hits")
134            .desc("number of " + cstr + " hits")
135            .flags(total | nozero | nonan)
136            ;
137    }
138
139    demandHits
140        .name(name() + ".demand_hits")
141        .desc("number of demand (read+write) hits")
142        .flags(total)
143        ;
144    demandHits = hits[Read] + hits[Write];
145
146    overallHits
147        .name(name() + ".overall_hits")
148        .desc("number of overall hits")
149        .flags(total)
150        ;
151    overallHits = demandHits + hits[Soft_Prefetch] + hits[Hard_Prefetch]
152        + hits[Writeback];
153
154    // Miss statistics
155    for (int access_idx = 0; access_idx < NUM_MEM_CMDS; ++access_idx) {
156        Packet::Command cmd = (Packet::CommandEnum)access_idx;
157        const string &cstr = cmd.toString();
158
159        misses[access_idx]
160            .init(maxThreadsPerCPU)
161            .name(name() + "." + cstr + "_misses")
162            .desc("number of " + cstr + " misses")
163            .flags(total | nozero | nonan)
164            ;
165    }
166
167    demandMisses
168        .name(name() + ".demand_misses")
169        .desc("number of demand (read+write) misses")
170        .flags(total)
171        ;
172    demandMisses = misses[Read] + misses[Write];
173
174    overallMisses
175        .name(name() + ".overall_misses")
176        .desc("number of overall misses")
177        .flags(total)
178        ;
179    overallMisses = demandMisses + misses[Soft_Prefetch] +
180        misses[Hard_Prefetch] + misses[Writeback];
181
182    // Miss latency statistics
183    for (int access_idx = 0; access_idx < NUM_MEM_CMDS; ++access_idx) {
184        Packet::Command cmd = (Packet::CommandEnum)access_idx;
185        const string &cstr = cmd.toString();
186
187        missLatency[access_idx]
188            .init(maxThreadsPerCPU)
189            .name(name() + "." + cstr + "_miss_latency")
190            .desc("number of " + cstr + " miss cycles")
191            .flags(total | nozero | nonan)
192            ;
193    }
194
195    demandMissLatency
196        .name(name() + ".demand_miss_latency")
197        .desc("number of demand (read+write) miss cycles")
198        .flags(total)
199        ;
200    demandMissLatency = missLatency[Read] + missLatency[Write];
201
202    overallMissLatency
203        .name(name() + ".overall_miss_latency")
204        .desc("number of overall miss cycles")
205        .flags(total)
206        ;
207    overallMissLatency = demandMissLatency + missLatency[Soft_Prefetch] +
208        missLatency[Hard_Prefetch];
209
210    // access formulas
211    for (int access_idx = 0; access_idx < NUM_MEM_CMDS; ++access_idx) {
212        Packet::Command cmd = (Packet::CommandEnum)access_idx;
213        const string &cstr = cmd.toString();
214
215        accesses[access_idx]
216            .name(name() + "." + cstr + "_accesses")
217            .desc("number of " + cstr + " accesses(hits+misses)")
218            .flags(total | nozero | nonan)
219            ;
220
221        accesses[access_idx] = hits[access_idx] + misses[access_idx];
222    }
223
224    demandAccesses
225        .name(name() + ".demand_accesses")
226        .desc("number of demand (read+write) accesses")
227        .flags(total)
228        ;
229    demandAccesses = demandHits + demandMisses;
230
231    overallAccesses
232        .name(name() + ".overall_accesses")
233        .desc("number of overall (read+write) accesses")
234        .flags(total)
235        ;
236    overallAccesses = overallHits + overallMisses;
237
238    // miss rate formulas
239    for (int access_idx = 0; access_idx < NUM_MEM_CMDS; ++access_idx) {
240        Packet::Command cmd = (Packet::CommandEnum)access_idx;
241        const string &cstr = cmd.toString();
242
243        missRate[access_idx]
244            .name(name() + "." + cstr + "_miss_rate")
245            .desc("miss rate for " + cstr + " accesses")
246            .flags(total | nozero | nonan)
247            ;
248
249        missRate[access_idx] = misses[access_idx] / accesses[access_idx];
250    }
251
252    demandMissRate
253        .name(name() + ".demand_miss_rate")
254        .desc("miss rate for demand accesses")
255        .flags(total)
256        ;
257    demandMissRate = demandMisses / demandAccesses;
258
259    overallMissRate
260        .name(name() + ".overall_miss_rate")
261        .desc("miss rate for overall accesses")
262        .flags(total)
263        ;
264    overallMissRate = overallMisses / overallAccesses;
265
266    // miss latency formulas
267    for (int access_idx = 0; access_idx < NUM_MEM_CMDS; ++access_idx) {
268        Packet::Command cmd = (Packet::CommandEnum)access_idx;
269        const string &cstr = cmd.toString();
270
271        avgMissLatency[access_idx]
272            .name(name() + "." + cstr + "_avg_miss_latency")
273            .desc("average " + cstr + " miss latency")
274            .flags(total | nozero | nonan)
275            ;
276
277        avgMissLatency[access_idx] =
278            missLatency[access_idx] / misses[access_idx];
279    }
280
281    demandAvgMissLatency
282        .name(name() + ".demand_avg_miss_latency")
283        .desc("average overall miss latency")
284        .flags(total)
285        ;
286    demandAvgMissLatency = demandMissLatency / demandMisses;
287
288    overallAvgMissLatency
289        .name(name() + ".overall_avg_miss_latency")
290        .desc("average overall miss latency")
291        .flags(total)
292        ;
293    overallAvgMissLatency = overallMissLatency / overallMisses;
294
295    blocked_cycles.init(NUM_BLOCKED_CAUSES);
296    blocked_cycles
297        .name(name() + ".blocked_cycles")
298        .desc("number of cycles access was blocked")
299        .subname(Blocked_NoMSHRs, "no_mshrs")
300        .subname(Blocked_NoTargets, "no_targets")
301        ;
302
303
304    blocked_causes.init(NUM_BLOCKED_CAUSES);
305    blocked_causes
306        .name(name() + ".blocked")
307        .desc("number of cycles access was blocked")
308        .subname(Blocked_NoMSHRs, "no_mshrs")
309        .subname(Blocked_NoTargets, "no_targets")
310        ;
311
312    avg_blocked
313        .name(name() + ".avg_blocked_cycles")
314        .desc("average number of cycles each access was blocked")
315        .subname(Blocked_NoMSHRs, "no_mshrs")
316        .subname(Blocked_NoTargets, "no_targets")
317        ;
318
319    avg_blocked = blocked_cycles / blocked_causes;
320
321    fastWrites
322        .name(name() + ".fast_writes")
323        .desc("number of fast writes performed")
324        ;
325
326    cacheCopies
327        .name(name() + ".cache_copies")
328        .desc("number of cache copies performed")
329        ;
330}
331