cache.hh revision 3860:73e3642713a3
1/*
2 * Copyright (c) 2002-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 *          Dave Greene
30 *          Steve Reinhardt
31 */
32
33/**
34 * @file
35 * Describes a cache based on template policies.
36 */
37
38#ifndef __CACHE_HH__
39#define __CACHE_HH__
40
41#include "base/compression/base.hh"
42#include "base/misc.hh" // fatal, panic, and warn
43#include "cpu/smt.hh" // SMT_MAX_THREADS
44
45#include "mem/cache/base_cache.hh"
46#include "mem/cache/cache_blk.hh"
47#include "mem/cache/miss/miss_buffer.hh"
48#include "mem/cache/prefetch/prefetcher.hh"
49
50//Forward decleration
51class MSHR;
52
53
54/**
55 * A template-policy based cache. The behavior of the cache can be altered by
56 * supplying different template policies. TagStore handles all tag and data
57 * storage @sa TagStore. Buffering handles all misses and writes/writebacks
58 * @sa MissQueue. Coherence handles all coherence policy details @sa
59 * UniCoherence, SimpleMultiCoherence.
60 */
61template <class TagStore, class Coherence>
62class Cache : public BaseCache
63{
64  public:
65    /** Define the type of cache block to use. */
66    typedef typename TagStore::BlkType BlkType;
67    /** A typedef for a list of BlkType pointers. */
68    typedef typename TagStore::BlkList BlkList;
69
70    bool prefetchAccess;
71
72  protected:
73
74    class CpuSidePort : public CachePort
75    {
76      public:
77        CpuSidePort(const std::string &_name,
78                    Cache<TagStore,Coherence> *_cache);
79
80        // BaseCache::CachePort just has a BaseCache *; this function
81        // lets us get back the type info we lost when we stored the
82        // cache pointer there.
83        Cache<TagStore,Coherence> *myCache() {
84            return static_cast<Cache<TagStore,Coherence> *>(cache);
85        }
86
87        virtual bool recvTiming(PacketPtr pkt);
88
89        virtual Tick recvAtomic(PacketPtr pkt);
90
91        virtual void recvFunctional(PacketPtr pkt);
92    };
93
94    class MemSidePort : public CachePort
95    {
96      public:
97        MemSidePort(const std::string &_name,
98                    Cache<TagStore,Coherence> *_cache);
99
100        // BaseCache::CachePort just has a BaseCache *; this function
101        // lets us get back the type info we lost when we stored the
102        // cache pointer there.
103        Cache<TagStore,Coherence> *myCache() {
104            return static_cast<Cache<TagStore,Coherence> *>(cache);
105        }
106
107        virtual bool recvTiming(PacketPtr pkt);
108
109        virtual Tick recvAtomic(PacketPtr pkt);
110
111        virtual void recvFunctional(PacketPtr pkt);
112    };
113
114    /** Tag and data Storage */
115    TagStore *tags;
116    /** Miss and Writeback handler */
117    MissBuffer *missQueue;
118    /** Coherence protocol. */
119    Coherence *coherence;
120
121    /** Prefetcher */
122    Prefetcher<TagStore> *prefetcher;
123
124    /**
125     * The clock ratio of the outgoing bus.
126     * Used for calculating critical word first.
127     */
128    int busRatio;
129
130     /**
131      * The bus width in bytes of the outgoing bus.
132      * Used for calculating critical word first.
133      */
134    int busWidth;
135
136    /**
137     * The latency of a hit in this device.
138     */
139    int hitLatency;
140
141     /**
142      * A permanent mem req to always be used to cause invalidations.
143      * Used to append to target list, to cause an invalidation.
144      */
145    PacketPtr invalidatePkt;
146    Request *invalidateReq;
147
148    /**
149     * Policy class for performing compression.
150     */
151    CompressionAlgorithm *compressionAlg;
152
153    /**
154     * The block size of this cache. Set to value in the Tags object.
155     */
156    const int16_t blkSize;
157
158    /**
159     * Can this cache should allocate a block on a line-sized write miss.
160     */
161    const bool doFastWrites;
162
163    const bool prefetchMiss;
164
165    /**
166     * Can the data can be stored in a compressed form.
167     */
168    const bool storeCompressed;
169
170    /**
171     * Do we need to compress blocks on writebacks (i.e. because
172     * writeback bus is compressed but storage is not)?
173     */
174    const bool compressOnWriteback;
175
176    /**
177     * The latency of a compression operation.
178     */
179    const int16_t compLatency;
180
181    /**
182     * Should we use an adaptive compression scheme.
183     */
184    const bool adaptiveCompression;
185
186    /**
187     * Do writebacks need to be compressed (i.e. because writeback bus
188     * is compressed), whether or not they're already compressed for
189     * storage.
190     */
191    const bool writebackCompressed;
192
193    /**
194     * Compare the internal block data to the fast access block data.
195     * @param blk The cache block to check.
196     * @return True if the data is the same.
197     */
198    bool verifyData(BlkType *blk);
199
200    /**
201     * Update the internal data of the block. The data to write is assumed to
202     * be in the fast access data.
203     * @param blk The block with the data to update.
204     * @param writebacks A list to store any generated writebacks.
205     * @param compress_block True if we should compress this block
206     */
207    void updateData(BlkType *blk, PacketList &writebacks, bool compress_block);
208
209    /**
210     * Handle a replacement for the given request.
211     * @param blk A pointer to the block, usually NULL
212     * @param pkt The memory request to satisfy.
213     * @param new_state The new state of the block.
214     * @param writebacks A list to store any generated writebacks.
215     */
216    BlkType* doReplacement(BlkType *blk, PacketPtr &pkt,
217                           CacheBlk::State new_state, PacketList &writebacks);
218
219    /**
220     * Does all the processing necessary to perform the provided request.
221     * @param pkt The memory request to perform.
222     * @param lat The latency of the access.
223     * @param writebacks List for any writebacks that need to be performed.
224     * @param update True if the replacement data should be updated.
225     * @return Pointer to the cache block touched by the request. NULL if it
226     * was a miss.
227     */
228    BlkType* handleAccess(PacketPtr &pkt, int & lat,
229                          PacketList & writebacks, bool update = true);
230
231    /**
232     * Populates a cache block and handles all outstanding requests for the
233     * satisfied fill request. This version takes an MSHR pointer and uses its
234     * request to fill the cache block, while repsonding to its targets.
235     * @param blk The cache block if it already exists.
236     * @param mshr The MSHR that contains the fill data and targets to satisfy.
237     * @param new_state The state of the new cache block.
238     * @param writebacks List for any writebacks that need to be performed.
239     * @return Pointer to the new cache block.
240     */
241    BlkType* handleFill(BlkType *blk, MSHR * mshr, CacheBlk::State new_state,
242                        PacketList & writebacks, PacketPtr pkt);
243
244    /**
245     * Populates a cache block and handles all outstanding requests for the
246     * satisfied fill request. This version takes two memory requests. One
247     * contains the fill data, the other is an optional target to satisfy.
248     * Used for Cache::probe.
249     * @param blk The cache block if it already exists.
250     * @param pkt The memory request with the fill data.
251     * @param new_state The state of the new cache block.
252     * @param writebacks List for any writebacks that need to be performed.
253     * @param target The memory request to perform after the fill.
254     * @return Pointer to the new cache block.
255     */
256    BlkType* handleFill(BlkType *blk, PacketPtr &pkt,
257                        CacheBlk::State new_state,
258                        PacketList & writebacks, PacketPtr target = NULL);
259
260    /**
261     * Sets the blk to the new state and handles the given request.
262     * @param blk The cache block being snooped.
263     * @param new_state The new coherence state for the block.
264     * @param pkt The request to satisfy
265     */
266    void handleSnoop(BlkType *blk, CacheBlk::State new_state,
267                     PacketPtr &pkt);
268
269    /**
270     * Sets the blk to the new state.
271     * @param blk The cache block being snooped.
272     * @param new_state The new coherence state for the block.
273     */
274    void handleSnoop(BlkType *blk, CacheBlk::State new_state);
275
276    /**
277     * Create a writeback request for the given block.
278     * @param blk The block to writeback.
279     * @return The writeback request for the block.
280     */
281    PacketPtr writebackBlk(BlkType *blk);
282
283    BlkType* findBlock(Addr addr)
284    {
285        return tags->findBlock(addr);
286    }
287
288    BlkType* findBlock(PacketPtr &pkt)
289    {
290        return tags->findBlock(pkt->getAddr());
291    }
292
293    void invalidateBlk(CacheBlk *blk)
294    {
295        tags->invalidateBlk(tags->regenerateBlkAddr(blk->tag, blk->set));
296    }
297
298  public:
299
300    class Params
301    {
302      public:
303        TagStore *tags;
304        MissBuffer *missQueue;
305        Coherence *coherence;
306        BaseCache::Params baseParams;
307        Prefetcher<TagStore> *prefetcher;
308        bool prefetchAccess;
309        int hitLatency;
310        CompressionAlgorithm *compressionAlg;
311        const int16_t blkSize;
312        const bool doFastWrites;
313        const bool prefetchMiss;
314        const bool storeCompressed;
315        const bool compressOnWriteback;
316        const int16_t compLatency;
317        const bool adaptiveCompression;
318        const bool writebackCompressed;
319
320        Params(TagStore *_tags, MissBuffer *mq, Coherence *coh,
321               BaseCache::Params params,
322               Prefetcher<TagStore> *_prefetcher,
323               bool prefetch_access, int hit_latency,
324               bool do_fast_writes,
325               bool store_compressed, bool adaptive_compression,
326               bool writeback_compressed,
327               CompressionAlgorithm *_compressionAlg, int comp_latency,
328               bool prefetch_miss)
329            : tags(_tags), missQueue(mq), coherence(coh),
330              baseParams(params),
331              prefetcher(_prefetcher), prefetchAccess(prefetch_access),
332              hitLatency(hit_latency),
333              compressionAlg(_compressionAlg),
334              blkSize(_tags->getBlockSize()),
335              doFastWrites(do_fast_writes),
336              prefetchMiss(prefetch_miss),
337              storeCompressed(store_compressed),
338              compressOnWriteback(!store_compressed && writeback_compressed),
339              compLatency(comp_latency),
340              adaptiveCompression(adaptive_compression),
341              writebackCompressed(writeback_compressed)
342        {
343        }
344    };
345
346    /** Instantiates a basic cache object. */
347    Cache(const std::string &_name, Params &params);
348
349    virtual Port *getPort(const std::string &if_name, int idx = -1);
350
351    virtual void recvStatusChange(Port::Status status, bool isCpuSide);
352
353    void regStats();
354
355    /**
356     * Performs the access specified by the request.
357     * @param pkt The request to perform.
358     * @return The result of the access.
359     */
360    bool access(PacketPtr &pkt);
361
362    /**
363     * Selects a request to send on the bus.
364     * @return The memory request to service.
365     */
366    virtual PacketPtr getPacket();
367
368    /**
369     * Was the request was sent successfully?
370     * @param pkt The request.
371     * @param success True if the request was sent successfully.
372     */
373    virtual void sendResult(PacketPtr &pkt, MSHR* mshr, bool success);
374
375    /**
376     * Was the CSHR request was sent successfully?
377     * @param pkt The request.
378     * @param success True if the request was sent successfully.
379     */
380    virtual void sendCoherenceResult(PacketPtr &pkt, MSHR* cshr, bool success);
381
382    /**
383     * Handles a response (cache line fill/write ack) from the bus.
384     * @param pkt The request being responded to.
385     */
386    void handleResponse(PacketPtr &pkt);
387
388    /**
389     * Selects a coherence message to forward to lower levels of the hierarchy.
390     * @return The coherence message to forward.
391     */
392    virtual PacketPtr getCoherencePacket();
393
394    /**
395     * Snoops bus transactions to maintain coherence.
396     * @param pkt The current bus transaction.
397     */
398    void snoop(PacketPtr &pkt);
399
400    void snoopResponse(PacketPtr &pkt);
401
402    /**
403     * Invalidates the block containing address if found.
404     * @param addr The address to look for.
405     * @param asid The address space ID of the address.
406     * @todo Is this function necessary?
407     */
408    void invalidateBlk(Addr addr);
409
410    /**
411     * Squash all requests associated with specified thread.
412     * intended for use by I-cache.
413     * @param threadNum The thread to squash.
414     */
415    void squash(int threadNum)
416    {
417        missQueue->squash(threadNum);
418    }
419
420    /**
421     * Return the number of outstanding misses in a Cache.
422     * Default returns 0.
423     *
424     * @retval unsigned The number of missing still outstanding.
425     */
426    unsigned outstandingMisses() const
427    {
428        return missQueue->getMisses();
429    }
430
431    /**
432     * Perform the access specified in the request and return the estimated
433     * time of completion. This function can either update the hierarchy state
434     * or just perform the access wherever the data is found depending on the
435     * state of the update flag.
436     * @param pkt The memory request to satisfy
437     * @param update If true, update the hierarchy, otherwise just perform the
438     * request.
439     * @return The estimated completion time.
440     */
441    Tick probe(PacketPtr &pkt, bool update, CachePort * otherSidePort);
442
443    /**
444     * Snoop for the provided request in the cache and return the estimated
445     * time of completion.
446     * @todo Can a snoop probe not change state?
447     * @param pkt The memory request to satisfy
448     * @param update If true, update the hierarchy, otherwise just perform the
449     * request.
450     * @return The estimated completion time.
451     */
452    Tick snoopProbe(PacketPtr &pkt);
453};
454
455#endif // __CACHE_HH__
456