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