mshr.hh revision 11284
112940Sgabeblack@google.com/*
212940Sgabeblack@google.com * Copyright (c) 2012-2013, 2015 ARM Limited
312940Sgabeblack@google.com * All rights reserved.
412940Sgabeblack@google.com *
512940Sgabeblack@google.com * The license below extends only to copyright in the software and shall
612940Sgabeblack@google.com * not be construed as granting a license to any other intellectual
712940Sgabeblack@google.com * property including but not limited to intellectual property relating
812940Sgabeblack@google.com * to a hardware implementation of the functionality of the software
912940Sgabeblack@google.com * licensed hereunder.  You may use the software subject to the license
1012940Sgabeblack@google.com * terms below provided that you ensure that this notice is replicated
1112940Sgabeblack@google.com * unmodified and in its entirety in all distributions of the software,
1212940Sgabeblack@google.com * modified or unmodified, in source code or in binary form.
1312940Sgabeblack@google.com *
1412940Sgabeblack@google.com * Copyright (c) 2002-2005 The Regents of The University of Michigan
1512940Sgabeblack@google.com * All rights reserved.
1612940Sgabeblack@google.com *
1712940Sgabeblack@google.com * Redistribution and use in source and binary forms, with or without
1812940Sgabeblack@google.com * modification, are permitted provided that the following conditions are
1912940Sgabeblack@google.com * met: redistributions of source code must retain the above copyright
2012940Sgabeblack@google.com * notice, this list of conditions and the following disclaimer;
2112940Sgabeblack@google.com * redistributions in binary form must reproduce the above copyright
2212940Sgabeblack@google.com * notice, this list of conditions and the following disclaimer in the
2312940Sgabeblack@google.com * documentation and/or other materials provided with the distribution;
2412940Sgabeblack@google.com * neither the name of the copyright holders nor the names of its
2512940Sgabeblack@google.com * contributors may be used to endorse or promote products derived from
2612940Sgabeblack@google.com * this software without specific prior written permission.
2712940Sgabeblack@google.com *
2812940Sgabeblack@google.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
2912940Sgabeblack@google.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
3012940Sgabeblack@google.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
3113192Sgabeblack@google.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
3213192Sgabeblack@google.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
3313192Sgabeblack@google.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
3412940Sgabeblack@google.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
3512940Sgabeblack@google.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
3612940Sgabeblack@google.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
3712940Sgabeblack@google.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
3812940Sgabeblack@google.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3913192Sgabeblack@google.com *
4012940Sgabeblack@google.com * Authors: Erik Hallnor
4112940Sgabeblack@google.com */
4213192Sgabeblack@google.com
4313192Sgabeblack@google.com/**
4413192Sgabeblack@google.com * @file
4513192Sgabeblack@google.com * Miss Status and Handling Register (MSHR) declaration.
4613192Sgabeblack@google.com */
4713192Sgabeblack@google.com
4813192Sgabeblack@google.com#ifndef __MEM_CACHE_MSHR_HH__
4913192Sgabeblack@google.com#define __MEM_CACHE_MSHR_HH__
5013192Sgabeblack@google.com
5112940Sgabeblack@google.com#include <list>
5212940Sgabeblack@google.com
5312940Sgabeblack@google.com#include "base/printable.hh"
5412940Sgabeblack@google.com#include "mem/packet.hh"
5513192Sgabeblack@google.com
5613192Sgabeblack@google.comclass CacheBlk;
5713192Sgabeblack@google.comclass MSHRQueue;
5813192Sgabeblack@google.com
5912940Sgabeblack@google.com/**
6012940Sgabeblack@google.com * Miss Status and handling Register. This class keeps all the information
6112946Sgabeblack@google.com * needed to handle a cache miss including a list of target requests.
6212946Sgabeblack@google.com * @sa  \ref gem5MemorySystem "gem5 Memory System"
6312946Sgabeblack@google.com */
6413192Sgabeblack@google.comclass MSHR : public Packet::SenderState, public Printable
6513192Sgabeblack@google.com{
6613192Sgabeblack@google.com
6713192Sgabeblack@google.com    /**
6813192Sgabeblack@google.com     * Consider the MSHRQueue a friend to avoid making everything public
6912946Sgabeblack@google.com     */
7012946Sgabeblack@google.com    friend class MSHRQueue;
7112946Sgabeblack@google.com
7212946Sgabeblack@google.com  private:
7312946Sgabeblack@google.com
7413192Sgabeblack@google.com    /** Cycle when ready to issue */
7513192Sgabeblack@google.com    Tick readyTime;
7613192Sgabeblack@google.com
7713192Sgabeblack@google.com    /** True if the request is uncacheable */
7813192Sgabeblack@google.com    bool _isUncacheable;
7912946Sgabeblack@google.com
8012946Sgabeblack@google.com    /** Flag set by downstream caches */
8112940Sgabeblack@google.com    bool downstreamPending;
8212940Sgabeblack@google.com
8312940Sgabeblack@google.com    /**
8413192Sgabeblack@google.com     * Here we use one flag to track both if:
8512940Sgabeblack@google.com     *
8612940Sgabeblack@google.com     * 1. We are going to become owner or not, i.e., we will get the
8712940Sgabeblack@google.com     * block in an ownership state (Owned or Modified) with BlkDirty
88     * set. This determines whether or not we are going to become the
89     * responder and ordering point for future requests that we snoop.
90     *
91     * 2. We know that we are going to get a writable block, i.e. we
92     * will get the block in writable state (Exclusive or Modified
93     * state) with BlkWritable set. That determines whether additional
94     * targets with needsWritable set will be able to be satisfied, or
95     * if not should be put on the deferred list to possibly wait for
96     * another request that does give us writable access.
97     *
98     * Condition 2 is actually just a shortcut that saves us from
99     * possibly building a deferred target list and calling
100     * promoteWritable() every time we get a writable block. Condition
101     * 1, tracking ownership, is what is important. However, we never
102     * receive ownership without marking the block dirty, and
103     * consequently use pendingModified to track both ownership and
104     * writability rather than having separate pendingDirty and
105     * pendingWritable flags.
106     */
107    bool pendingModified;
108
109    /** Did we snoop an invalidate while waiting for data? */
110    bool postInvalidate;
111
112    /** Did we snoop a read while waiting for data? */
113    bool postDowngrade;
114
115  public:
116
117    class Target {
118      public:
119
120        enum Source {
121            FromCPU,
122            FromSnoop,
123            FromPrefetcher
124        };
125
126        const Tick recvTime;  //!< Time when request was received (for stats)
127        const Tick readyTime; //!< Time when request is ready to be serviced
128        const Counter order;  //!< Global order (for memory consistency mgmt)
129        const PacketPtr pkt;  //!< Pending request packet.
130        const Source source;  //!< Request from cpu, memory, or prefetcher?
131        const bool markedPending; //!< Did we mark upstream MSHR
132                                  //!< as downstreamPending?
133
134        Target(PacketPtr _pkt, Tick _readyTime, Counter _order,
135               Source _source, bool _markedPending)
136            : recvTime(curTick()), readyTime(_readyTime), order(_order),
137              pkt(_pkt), source(_source), markedPending(_markedPending)
138        {}
139    };
140
141    class TargetList : public std::list<Target> {
142
143      public:
144        bool needsWritable;
145        bool hasUpgrade;
146
147        TargetList();
148        void resetFlags() { needsWritable = hasUpgrade = false; }
149        bool isReset() const { return !needsWritable && !hasUpgrade; }
150        void add(PacketPtr pkt, Tick readyTime, Counter order,
151                 Target::Source source, bool markPending);
152        void replaceUpgrades();
153        void clearDownstreamPending();
154        bool checkFunctional(PacketPtr pkt);
155        void print(std::ostream &os, int verbosity,
156                   const std::string &prefix) const;
157    };
158
159    /** A list of MSHRs. */
160    typedef std::list<MSHR *> List;
161    /** MSHR list iterator. */
162    typedef List::iterator Iterator;
163    /** MSHR list const_iterator. */
164    typedef List::const_iterator ConstIterator;
165
166    /** Pointer to queue containing this MSHR. */
167    MSHRQueue *queue;
168
169    /** Order number assigned by the miss queue. */
170    Counter order;
171
172    /** Block aligned address of the MSHR. */
173    Addr blkAddr;
174
175    /** Block size of the cache. */
176    unsigned blkSize;
177
178    /** True if the request targets the secure memory space. */
179    bool isSecure;
180
181    /** True if the request has been sent to the bus. */
182    bool inService;
183
184    /** True if the request is just a simple forward from an upper level */
185    bool isForward;
186
187    /** Keep track of whether we should allocate on fill or not */
188    bool allocOnFill;
189
190    /** The pending* and post* flags are only valid if inService is
191     *  true.  Using the accessor functions lets us detect if these
192     *  flags are accessed improperly.
193     */
194
195    /** True if we need to get a writable copy of the block. */
196    bool needsWritable() const { return targets.needsWritable; }
197
198    bool isPendingModified() const {
199        assert(inService); return pendingModified;
200    }
201
202    bool hasPostInvalidate() const {
203        assert(inService); return postInvalidate;
204    }
205
206    bool hasPostDowngrade() const {
207        assert(inService); return postDowngrade;
208    }
209
210  private:
211
212    /** Data buffer (if needed).  Currently used only for pending
213     * upgrade handling. */
214    uint8_t *data;
215
216    /**
217     * Pointer to this MSHR on the ready list.
218     * @sa MissQueue, MSHRQueue::readyList
219     */
220    Iterator readyIter;
221
222    /**
223     * Pointer to this MSHR on the allocated list.
224     * @sa MissQueue, MSHRQueue::allocatedList
225     */
226    Iterator allocIter;
227
228    /** List of all requests that match the address */
229    TargetList targets;
230
231    TargetList deferredTargets;
232
233  public:
234
235    bool isUncacheable() const { return _isUncacheable; }
236
237    /**
238     * Allocate a miss to this MSHR.
239     * @param blk_addr The address of the block.
240     * @param blk_size The number of bytes to request.
241     * @param pkt The original miss.
242     * @param when_ready When should the MSHR be ready to act upon.
243     * @param _order The logical order of this MSHR
244     * @param alloc_on_fill Should the cache allocate a block on fill
245     */
246    void allocate(Addr blk_addr, unsigned blk_size, PacketPtr pkt,
247                  Tick when_ready, Counter _order, bool alloc_on_fill);
248
249    bool markInService(bool pending_modified_resp);
250
251    void clearDownstreamPending();
252
253    /**
254     * Mark this MSHR as free.
255     */
256    void deallocate();
257
258    /**
259     * Add a request to the list of targets.
260     * @param target The target.
261     */
262    void allocateTarget(PacketPtr target, Tick when, Counter order,
263                        bool alloc_on_fill);
264    bool handleSnoop(PacketPtr target, Counter order);
265
266    /** A simple constructor. */
267    MSHR();
268
269    /**
270     * Returns the current number of allocated targets.
271     * @return The current number of allocated targets.
272     */
273    int getNumTargets() const
274    { return targets.size() + deferredTargets.size(); }
275
276    /**
277     * Returns true if there are targets left.
278     * @return true if there are targets
279     */
280    bool hasTargets() const { return !targets.empty(); }
281
282    /**
283     * Returns a reference to the first target.
284     * @return A pointer to the first target.
285     */
286    Target *getTarget()
287    {
288        assert(hasTargets());
289        return &targets.front();
290    }
291
292    /**
293     * Pop first target.
294     */
295    void popTarget()
296    {
297        targets.pop_front();
298    }
299
300    bool isForwardNoResponse() const
301    {
302        if (getNumTargets() != 1)
303            return false;
304        const Target *tgt = &targets.front();
305        return tgt->source == Target::FromCPU && !tgt->pkt->needsResponse();
306    }
307
308    bool promoteDeferredTargets();
309
310    void promoteWritable();
311
312    bool checkFunctional(PacketPtr pkt);
313
314    /**
315     * Prints the contents of this MSHR for debugging.
316     */
317    void print(std::ostream &os,
318               int verbosity = 0,
319               const std::string &prefix = "") const;
320    /**
321     * A no-args wrapper of print(std::ostream...)  meant to be
322     * invoked from DPRINTFs avoiding string overheads in fast mode
323     *
324     * @return string with mshr fields + [deferred]targets
325     */
326    std::string print() const;
327};
328
329#endif // __MEM_CACHE_MSHR_HH__
330