mem-cache: Remove isTouched field from the CacheBlk
[gem5.git] / src / mem / cache / blk.hh
1 /*
2 * Copyright (c) 2012-2017 ARM Limited
3 * All rights reserved.
4 *
5 * The license below extends only to copyright in the software and shall
6 * not be construed as granting a license to any other intellectual
7 * property including but not limited to intellectual property relating
8 * to a hardware implementation of the functionality of the software
9 * licensed hereunder. You may use the software subject to the license
10 * terms below provided that you ensure that this notice is replicated
11 * unmodified and in its entirety in all distributions of the software,
12 * modified or unmodified, in source code or in binary form.
13 *
14 * Copyright (c) 2003-2005 The Regents of The University of Michigan
15 * All rights reserved.
16 *
17 * Redistribution and use in source and binary forms, with or without
18 * modification, are permitted provided that the following conditions are
19 * met: redistributions of source code must retain the above copyright
20 * notice, this list of conditions and the following disclaimer;
21 * redistributions in binary form must reproduce the above copyright
22 * notice, this list of conditions and the following disclaimer in the
23 * documentation and/or other materials provided with the distribution;
24 * neither the name of the copyright holders nor the names of its
25 * contributors may be used to endorse or promote products derived from
26 * this software without specific prior written permission.
27 *
28 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
29 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
30 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
31 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
32 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
33 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
34 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
35 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
36 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
37 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
38 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
39 *
40 * Authors: Erik Hallnor
41 * Andreas Sandberg
42 */
43
44 /** @file
45 * Definitions of a simple cache block class.
46 */
47
48 #ifndef __MEM_CACHE_BLK_HH__
49 #define __MEM_CACHE_BLK_HH__
50
51 #include <list>
52
53 #include "base/printable.hh"
54 #include "mem/cache/replacement_policies/base.hh"
55 #include "mem/packet.hh"
56 #include "mem/request.hh"
57
58 /**
59 * Cache block status bit assignments
60 */
61 enum CacheBlkStatusBits : unsigned {
62 /** valid, readable */
63 BlkValid = 0x01,
64 /** write permission */
65 BlkWritable = 0x02,
66 /** read permission (yes, block can be valid but not readable) */
67 BlkReadable = 0x04,
68 /** dirty (modified) */
69 BlkDirty = 0x08,
70 /** block was a hardware prefetch yet unaccessed*/
71 BlkHWPrefetched = 0x20,
72 /** block holds data from the secure memory space */
73 BlkSecure = 0x40,
74 };
75
76 /**
77 * A Basic Cache block.
78 * Contains the tag, status, and a pointer to data.
79 */
80 class CacheBlk : public ReplaceableEntry
81 {
82 public:
83 /** Task Id associated with this block */
84 uint32_t task_id;
85
86 /** Data block tag value. */
87 Addr tag;
88 /**
89 * Contains a copy of the data in this block for easy access. This is used
90 * for efficient execution when the data could be actually stored in
91 * another format (COW, compressed, sub-blocked, etc). In all cases the
92 * data stored here should be kept consistant with the actual data
93 * referenced by this block.
94 */
95 uint8_t *data;
96
97 /** block state: OR of CacheBlkStatusBit */
98 typedef unsigned State;
99
100 /** The current status of this block. @sa CacheBlockStatusBits */
101 State status;
102
103 /** Which curTick() will this block be accessible */
104 Tick whenReady;
105
106 /**
107 * The set and way this block belongs to.
108 * @todo Move this into subclasses when we fix CacheTags to use them.
109 */
110 int set, way;
111
112 /** Number of references to this block since it was brought in. */
113 unsigned refCount;
114
115 /** holds the source requestor ID for this block. */
116 int srcMasterId;
117
118 /** Tick on which the block was inserted in the cache. */
119 Tick tickInserted;
120
121 protected:
122 /**
123 * Represents that the indicated thread context has a "lock" on
124 * the block, in the LL/SC sense.
125 */
126 class Lock {
127 public:
128 ContextID contextId; // locking context
129 Addr lowAddr; // low address of lock range
130 Addr highAddr; // high address of lock range
131
132 // check for matching execution context, and an address that
133 // is within the lock
134 bool matches(const RequestPtr req) const
135 {
136 Addr req_low = req->getPaddr();
137 Addr req_high = req_low + req->getSize() -1;
138 return (contextId == req->contextId()) &&
139 (req_low >= lowAddr) && (req_high <= highAddr);
140 }
141
142 // check if a request is intersecting and thus invalidating the lock
143 bool intersects(const RequestPtr req) const
144 {
145 Addr req_low = req->getPaddr();
146 Addr req_high = req_low + req->getSize() - 1;
147
148 return (req_low <= highAddr) && (req_high >= lowAddr);
149 }
150
151 Lock(const RequestPtr req)
152 : contextId(req->contextId()),
153 lowAddr(req->getPaddr()),
154 highAddr(lowAddr + req->getSize() - 1)
155 {
156 }
157 };
158
159 /** List of thread contexts that have performed a load-locked (LL)
160 * on the block since the last store. */
161 std::list<Lock> lockList;
162
163 public:
164
165 CacheBlk()
166 {
167 invalidate();
168 }
169
170 CacheBlk(const CacheBlk&) = delete;
171 CacheBlk& operator=(const CacheBlk&) = delete;
172 virtual ~CacheBlk() {};
173
174 /**
175 * Checks the write permissions of this block.
176 * @return True if the block is writable.
177 */
178 bool isWritable() const
179 {
180 const State needed_bits = BlkWritable | BlkValid;
181 return (status & needed_bits) == needed_bits;
182 }
183
184 /**
185 * Checks the read permissions of this block. Note that a block
186 * can be valid but not readable if there is an outstanding write
187 * upgrade miss.
188 * @return True if the block is readable.
189 */
190 bool isReadable() const
191 {
192 const State needed_bits = BlkReadable | BlkValid;
193 return (status & needed_bits) == needed_bits;
194 }
195
196 /**
197 * Checks that a block is valid.
198 * @return True if the block is valid.
199 */
200 bool isValid() const
201 {
202 return (status & BlkValid) != 0;
203 }
204
205 /**
206 * Invalidate the block and clear all state.
207 */
208 virtual void invalidate()
209 {
210 tag = MaxAddr;
211 task_id = ContextSwitchTaskId::Unknown;
212 status = 0;
213 whenReady = MaxTick;
214 refCount = 0;
215 srcMasterId = Request::invldMasterId;
216 tickInserted = MaxTick;
217 lockList.clear();
218 }
219
220 /**
221 * Check to see if a block has been written.
222 * @return True if the block is dirty.
223 */
224 bool isDirty() const
225 {
226 return (status & BlkDirty) != 0;
227 }
228
229 /**
230 * Check if this block was the result of a hardware prefetch, yet to
231 * be touched.
232 * @return True if the block was a hardware prefetch, unaccesed.
233 */
234 bool wasPrefetched() const
235 {
236 return (status & BlkHWPrefetched) != 0;
237 }
238
239 /**
240 * Check if this block holds data from the secure memory space.
241 * @return True if the block holds data from the secure memory space.
242 */
243 bool isSecure() const
244 {
245 return (status & BlkSecure) != 0;
246 }
247
248 /**
249 * Set member variables when a block insertion occurs. Resets reference
250 * count to 1 (the insertion counts as a reference), and touch block if
251 * it hadn't been touched previously. Sets the insertion tick to the
252 * current tick. Does not make block valid.
253 *
254 * @param tag Block address tag.
255 * @param is_secure Whether the block is in secure space or not.
256 * @param src_master_ID The source requestor ID.
257 * @param task_ID The new task ID.
258 */
259 void insert(const Addr tag, const State is_secure, const int src_master_ID,
260 const uint32_t task_ID);
261
262 /**
263 * Track the fact that a local locked was issued to the
264 * block. Invalidate any previous LL to the same address.
265 */
266 void trackLoadLocked(PacketPtr pkt)
267 {
268 assert(pkt->isLLSC());
269 auto l = lockList.begin();
270 while (l != lockList.end()) {
271 if (l->intersects(pkt->req))
272 l = lockList.erase(l);
273 else
274 ++l;
275 }
276
277 lockList.emplace_front(pkt->req);
278 }
279
280 /**
281 * Clear the any load lock that intersect the request, and is from
282 * a different context.
283 */
284 void clearLoadLocks(RequestPtr req)
285 {
286 auto l = lockList.begin();
287 while (l != lockList.end()) {
288 if (l->intersects(req) && l->contextId != req->contextId()) {
289 l = lockList.erase(l);
290 } else {
291 ++l;
292 }
293 }
294 }
295
296 /**
297 * Pretty-print a tag, and interpret state bits to readable form
298 * including mapping to a MOESI state.
299 *
300 * @return string with basic state information
301 */
302 std::string print() const
303 {
304 /**
305 * state M O E S I
306 * writable 1 0 1 0 0
307 * dirty 1 1 0 0 0
308 * valid 1 1 1 1 0
309 *
310 * state writable dirty valid
311 * M 1 1 1
312 * O 0 1 1
313 * E 1 0 1
314 * S 0 0 1
315 * I 0 0 0
316 *
317 * Note that only one cache ever has a block in Modified or
318 * Owned state, i.e., only one cache owns the block, or
319 * equivalently has the BlkDirty bit set. However, multiple
320 * caches on the same path to memory can have a block in the
321 * Exclusive state (despite the name). Exclusive means this
322 * cache has the only copy at this level of the hierarchy,
323 * i.e., there may be copies in caches above this cache (in
324 * various states), but there are no peers that have copies on
325 * this branch of the hierarchy, and no caches at or above
326 * this level on any other branch have copies either.
327 **/
328 unsigned state = isWritable() << 2 | isDirty() << 1 | isValid();
329 char s = '?';
330 switch (state) {
331 case 0b111: s = 'M'; break;
332 case 0b011: s = 'O'; break;
333 case 0b101: s = 'E'; break;
334 case 0b001: s = 'S'; break;
335 case 0b000: s = 'I'; break;
336 default: s = 'T'; break; // @TODO add other types
337 }
338 return csprintf("state: %x (%c) valid: %d writable: %d readable: %d "
339 "dirty: %d tag: %x", status, s, isValid(),
340 isWritable(), isReadable(), isDirty(), tag);
341 }
342
343 /**
344 * Handle interaction of load-locked operations and stores.
345 * @return True if write should proceed, false otherwise. Returns
346 * false only in the case of a failed store conditional.
347 */
348 bool checkWrite(PacketPtr pkt)
349 {
350 assert(pkt->isWrite());
351
352 // common case
353 if (!pkt->isLLSC() && lockList.empty())
354 return true;
355
356 RequestPtr req = pkt->req;
357
358 if (pkt->isLLSC()) {
359 // it's a store conditional... have to check for matching
360 // load locked.
361 bool success = false;
362
363 auto l = lockList.begin();
364 while (!success && l != lockList.end()) {
365 if (l->matches(pkt->req)) {
366 // it's a store conditional, and as far as the
367 // memory system can tell, the requesting
368 // context's lock is still valid.
369 success = true;
370 lockList.erase(l);
371 } else {
372 ++l;
373 }
374 }
375
376 req->setExtraData(success ? 1 : 0);
377 // clear any intersected locks from other contexts (our LL
378 // should already have cleared them)
379 clearLoadLocks(req);
380 return success;
381 } else {
382 // a normal write, if there is any lock not from this
383 // context we clear the list, thus for a private cache we
384 // never clear locks on normal writes
385 clearLoadLocks(req);
386 return true;
387 }
388 }
389 };
390
391 /**
392 * Simple class to provide virtual print() method on cache blocks
393 * without allocating a vtable pointer for every single cache block.
394 * Just wrap the CacheBlk object in an instance of this before passing
395 * to a function that requires a Printable object.
396 */
397 class CacheBlkPrintWrapper : public Printable
398 {
399 CacheBlk *blk;
400 public:
401 CacheBlkPrintWrapper(CacheBlk *_blk) : blk(_blk) {}
402 virtual ~CacheBlkPrintWrapper() {}
403 void print(std::ostream &o, int verbosity = 0,
404 const std::string &prefix = "") const;
405 };
406
407 /**
408 * Base class for cache block visitor, operating on the cache block
409 * base class (later subclassed for the various tag classes). This
410 * visitor class is used as part of the forEachBlk interface in the
411 * tag classes.
412 */
413 class CacheBlkVisitor
414 {
415 public:
416
417 CacheBlkVisitor() {}
418 virtual ~CacheBlkVisitor() {}
419
420 virtual bool operator()(CacheBlk &blk) = 0;
421 };
422
423 #endif //__MEM_CACHE_BLK_HH__