cache_blk.hh revision 4040:eb894f3fc168
15081Sgblack@eecs.umich.edu/*
25081Sgblack@eecs.umich.edu * Copyright (c) 2003-2005 The Regents of The University of Michigan
35081Sgblack@eecs.umich.edu * All rights reserved.
47087Snate@binkert.org *
57087Snate@binkert.org * Redistribution and use in source and binary forms, with or without
67087Snate@binkert.org * modification, are permitted provided that the following conditions are
77087Snate@binkert.org * met: redistributions of source code must retain the above copyright
87087Snate@binkert.org * notice, this list of conditions and the following disclaimer;
97087Snate@binkert.org * redistributions in binary form must reproduce the above copyright
107087Snate@binkert.org * notice, this list of conditions and the following disclaimer in the
117087Snate@binkert.org * documentation and/or other materials provided with the distribution;
125081Sgblack@eecs.umich.edu * neither the name of the copyright holders nor the names of its
137087Snate@binkert.org * contributors may be used to endorse or promote products derived from
147087Snate@binkert.org * this software without specific prior written permission.
157087Snate@binkert.org *
167087Snate@binkert.org * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
177087Snate@binkert.org * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
187087Snate@binkert.org * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
197087Snate@binkert.org * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
207087Snate@binkert.org * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
215081Sgblack@eecs.umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
227087Snate@binkert.org * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
235081Sgblack@eecs.umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
245081Sgblack@eecs.umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
255081Sgblack@eecs.umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
265081Sgblack@eecs.umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
275081Sgblack@eecs.umich.edu *
285081Sgblack@eecs.umich.edu * Authors: Erik Hallnor
295081Sgblack@eecs.umich.edu */
305081Sgblack@eecs.umich.edu
315081Sgblack@eecs.umich.edu/** @file
325081Sgblack@eecs.umich.edu * Definitions of a simple cache block class.
335081Sgblack@eecs.umich.edu */
345081Sgblack@eecs.umich.edu
355081Sgblack@eecs.umich.edu#ifndef __CACHE_BLK_HH__
365081Sgblack@eecs.umich.edu#define __CACHE_BLK_HH__
375081Sgblack@eecs.umich.edu
385081Sgblack@eecs.umich.edu#include <list>
395081Sgblack@eecs.umich.edu
405081Sgblack@eecs.umich.edu#include "sim/root.hh"		// for Tick
415081Sgblack@eecs.umich.edu#include "arch/isa_traits.hh"	// for Addr
42#include "mem/request.hh"
43
44/**
45 * Cache block status bit assignments
46 */
47enum CacheBlkStatusBits {
48    /** valid, readable */
49    BlkValid =		0x01,
50    /** write permission */
51    BlkWritable =	0x02,
52    /** dirty (modified) */
53    BlkDirty =		0x04,
54    /** compressed */
55    BlkCompressed =	0x08,
56    /** block was referenced */
57    BlkReferenced =	0x10,
58    /** block was a hardware prefetch yet unaccessed*/
59    BlkHWPrefetched =	0x20
60};
61
62/**
63 * A Basic Cache block.
64 * Contains the tag, status, and a pointer to data.
65 */
66class CacheBlk
67{
68  public:
69    /** The address space ID of this block. */
70    int asid;
71    /** Data block tag value. */
72    Addr tag;
73    /**
74     * Contains a copy of the data in this block for easy access. This is used
75     * for efficient execution when the data could be actually stored in
76     * another format (COW, compressed, sub-blocked, etc). In all cases the
77     * data stored here should be kept consistant with the actual data
78     * referenced by this block.
79     */
80    uint8_t *data;
81    /** the number of bytes stored in this block. */
82    int size;
83
84    /** block state: OR of CacheBlkStatusBit */
85    typedef unsigned State;
86
87    /** The current status of this block. @sa CacheBlockStatusBits */
88    State status;
89
90    /** Which curTick will this block be accessable */
91    Tick whenReady;
92
93    /**
94     * The set this block belongs to.
95     * @todo Move this into subclasses when we fix CacheTags to use them.
96     */
97    int set;
98
99    /** Number of references to this block since it was brought in. */
100    int refCount;
101
102  protected:
103    /**
104     * Represents that the indicated thread context has a "lock" on
105     * the block, in the LL/SC sense.
106     */
107    class Lock {
108      public:
109        int cpuNum;	// locking CPU
110        int threadNum;	// locking thread ID within CPU
111
112        // check for matching execution context
113        bool matchesContext(Request *req)
114        {
115            return (cpuNum == req->getCpuNum() &&
116                    threadNum == req->getThreadNum());
117        }
118
119        Lock(Request *req)
120            : cpuNum(req->getCpuNum()), threadNum(req->getThreadNum())
121        {
122        }
123    };
124
125    /** List of thread contexts that have performed a load-locked (LL)
126     * on the block since the last store. */
127    std::list<Lock> lockList;
128
129  public:
130
131    CacheBlk()
132        : asid(-1), tag(0), data(0) ,size(0), status(0), whenReady(0),
133          set(-1), refCount(0)
134    {}
135
136    /**
137     * Copy the state of the given block into this one.
138     * @param rhs The block to copy.
139     * @return a const reference to this block.
140     */
141    const CacheBlk& operator=(const CacheBlk& rhs)
142    {
143        asid = rhs.asid;
144        tag = rhs.tag;
145        data = rhs.data;
146        size = rhs.size;
147        status = rhs.status;
148        whenReady = rhs.whenReady;
149        set = rhs.set;
150        refCount = rhs.refCount;
151        return *this;
152    }
153
154    /**
155     * Checks the write permissions of this block.
156     * @return True if the block is writable.
157     */
158    bool isWritable() const
159    {
160        const int needed_bits = BlkWritable | BlkValid;
161        return (status & needed_bits) == needed_bits;
162    }
163
164    /**
165     * Checks that a block is valid (readable).
166     * @return True if the block is valid.
167     */
168    bool isValid() const
169    {
170        return (status & BlkValid) != 0;
171    }
172
173    /**
174     * Check to see if a block has been written.
175     * @return True if the block is dirty.
176     */
177    bool isModified() const
178    {
179        return (status & BlkDirty) != 0;
180    }
181
182    /**
183     * Check to see if this block contains compressed data.
184     * @return True iF the block's data is compressed.
185     */
186    bool isCompressed() const
187    {
188        return (status & BlkCompressed) != 0;
189    }
190
191    /**
192     * Check if this block has been referenced.
193     * @return True if the block has been referenced.
194     */
195    bool isReferenced() const
196    {
197        return (status & BlkReferenced) != 0;
198    }
199
200    /**
201     * Check if this block was the result of a hardware prefetch, yet to
202     * be touched.
203     * @return True if the block was a hardware prefetch, unaccesed.
204     */
205    bool isPrefetch() const
206    {
207        return (status & BlkHWPrefetched) != 0;
208    }
209
210    /**
211     * Track the fact that a local locked was issued to the block.  If
212     * multiple LLs get issued from the same context we could have
213     * redundant records on the list, but that's OK, as they'll all
214     * get blown away at the next store.
215     */
216    void trackLoadLocked(Request *req)
217    {
218        assert(req->isLocked());
219        lockList.push_front(Lock(req));
220    }
221
222    /**
223     * Clear the list of valid load locks.  Should be called whenever
224     * block is written to or invalidated.
225     */
226    void clearLoadLocks() { lockList.clear(); }
227
228    /**
229     * Handle interaction of load-locked operations and stores.
230     * @return True if write should proceed, false otherwise.  Returns
231     * false only in the case of a failed store conditional.
232     */
233    bool checkWrite(Request *req)
234    {
235        if (req->isLocked()) {
236            // it's a store conditional... have to check for matching
237            // load locked.
238            bool success = false;
239
240            for (std::list<Lock>::iterator i = lockList.begin();
241                 i != lockList.end(); ++i)
242            {
243                if (i->matchesContext(req)) {
244                    // it's a store conditional, and as far as the memory
245                    // system can tell, the requesting context's lock is
246                    // still valid.
247                    success = true;
248                    break;
249                }
250            }
251
252            req->setExtraData(success ? 1 : 0);
253            clearLoadLocks();
254            return success;
255        } else {
256            // for *all* stores (conditional or otherwise) we have to
257            // clear the list of load-locks as they're all invalid now.
258            clearLoadLocks();
259            return true;
260        }
261    }
262};
263
264#endif //__CACHE_BLK_HH__
265