Fix the packet data allocation methods. Small fixes from changesets after my initial...
[gem5.git] / src / mem / cache / base_cache.cc
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
40 using namespace std;
41
42 BaseCache::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
52 void
53 BaseCache::CachePort::recvStatusChange(Port::Status status)
54 {
55 cache->recvStatusChange(status, isCpuSide);
56 }
57
58 void
59 BaseCache::CachePort::getDeviceAddressRanges(AddrRangeList &resp,
60 AddrRangeList &snoop)
61 {
62 cache->getAddressRanges(resp, snoop);
63 }
64
65 int
66 BaseCache::CachePort::deviceBlockSize()
67 {
68 return cache->getBlockSize();
69 }
70
71 bool
72 BaseCache::CachePort::recvTiming(Packet *pkt)
73 {
74 return cache->doTimingAccess(pkt, this, isCpuSide);
75 }
76
77 Tick
78 BaseCache::CachePort::recvAtomic(Packet *pkt)
79 {
80 return cache->doAtomicAccess(pkt, isCpuSide);
81 }
82
83 void
84 BaseCache::CachePort::recvFunctional(Packet *pkt)
85 {
86 cache->doFunctionalAccess(pkt, isCpuSide);
87 }
88
89 void
90 BaseCache::CachePort::setBlocked()
91 {
92 blocked = true;
93 }
94
95 void
96 BaseCache::CachePort::clearBlocked()
97 {
98 blocked = false;
99 }
100
101 Port*
102 BaseCache::getPort(const std::string &if_name, int idx)
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
121 void
122 BaseCache::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 }