cache.hh revision 11199:929fd978ab4e
1/*
2 * Copyright (c) 2012-2015 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) 2002-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 *          Dave Greene
42 *          Steve Reinhardt
43 *          Ron Dreslinski
44 *          Andreas Hansson
45 */
46
47/**
48 * @file
49 * Describes a cache based on template policies.
50 */
51
52#ifndef __MEM_CACHE_CACHE_HH__
53#define __MEM_CACHE_CACHE_HH__
54
55#include "base/misc.hh" // fatal, panic, and warn
56#include "enums/Clusivity.hh"
57#include "mem/cache/base.hh"
58#include "mem/cache/blk.hh"
59#include "mem/cache/mshr.hh"
60#include "mem/cache/tags/base.hh"
61#include "params/Cache.hh"
62#include "sim/eventq.hh"
63
64//Forward decleration
65class BasePrefetcher;
66
67/**
68 * A template-policy based cache. The behavior of the cache can be altered by
69 * supplying different template policies. TagStore handles all tag and data
70 * storage @sa TagStore, \ref gem5MemorySystem "gem5 Memory System"
71 */
72class Cache : public BaseCache
73{
74  public:
75
76    /** A typedef for a list of CacheBlk pointers. */
77    typedef std::list<CacheBlk*> BlkList;
78
79  protected:
80
81    /**
82     * The CPU-side port extends the base cache slave port with access
83     * functions for functional, atomic and timing requests.
84     */
85    class CpuSidePort : public CacheSlavePort
86    {
87      private:
88
89        // a pointer to our specific cache implementation
90        Cache *cache;
91
92      protected:
93
94        virtual bool recvTimingSnoopResp(PacketPtr pkt);
95
96        virtual bool recvTimingReq(PacketPtr pkt);
97
98        virtual Tick recvAtomic(PacketPtr pkt);
99
100        virtual void recvFunctional(PacketPtr pkt);
101
102        virtual AddrRangeList getAddrRanges() const;
103
104      public:
105
106        CpuSidePort(const std::string &_name, Cache *_cache,
107                    const std::string &_label);
108
109    };
110
111    /**
112     * Override the default behaviour of sendDeferredPacket to enable
113     * the memory-side cache port to also send requests based on the
114     * current MSHR status. This queue has a pointer to our specific
115     * cache implementation and is used by the MemSidePort.
116     */
117    class CacheReqPacketQueue : public ReqPacketQueue
118    {
119
120      protected:
121
122        Cache &cache;
123        SnoopRespPacketQueue &snoopRespQueue;
124
125      public:
126
127        CacheReqPacketQueue(Cache &cache, MasterPort &port,
128                            SnoopRespPacketQueue &snoop_resp_queue,
129                            const std::string &label) :
130            ReqPacketQueue(cache, port, label), cache(cache),
131            snoopRespQueue(snoop_resp_queue) { }
132
133        /**
134         * Override the normal sendDeferredPacket and do not only
135         * consider the transmit list (used for responses), but also
136         * requests.
137         */
138        virtual void sendDeferredPacket();
139
140    };
141
142    /**
143     * The memory-side port extends the base cache master port with
144     * access functions for functional, atomic and timing snoops.
145     */
146    class MemSidePort : public CacheMasterPort
147    {
148      private:
149
150        /** The cache-specific queue. */
151        CacheReqPacketQueue _reqQueue;
152
153        SnoopRespPacketQueue _snoopRespQueue;
154
155        // a pointer to our specific cache implementation
156        Cache *cache;
157
158      protected:
159
160        virtual void recvTimingSnoopReq(PacketPtr pkt);
161
162        virtual bool recvTimingResp(PacketPtr pkt);
163
164        virtual Tick recvAtomicSnoop(PacketPtr pkt);
165
166        virtual void recvFunctionalSnoop(PacketPtr pkt);
167
168      public:
169
170        MemSidePort(const std::string &_name, Cache *_cache,
171                    const std::string &_label);
172    };
173
174    /** Tag and data Storage */
175    BaseTags *tags;
176
177    /** Prefetcher */
178    BasePrefetcher *prefetcher;
179
180    /** Temporary cache block for occasional transitory use */
181    CacheBlk *tempBlock;
182
183    /**
184     * This cache should allocate a block on a line-sized write miss.
185     */
186    const bool doFastWrites;
187
188    /**
189     * Turn line-sized writes into WriteInvalidate transactions.
190     */
191    void promoteWholeLineWrites(PacketPtr pkt);
192
193    /**
194     * Notify the prefetcher on every access, not just misses.
195     */
196    const bool prefetchOnAccess;
197
198     /**
199     * Clusivity with respect to the upstream cache, determining if we
200     * fill into both this cache and the cache above on a miss. Note
201     * that we currently do not support strict clusivity policies.
202     */
203    const Enums::Clusivity clusivity;
204
205     /**
206     * Determine if clean lines should be written back or not. In
207     * cases where a downstream cache is mostly inclusive we likely
208     * want it to act as a victim cache also for lines that have not
209     * been modified. Hence, we cannot simply drop the line (or send a
210     * clean evict), but rather need to send the actual data.
211     */
212    const bool writebackClean;
213
214    /**
215     * Upstream caches need this packet until true is returned, so
216     * hold it for deletion until a subsequent call
217     */
218    std::unique_ptr<Packet> pendingDelete;
219
220    /**
221     * Writebacks from the tempBlock, resulting on the response path
222     * in atomic mode, must happen after the call to recvAtomic has
223     * finished (for the right ordering of the packets). We therefore
224     * need to hold on to the packets, and have a method and an event
225     * to send them.
226     */
227    PacketPtr tempBlockWriteback;
228
229    /**
230     * Send the outstanding tempBlock writeback. To be called after
231     * recvAtomic finishes in cases where the block we filled is in
232     * fact the tempBlock, and now needs to be written back.
233     */
234    void writebackTempBlockAtomic() {
235        assert(tempBlockWriteback != nullptr);
236        PacketList writebacks{tempBlockWriteback};
237        doWritebacksAtomic(writebacks);
238        tempBlockWriteback = nullptr;
239    }
240
241    /**
242     * An event to writeback the tempBlock after recvAtomic
243     * finishes. To avoid other calls to recvAtomic getting in
244     * between, we create this event with a higher priority.
245     */
246    EventWrapper<Cache, &Cache::writebackTempBlockAtomic> \
247        writebackTempBlockAtomicEvent;
248
249    /**
250     * Does all the processing necessary to perform the provided request.
251     * @param pkt The memory request to perform.
252     * @param blk The cache block to be updated.
253     * @param lat The latency of the access.
254     * @param writebacks List for any writebacks that need to be performed.
255     * @return Boolean indicating whether the request was satisfied.
256     */
257    bool access(PacketPtr pkt, CacheBlk *&blk,
258                Cycles &lat, PacketList &writebacks);
259
260    /**
261     *Handle doing the Compare and Swap function for SPARC.
262     */
263    void cmpAndSwap(CacheBlk *blk, PacketPtr pkt);
264
265    /**
266     * Find a block frame for new block at address addr targeting the
267     * given security space, assuming that the block is not currently
268     * in the cache.  Append writebacks if any to provided packet
269     * list.  Return free block frame.  May return NULL if there are
270     * no replaceable blocks at the moment.
271     */
272    CacheBlk *allocateBlock(Addr addr, bool is_secure, PacketList &writebacks);
273
274    /**
275     * Invalidate a cache block.
276     *
277     * @param blk Block to invalidate
278     */
279    void invalidateBlock(CacheBlk *blk);
280
281    /**
282     * Populates a cache block and handles all outstanding requests for the
283     * satisfied fill request. This version takes two memory requests. One
284     * contains the fill data, the other is an optional target to satisfy.
285     * @param pkt The memory request with the fill data.
286     * @param blk The cache block if it already exists.
287     * @param writebacks List for any writebacks that need to be performed.
288     * @param allocate Whether to allocate a block or use the temp block
289     * @return Pointer to the new cache block.
290     */
291    CacheBlk *handleFill(PacketPtr pkt, CacheBlk *blk,
292                         PacketList &writebacks, bool allocate);
293
294    /**
295     * Determine whether we should allocate on a fill or not. If this
296     * cache is mostly inclusive with regards to the upstream cache(s)
297     * we always allocate (for any non-forwarded and cacheable
298     * requests). In the case of a mostly exclusive cache, we allocate
299     * on fill if the packet did not come from a cache, thus if we:
300     * are dealing with a whole-line write (the latter behaves much
301     * like a writeback), the original target packet came from a
302     * non-caching source, or if we are performing a prefetch or LLSC.
303     *
304     * @param cmd Command of the incoming requesting packet
305     * @return Whether we should allocate on the fill
306     */
307    inline bool allocOnFill(MemCmd cmd) const
308    {
309        return clusivity == Enums::mostly_incl ||
310            cmd == MemCmd::WriteLineReq ||
311            cmd == MemCmd::ReadReq ||
312            cmd == MemCmd::WriteReq ||
313            cmd.isPrefetch() ||
314            cmd.isLLSC();
315    }
316
317    /**
318     * Performs the access specified by the request.
319     * @param pkt The request to perform.
320     * @return The result of the access.
321     */
322    bool recvTimingReq(PacketPtr pkt);
323
324    /**
325     * Insert writebacks into the write buffer
326     */
327    void doWritebacks(PacketList& writebacks, Tick forward_time);
328
329    /**
330     * Send writebacks down the memory hierarchy in atomic mode
331     */
332    void doWritebacksAtomic(PacketList& writebacks);
333
334    /**
335     * Handles a response (cache line fill/write ack) from the bus.
336     * @param pkt The response packet
337     */
338    void recvTimingResp(PacketPtr pkt);
339
340    /**
341     * Snoops bus transactions to maintain coherence.
342     * @param pkt The current bus transaction.
343     */
344    void recvTimingSnoopReq(PacketPtr pkt);
345
346    /**
347     * Handle a snoop response.
348     * @param pkt Snoop response packet
349     */
350    void recvTimingSnoopResp(PacketPtr pkt);
351
352    /**
353     * Performs the access specified by the request.
354     * @param pkt The request to perform.
355     * @return The number of ticks required for the access.
356     */
357    Tick recvAtomic(PacketPtr pkt);
358
359    /**
360     * Snoop for the provided request in the cache and return the estimated
361     * time taken.
362     * @param pkt The memory request to snoop
363     * @return The number of ticks required for the snoop.
364     */
365    Tick recvAtomicSnoop(PacketPtr pkt);
366
367    /**
368     * Performs the access specified by the request.
369     * @param pkt The request to perform.
370     * @param fromCpuSide from the CPU side port or the memory side port
371     */
372    void functionalAccess(PacketPtr pkt, bool fromCpuSide);
373
374    void satisfyCpuSideRequest(PacketPtr pkt, CacheBlk *blk,
375                               bool deferred_response = false,
376                               bool pending_downgrade = false);
377    bool satisfyMSHR(MSHR *mshr, PacketPtr pkt, CacheBlk *blk);
378
379    void doTimingSupplyResponse(PacketPtr req_pkt, const uint8_t *blk_data,
380                                bool already_copied, bool pending_inval);
381
382    /**
383     * Perform an upward snoop if needed, and update the block state
384     * (possibly invalidating the block). Also create a response if required.
385     *
386     * @param pkt Snoop packet
387     * @param blk Cache block being snooped
388     * @param is_timing Timing or atomic for the response
389     * @param is_deferred Is this a deferred snoop or not?
390     * @param pending_inval Do we have a pending invalidation?
391     *
392     * @return The snoop delay incurred by the upwards snoop
393     */
394    uint32_t handleSnoop(PacketPtr pkt, CacheBlk *blk,
395                         bool is_timing, bool is_deferred, bool pending_inval);
396
397    /**
398     * Create a writeback request for the given block.
399     * @param blk The block to writeback.
400     * @return The writeback request for the block.
401     */
402    PacketPtr writebackBlk(CacheBlk *blk);
403
404    /**
405     * Create a CleanEvict request for the given block.
406     * @param blk The block to evict.
407     * @return The CleanEvict request for the block.
408     */
409    PacketPtr cleanEvictBlk(CacheBlk *blk);
410
411
412    void memWriteback() override;
413    void memInvalidate() override;
414    bool isDirty() const override;
415
416    /**
417     * Cache block visitor that writes back dirty cache blocks using
418     * functional writes.
419     *
420     * \return Always returns true.
421     */
422    bool writebackVisitor(CacheBlk &blk);
423    /**
424     * Cache block visitor that invalidates all blocks in the cache.
425     *
426     * @warn Dirty cache lines will not be written back to memory.
427     *
428     * \return Always returns true.
429     */
430    bool invalidateVisitor(CacheBlk &blk);
431
432    /**
433     * Generate an appropriate downstream bus request packet for the
434     * given parameters.
435     * @param cpu_pkt  The upstream request that needs to be satisfied.
436     * @param blk The block currently in the cache corresponding to
437     * cpu_pkt (NULL if none).
438     * @param needsExclusive  Indicates that an exclusive copy is required
439     * even if the request in cpu_pkt doesn't indicate that.
440     * @return A new Packet containing the request, or NULL if the
441     * current request in cpu_pkt should just be forwarded on.
442     */
443    PacketPtr getBusPacket(PacketPtr cpu_pkt, CacheBlk *blk,
444                           bool needsExclusive) const;
445
446    /**
447     * Return the next MSHR to service, either a pending miss from the
448     * mshrQueue, a buffered write from the write buffer, or something
449     * from the prefetcher.  This function is responsible for
450     * prioritizing among those sources on the fly.
451     */
452    MSHR *getNextMSHR();
453
454    /**
455     * Send up a snoop request and find cached copies. If cached copies are
456     * found, set the BLOCK_CACHED flag in pkt.
457     */
458    bool isCachedAbove(PacketPtr pkt, bool is_timing = true) const;
459
460    /**
461     * Selects an outstanding request to service.  Called when the
462     * cache gets granted the downstream bus in timing mode.
463     * @return The request to service, NULL if none found.
464     */
465    PacketPtr getTimingPacket();
466
467    /**
468     * Marks a request as in service (sent on the bus). This can have
469     * side effect since storage for no response commands is
470     * deallocated once they are successfully sent. Also remember if
471     * we are expecting a dirty response from another cache,
472     * effectively making this MSHR the ordering point.
473     */
474    void markInService(MSHR *mshr, bool pending_dirty_resp);
475
476    /**
477     * Return whether there are any outstanding misses.
478     */
479    bool outstandingMisses() const
480    {
481        return mshrQueue.allocated != 0;
482    }
483
484    CacheBlk *findBlock(Addr addr, bool is_secure) const {
485        return tags->findBlock(addr, is_secure);
486    }
487
488    bool inCache(Addr addr, bool is_secure) const override {
489        return (tags->findBlock(addr, is_secure) != 0);
490    }
491
492    bool inMissQueue(Addr addr, bool is_secure) const override {
493        return (mshrQueue.findMatch(addr, is_secure) != 0);
494    }
495
496    /**
497     * Find next request ready time from among possible sources.
498     */
499    Tick nextMSHRReadyTime() const;
500
501  public:
502    /** Instantiates a basic cache object. */
503    Cache(const CacheParams *p);
504
505    /** Non-default destructor is needed to deallocate memory. */
506    virtual ~Cache();
507
508    void regStats() override;
509
510    /** serialize the state of the caches
511     * We currently don't support checkpointing cache state, so this panics.
512     */
513    void serialize(CheckpointOut &cp) const override;
514    void unserialize(CheckpointIn &cp) override;
515};
516
517/**
518 * Wrap a method and present it as a cache block visitor.
519 *
520 * For example the forEachBlk method in the tag arrays expects a
521 * callable object/function as their parameter. This class wraps a
522 * method in an object and presents  callable object that adheres to
523 * the cache block visitor protocol.
524 */
525class CacheBlkVisitorWrapper : public CacheBlkVisitor
526{
527  public:
528    typedef bool (Cache::*VisitorPtr)(CacheBlk &blk);
529
530    CacheBlkVisitorWrapper(Cache &_cache, VisitorPtr _visitor)
531        : cache(_cache), visitor(_visitor) {}
532
533    bool operator()(CacheBlk &blk) override {
534        return (cache.*visitor)(blk);
535    }
536
537  private:
538    Cache &cache;
539    VisitorPtr visitor;
540};
541
542/**
543 * Cache block visitor that determines if there are dirty blocks in a
544 * cache.
545 *
546 * Use with the forEachBlk method in the tag array to determine if the
547 * array contains dirty blocks.
548 */
549class CacheBlkIsDirtyVisitor : public CacheBlkVisitor
550{
551  public:
552    CacheBlkIsDirtyVisitor()
553        : _isDirty(false) {}
554
555    bool operator()(CacheBlk &blk) override {
556        if (blk.isDirty()) {
557            _isDirty = true;
558            return false;
559        } else {
560            return true;
561        }
562    }
563
564    /**
565     * Does the array contain a dirty line?
566     *
567     * \return true if yes, false otherwise.
568     */
569    bool isDirty() const { return _isDirty; };
570
571  private:
572    bool _isDirty;
573};
574
575#endif // __MEM_CACHE_CACHE_HH__
576