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