base.cc revision 2811
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
52void
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    Request temp_req;
125    Packet::Command temp_cmd = Packet::ReadReq;
126    Packet temp_pkt(&temp_req, temp_cmd, 0);  //@todo FIx command strings so this isn't neccessary
127
128    using namespace Stats;
129
130    // Hit statistics
131    for (int access_idx = 0; access_idx < NUM_MEM_CMDS; ++access_idx) {
132        Packet::Command cmd = (Packet::Command)access_idx;
133        const string &cstr = temp_pkt.cmdIdxToString(cmd);
134
135        hits[access_idx]
136            .init(maxThreadsPerCPU)
137            .name(name() + "." + cstr + "_hits")
138            .desc("number of " + cstr + " hits")
139            .flags(total | nozero | nonan)
140            ;
141    }
142
143    demandHits
144        .name(name() + ".demand_hits")
145        .desc("number of demand (read+write) hits")
146        .flags(total)
147        ;
148    demandHits = hits[Packet::ReadReq] + hits[Packet::WriteReq];
149
150    overallHits
151        .name(name() + ".overall_hits")
152        .desc("number of overall hits")
153        .flags(total)
154        ;
155    overallHits = demandHits + hits[Packet::SoftPFReq] + hits[Packet::HardPFReq]
156        + hits[Packet::Writeback];
157
158    // Miss statistics
159    for (int access_idx = 0; access_idx < NUM_MEM_CMDS; ++access_idx) {
160        Packet::Command cmd = (Packet::Command)access_idx;
161        const string &cstr = temp_pkt.cmdIdxToString(cmd);
162
163        misses[access_idx]
164            .init(maxThreadsPerCPU)
165            .name(name() + "." + cstr + "_misses")
166            .desc("number of " + cstr + " misses")
167            .flags(total | nozero | nonan)
168            ;
169    }
170
171    demandMisses
172        .name(name() + ".demand_misses")
173        .desc("number of demand (read+write) misses")
174        .flags(total)
175        ;
176    demandMisses = misses[Packet::ReadReq] + misses[Packet::WriteReq];
177
178    overallMisses
179        .name(name() + ".overall_misses")
180        .desc("number of overall misses")
181        .flags(total)
182        ;
183    overallMisses = demandMisses + misses[Packet::SoftPFReq] +
184        misses[Packet::HardPFReq] + misses[Packet::Writeback];
185
186    // Miss latency statistics
187    for (int access_idx = 0; access_idx < NUM_MEM_CMDS; ++access_idx) {
188        Packet::Command cmd = (Packet::Command)access_idx;
189        const string &cstr = temp_pkt.cmdIdxToString(cmd);
190
191        missLatency[access_idx]
192            .init(maxThreadsPerCPU)
193            .name(name() + "." + cstr + "_miss_latency")
194            .desc("number of " + cstr + " miss cycles")
195            .flags(total | nozero | nonan)
196            ;
197    }
198
199    demandMissLatency
200        .name(name() + ".demand_miss_latency")
201        .desc("number of demand (read+write) miss cycles")
202        .flags(total)
203        ;
204    demandMissLatency = missLatency[Packet::ReadReq] + missLatency[Packet::WriteReq];
205
206    overallMissLatency
207        .name(name() + ".overall_miss_latency")
208        .desc("number of overall miss cycles")
209        .flags(total)
210        ;
211    overallMissLatency = demandMissLatency + missLatency[Packet::SoftPFReq] +
212        missLatency[Packet::HardPFReq];
213
214    // access formulas
215    for (int access_idx = 0; access_idx < NUM_MEM_CMDS; ++access_idx) {
216        Packet::Command cmd = (Packet::Command)access_idx;
217        const string &cstr = temp_pkt.cmdIdxToString(cmd);
218
219        accesses[access_idx]
220            .name(name() + "." + cstr + "_accesses")
221            .desc("number of " + cstr + " accesses(hits+misses)")
222            .flags(total | nozero | nonan)
223            ;
224
225        accesses[access_idx] = hits[access_idx] + misses[access_idx];
226    }
227
228    demandAccesses
229        .name(name() + ".demand_accesses")
230        .desc("number of demand (read+write) accesses")
231        .flags(total)
232        ;
233    demandAccesses = demandHits + demandMisses;
234
235    overallAccesses
236        .name(name() + ".overall_accesses")
237        .desc("number of overall (read+write) accesses")
238        .flags(total)
239        ;
240    overallAccesses = overallHits + overallMisses;
241
242    // miss rate formulas
243    for (int access_idx = 0; access_idx < NUM_MEM_CMDS; ++access_idx) {
244        Packet::Command cmd = (Packet::Command)access_idx;
245        const string &cstr = temp_pkt.cmdIdxToString(cmd);
246
247        missRate[access_idx]
248            .name(name() + "." + cstr + "_miss_rate")
249            .desc("miss rate for " + cstr + " accesses")
250            .flags(total | nozero | nonan)
251            ;
252
253        missRate[access_idx] = misses[access_idx] / accesses[access_idx];
254    }
255
256    demandMissRate
257        .name(name() + ".demand_miss_rate")
258        .desc("miss rate for demand accesses")
259        .flags(total)
260        ;
261    demandMissRate = demandMisses / demandAccesses;
262
263    overallMissRate
264        .name(name() + ".overall_miss_rate")
265        .desc("miss rate for overall accesses")
266        .flags(total)
267        ;
268    overallMissRate = overallMisses / overallAccesses;
269
270    // miss latency formulas
271    for (int access_idx = 0; access_idx < NUM_MEM_CMDS; ++access_idx) {
272        Packet::Command cmd = (Packet::Command)access_idx;
273        const string &cstr = temp_pkt.cmdIdxToString(cmd);
274
275        avgMissLatency[access_idx]
276            .name(name() + "." + cstr + "_avg_miss_latency")
277            .desc("average " + cstr + " miss latency")
278            .flags(total | nozero | nonan)
279            ;
280
281        avgMissLatency[access_idx] =
282            missLatency[access_idx] / misses[access_idx];
283    }
284
285    demandAvgMissLatency
286        .name(name() + ".demand_avg_miss_latency")
287        .desc("average overall miss latency")
288        .flags(total)
289        ;
290    demandAvgMissLatency = demandMissLatency / demandMisses;
291
292    overallAvgMissLatency
293        .name(name() + ".overall_avg_miss_latency")
294        .desc("average overall miss latency")
295        .flags(total)
296        ;
297    overallAvgMissLatency = overallMissLatency / overallMisses;
298
299    blocked_cycles.init(NUM_BLOCKED_CAUSES);
300    blocked_cycles
301        .name(name() + ".blocked_cycles")
302        .desc("number of cycles access was blocked")
303        .subname(Blocked_NoMSHRs, "no_mshrs")
304        .subname(Blocked_NoTargets, "no_targets")
305        ;
306
307
308    blocked_causes.init(NUM_BLOCKED_CAUSES);
309    blocked_causes
310        .name(name() + ".blocked")
311        .desc("number of cycles access was blocked")
312        .subname(Blocked_NoMSHRs, "no_mshrs")
313        .subname(Blocked_NoTargets, "no_targets")
314        ;
315
316    avg_blocked
317        .name(name() + ".avg_blocked_cycles")
318        .desc("average number of cycles each access was blocked")
319        .subname(Blocked_NoMSHRs, "no_mshrs")
320        .subname(Blocked_NoTargets, "no_targets")
321        ;
322
323    avg_blocked = blocked_cycles / blocked_causes;
324
325    fastWrites
326        .name(name() + ".fast_writes")
327        .desc("number of fast writes performed")
328        ;
329
330    cacheCopies
331        .name(name() + ".cache_copies")
332        .desc("number of cache copies performed")
333        ;
334}
335