A few minor non-debug compilation issues.
[gem5.git] / src / mem / cache / base_cache.hh
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 * Steve Reinhardt
30 * Ron Dreslinski
31 */
32
33 /**
34 * @file
35 * Declares a basic cache interface BaseCache.
36 */
37
38 #ifndef __BASE_CACHE_HH__
39 #define __BASE_CACHE_HH__
40
41 #include <vector>
42 #include <string>
43 #include <list>
44 #include <algorithm>
45 #include <inttypes.h>
46
47 #include "base/misc.hh"
48 #include "base/statistics.hh"
49 #include "base/trace.hh"
50 #include "mem/cache/miss/mshr_queue.hh"
51 #include "mem/mem_object.hh"
52 #include "mem/packet.hh"
53 #include "mem/tport.hh"
54 #include "mem/request.hh"
55 #include "sim/eventq.hh"
56 #include "sim/sim_exit.hh"
57
58 class MSHR;
59 /**
60 * A basic cache interface. Implements some common functions for speed.
61 */
62 class BaseCache : public MemObject
63 {
64 /**
65 * Indexes to enumerate the MSHR queues.
66 */
67 enum MSHRQueueIndex {
68 MSHRQueue_MSHRs,
69 MSHRQueue_WriteBuffer
70 };
71
72 /**
73 * Reasons for caches to be blocked.
74 */
75 enum BlockedCause {
76 Blocked_NoMSHRs = MSHRQueue_MSHRs,
77 Blocked_NoWBBuffers = MSHRQueue_WriteBuffer,
78 Blocked_NoTargets,
79 NUM_BLOCKED_CAUSES
80 };
81
82 public:
83 /**
84 * Reasons for cache to request a bus.
85 */
86 enum RequestCause {
87 Request_MSHR = MSHRQueue_MSHRs,
88 Request_WB = MSHRQueue_WriteBuffer,
89 Request_PF,
90 NUM_REQUEST_CAUSES
91 };
92
93 private:
94
95 class CachePort : public SimpleTimingPort
96 {
97 public:
98 BaseCache *cache;
99
100 protected:
101 CachePort(const std::string &_name, BaseCache *_cache);
102
103 virtual void recvStatusChange(Status status);
104
105 virtual int deviceBlockSize();
106
107 bool recvRetryCommon();
108
109 typedef EventWrapper<Port, &Port::sendRetry>
110 SendRetryEvent;
111
112 public:
113 void setOtherPort(CachePort *_otherPort) { otherPort = _otherPort; }
114
115 void setBlocked();
116
117 void clearBlocked();
118
119 void checkAndSendFunctional(PacketPtr pkt);
120
121 CachePort *otherPort;
122
123 bool blocked;
124
125 bool mustSendRetry;
126
127 void requestBus(RequestCause cause, Tick time)
128 {
129 DPRINTF(CachePort, "Asserting bus request for cause %d\n", cause);
130 if (!waitingOnRetry) {
131 schedSendEvent(time);
132 }
133 }
134
135 void respond(PacketPtr pkt, Tick time) {
136 schedSendTiming(pkt, time);
137 }
138 };
139
140 public: //Made public so coherence can get at it.
141 CachePort *cpuSidePort;
142 CachePort *memSidePort;
143
144 protected:
145
146 /** Miss status registers */
147 MSHRQueue mshrQueue;
148
149 /** Write/writeback buffer */
150 MSHRQueue writeBuffer;
151
152 MSHR *allocateBufferInternal(MSHRQueue *mq, Addr addr, int size,
153 PacketPtr pkt, Tick time, bool requestBus)
154 {
155 MSHR *mshr = mq->allocate(addr, size, pkt, time, order++);
156
157 if (mq->isFull()) {
158 setBlocked((BlockedCause)mq->index);
159 }
160
161 if (requestBus) {
162 requestMemSideBus((RequestCause)mq->index, time);
163 }
164
165 return mshr;
166 }
167
168 void markInServiceInternal(MSHR *mshr)
169 {
170 MSHRQueue *mq = mshr->queue;
171 bool wasFull = mq->isFull();
172 mq->markInService(mshr);
173 if (wasFull && !mq->isFull()) {
174 clearBlocked((BlockedCause)mq->index);
175 }
176 }
177
178 /** Block size of this cache */
179 const int blkSize;
180
181 /**
182 * The latency of a hit in this device.
183 */
184 int hitLatency;
185
186 /** The number of targets for each MSHR. */
187 const int numTarget;
188
189 /** Increasing order number assigned to each incoming request. */
190 uint64_t order;
191
192 /**
193 * Bit vector of the blocking reasons for the access path.
194 * @sa #BlockedCause
195 */
196 uint8_t blocked;
197
198 /** Stores time the cache blocked for statistics. */
199 Tick blockedCycle;
200
201 /** Pointer to the MSHR that has no targets. */
202 MSHR *noTargetMSHR;
203
204 /** The number of misses to trigger an exit event. */
205 Counter missCount;
206
207 /** The drain event. */
208 Event *drainEvent;
209
210 public:
211 // Statistics
212 /**
213 * @addtogroup CacheStatistics
214 * @{
215 */
216
217 /** Number of hits per thread for each type of command. @sa Packet::Command */
218 Stats::Vector<> hits[MemCmd::NUM_MEM_CMDS];
219 /** Number of hits for demand accesses. */
220 Stats::Formula demandHits;
221 /** Number of hit for all accesses. */
222 Stats::Formula overallHits;
223
224 /** Number of misses per thread for each type of command. @sa Packet::Command */
225 Stats::Vector<> misses[MemCmd::NUM_MEM_CMDS];
226 /** Number of misses for demand accesses. */
227 Stats::Formula demandMisses;
228 /** Number of misses for all accesses. */
229 Stats::Formula overallMisses;
230
231 /**
232 * Total number of cycles per thread/command spent waiting for a miss.
233 * Used to calculate the average miss latency.
234 */
235 Stats::Vector<> missLatency[MemCmd::NUM_MEM_CMDS];
236 /** Total number of cycles spent waiting for demand misses. */
237 Stats::Formula demandMissLatency;
238 /** Total number of cycles spent waiting for all misses. */
239 Stats::Formula overallMissLatency;
240
241 /** The number of accesses per command and thread. */
242 Stats::Formula accesses[MemCmd::NUM_MEM_CMDS];
243 /** The number of demand accesses. */
244 Stats::Formula demandAccesses;
245 /** The number of overall accesses. */
246 Stats::Formula overallAccesses;
247
248 /** The miss rate per command and thread. */
249 Stats::Formula missRate[MemCmd::NUM_MEM_CMDS];
250 /** The miss rate of all demand accesses. */
251 Stats::Formula demandMissRate;
252 /** The miss rate for all accesses. */
253 Stats::Formula overallMissRate;
254
255 /** The average miss latency per command and thread. */
256 Stats::Formula avgMissLatency[MemCmd::NUM_MEM_CMDS];
257 /** The average miss latency for demand misses. */
258 Stats::Formula demandAvgMissLatency;
259 /** The average miss latency for all misses. */
260 Stats::Formula overallAvgMissLatency;
261
262 /** The total number of cycles blocked for each blocked cause. */
263 Stats::Vector<> blocked_cycles;
264 /** The number of times this cache blocked for each blocked cause. */
265 Stats::Vector<> blocked_causes;
266
267 /** The average number of cycles blocked for each blocked cause. */
268 Stats::Formula avg_blocked;
269
270 /** The number of fast writes (WH64) performed. */
271 Stats::Scalar<> fastWrites;
272
273 /** The number of cache copies performed. */
274 Stats::Scalar<> cacheCopies;
275
276 /** Number of blocks written back per thread. */
277 Stats::Vector<> writebacks;
278
279 /** Number of misses that hit in the MSHRs per command and thread. */
280 Stats::Vector<> mshr_hits[MemCmd::NUM_MEM_CMDS];
281 /** Demand misses that hit in the MSHRs. */
282 Stats::Formula demandMshrHits;
283 /** Total number of misses that hit in the MSHRs. */
284 Stats::Formula overallMshrHits;
285
286 /** Number of misses that miss in the MSHRs, per command and thread. */
287 Stats::Vector<> mshr_misses[MemCmd::NUM_MEM_CMDS];
288 /** Demand misses that miss in the MSHRs. */
289 Stats::Formula demandMshrMisses;
290 /** Total number of misses that miss in the MSHRs. */
291 Stats::Formula overallMshrMisses;
292
293 /** Number of misses that miss in the MSHRs, per command and thread. */
294 Stats::Vector<> mshr_uncacheable[MemCmd::NUM_MEM_CMDS];
295 /** Total number of misses that miss in the MSHRs. */
296 Stats::Formula overallMshrUncacheable;
297
298 /** Total cycle latency of each MSHR miss, per command and thread. */
299 Stats::Vector<> mshr_miss_latency[MemCmd::NUM_MEM_CMDS];
300 /** Total cycle latency of demand MSHR misses. */
301 Stats::Formula demandMshrMissLatency;
302 /** Total cycle latency of overall MSHR misses. */
303 Stats::Formula overallMshrMissLatency;
304
305 /** Total cycle latency of each MSHR miss, per command and thread. */
306 Stats::Vector<> mshr_uncacheable_lat[MemCmd::NUM_MEM_CMDS];
307 /** Total cycle latency of overall MSHR misses. */
308 Stats::Formula overallMshrUncacheableLatency;
309
310 /** The total number of MSHR accesses per command and thread. */
311 Stats::Formula mshrAccesses[MemCmd::NUM_MEM_CMDS];
312 /** The total number of demand MSHR accesses. */
313 Stats::Formula demandMshrAccesses;
314 /** The total number of MSHR accesses. */
315 Stats::Formula overallMshrAccesses;
316
317 /** The miss rate in the MSHRs pre command and thread. */
318 Stats::Formula mshrMissRate[MemCmd::NUM_MEM_CMDS];
319 /** The demand miss rate in the MSHRs. */
320 Stats::Formula demandMshrMissRate;
321 /** The overall miss rate in the MSHRs. */
322 Stats::Formula overallMshrMissRate;
323
324 /** The average latency of an MSHR miss, per command and thread. */
325 Stats::Formula avgMshrMissLatency[MemCmd::NUM_MEM_CMDS];
326 /** The average latency of a demand MSHR miss. */
327 Stats::Formula demandAvgMshrMissLatency;
328 /** The average overall latency of an MSHR miss. */
329 Stats::Formula overallAvgMshrMissLatency;
330
331 /** The average latency of an MSHR miss, per command and thread. */
332 Stats::Formula avgMshrUncacheableLatency[MemCmd::NUM_MEM_CMDS];
333 /** The average overall latency of an MSHR miss. */
334 Stats::Formula overallAvgMshrUncacheableLatency;
335
336 /** The number of times a thread hit its MSHR cap. */
337 Stats::Vector<> mshr_cap_events;
338 /** The number of times software prefetches caused the MSHR to block. */
339 Stats::Vector<> soft_prefetch_mshr_full;
340
341 Stats::Scalar<> mshr_no_allocate_misses;
342
343 /**
344 * @}
345 */
346
347 /**
348 * Register stats for this object.
349 */
350 virtual void regStats();
351
352 public:
353
354 class Params
355 {
356 public:
357 /** The hit latency for this cache. */
358 int hitLatency;
359 /** The block size of this cache. */
360 int blkSize;
361 int numMSHRs;
362 int numTargets;
363 int numWriteBuffers;
364 /**
365 * The maximum number of misses this cache should handle before
366 * ending the simulation.
367 */
368 Counter maxMisses;
369
370 /**
371 * Construct an instance of this parameter class.
372 */
373 Params(int _hitLatency, int _blkSize,
374 int _numMSHRs, int _numTargets, int _numWriteBuffers,
375 Counter _maxMisses)
376 : hitLatency(_hitLatency), blkSize(_blkSize),
377 numMSHRs(_numMSHRs), numTargets(_numTargets),
378 numWriteBuffers(_numWriteBuffers), maxMisses(_maxMisses)
379 {
380 }
381 };
382
383 /**
384 * Create and initialize a basic cache object.
385 * @param name The name of this cache.
386 * @param hier_params Pointer to the HierParams object for this hierarchy
387 * of this cache.
388 * @param params The parameter object for this BaseCache.
389 */
390 BaseCache(const std::string &name, Params &params);
391
392 ~BaseCache()
393 {
394 }
395
396 virtual void init();
397
398 /**
399 * Query block size of a cache.
400 * @return The block size
401 */
402 int getBlockSize() const
403 {
404 return blkSize;
405 }
406
407
408 Addr blockAlign(Addr addr) const { return (addr & ~(blkSize - 1)); }
409
410
411 MSHR *allocateMissBuffer(PacketPtr pkt, Tick time, bool requestBus)
412 {
413 assert(!pkt->req->isUncacheable());
414 return allocateBufferInternal(&mshrQueue,
415 blockAlign(pkt->getAddr()), blkSize,
416 pkt, time, requestBus);
417 }
418
419 MSHR *allocateWriteBuffer(PacketPtr pkt, Tick time, bool requestBus)
420 {
421 assert(pkt->isWrite() && !pkt->isRead());
422 return allocateBufferInternal(&writeBuffer,
423 pkt->getAddr(), pkt->getSize(),
424 pkt, time, requestBus);
425 }
426
427 MSHR *allocateUncachedReadBuffer(PacketPtr pkt, Tick time, bool requestBus)
428 {
429 assert(pkt->req->isUncacheable());
430 assert(pkt->isRead());
431 return allocateBufferInternal(&mshrQueue,
432 pkt->getAddr(), pkt->getSize(),
433 pkt, time, requestBus);
434 }
435
436 /**
437 * Returns true if the cache is blocked for accesses.
438 */
439 bool isBlocked()
440 {
441 return blocked != 0;
442 }
443
444 /**
445 * Marks the access path of the cache as blocked for the given cause. This
446 * also sets the blocked flag in the slave interface.
447 * @param cause The reason for the cache blocking.
448 */
449 void setBlocked(BlockedCause cause)
450 {
451 uint8_t flag = 1 << cause;
452 if (blocked == 0) {
453 blocked_causes[cause]++;
454 blockedCycle = curTick;
455 cpuSidePort->setBlocked();
456 }
457 blocked |= flag;
458 DPRINTF(Cache,"Blocking for cause %d, mask=%d\n", cause, blocked);
459 }
460
461 /**
462 * Marks the cache as unblocked for the given cause. This also clears the
463 * blocked flags in the appropriate interfaces.
464 * @param cause The newly unblocked cause.
465 * @warning Calling this function can cause a blocked request on the bus to
466 * access the cache. The cache must be in a state to handle that request.
467 */
468 void clearBlocked(BlockedCause cause)
469 {
470 uint8_t flag = 1 << cause;
471 blocked &= ~flag;
472 DPRINTF(Cache,"Unblocking for cause %d, mask=%d\n", cause, blocked);
473 if (blocked == 0) {
474 blocked_cycles[cause] += curTick - blockedCycle;
475 cpuSidePort->clearBlocked();
476 }
477 }
478
479 Tick nextMSHRReadyTime()
480 {
481 return std::min(mshrQueue.nextMSHRReadyTime(),
482 writeBuffer.nextMSHRReadyTime());
483 }
484
485 /**
486 * Request the master bus for the given cause and time.
487 * @param cause The reason for the request.
488 * @param time The time to make the request.
489 */
490 void requestMemSideBus(RequestCause cause, Tick time)
491 {
492 memSidePort->requestBus(cause, time);
493 }
494
495 /**
496 * Clear the master bus request for the given cause.
497 * @param cause The request reason to clear.
498 */
499 void deassertMemSideBusRequest(RequestCause cause)
500 {
501 // obsolete!!
502 assert(false);
503 // memSidePort->deassertBusRequest(cause);
504 // checkDrain();
505 }
506
507 virtual unsigned int drain(Event *de);
508
509 virtual bool inCache(Addr addr) = 0;
510
511 virtual bool inMissQueue(Addr addr) = 0;
512
513 void incMissCount(PacketPtr pkt)
514 {
515 misses[pkt->cmdToIndex()][0/*pkt->req->getThreadNum()*/]++;
516
517 if (missCount) {
518 --missCount;
519 if (missCount == 0)
520 exitSimLoop("A cache reached the maximum miss count");
521 }
522 }
523
524 };
525
526 #endif //__BASE_CACHE_HH__