lsq.hh revision 12127
15449Sgblack@eecs.umich.edu/*
24519Sgblack@eecs.umich.edu * Copyright (c) 2013-2014 ARM Limited
34519Sgblack@eecs.umich.edu * All rights reserved
47087Snate@binkert.org *
57087Snate@binkert.org * The license below extends only to copyright in the software and shall
67087Snate@binkert.org * not be construed as granting a license to any other intellectual
77087Snate@binkert.org * property including but not limited to intellectual property relating
87087Snate@binkert.org * to a hardware implementation of the functionality of the software
97087Snate@binkert.org * licensed hereunder.  You may use the software subject to the license
107087Snate@binkert.org * terms below provided that you ensure that this notice is replicated
117087Snate@binkert.org * unmodified and in its entirety in all distributions of the software,
124519Sgblack@eecs.umich.edu * modified or unmodified, in source code or in binary form.
137087Snate@binkert.org *
147087Snate@binkert.org * Redistribution and use in source and binary forms, with or without
157087Snate@binkert.org * modification, are permitted provided that the following conditions are
167087Snate@binkert.org * met: redistributions of source code must retain the above copyright
177087Snate@binkert.org * notice, this list of conditions and the following disclaimer;
187087Snate@binkert.org * redistributions in binary form must reproduce the above copyright
197087Snate@binkert.org * notice, this list of conditions and the following disclaimer in the
207087Snate@binkert.org * documentation and/or other materials provided with the distribution;
214519Sgblack@eecs.umich.edu * neither the name of the copyright holders nor the names of its
227087Snate@binkert.org * contributors may be used to endorse or promote products derived from
234519Sgblack@eecs.umich.edu * this software without specific prior written permission.
244519Sgblack@eecs.umich.edu *
254519Sgblack@eecs.umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
264519Sgblack@eecs.umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
274519Sgblack@eecs.umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
284519Sgblack@eecs.umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
294519Sgblack@eecs.umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
304519Sgblack@eecs.umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
314519Sgblack@eecs.umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
324519Sgblack@eecs.umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
334519Sgblack@eecs.umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
344519Sgblack@eecs.umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
354519Sgblack@eecs.umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
364519Sgblack@eecs.umich.edu *
374519Sgblack@eecs.umich.edu * Authors: Andrew Bardsley
384519Sgblack@eecs.umich.edu */
394519Sgblack@eecs.umich.edu
404519Sgblack@eecs.umich.edu/**
414519Sgblack@eecs.umich.edu * @file
424519Sgblack@eecs.umich.edu *
434519Sgblack@eecs.umich.edu *  A load/store queue that allows outstanding reads and writes.
444590Sgblack@eecs.umich.edu *
455163Sgblack@eecs.umich.edu */
464590Sgblack@eecs.umich.edu
474590Sgblack@eecs.umich.edu#ifndef __CPU_MINOR_NEW_LSQ_HH__
484590Sgblack@eecs.umich.edu#define __CPU_MINOR_NEW_LSQ_HH__
495163Sgblack@eecs.umich.edu
504590Sgblack@eecs.umich.edu#include "cpu/minor/buffers.hh"
514590Sgblack@eecs.umich.edu#include "cpu/minor/cpu.hh"
525163Sgblack@eecs.umich.edu#include "cpu/minor/pipe_data.hh"
537620Sgblack@eecs.umich.edu#include "cpu/minor/trace.hh"
544590Sgblack@eecs.umich.edu
554696Sgblack@eecs.umich.edunamespace Minor
564696Sgblack@eecs.umich.edu{
574590Sgblack@eecs.umich.edu
585172Sgblack@eecs.umich.edu/* Forward declaration */
595172Sgblack@eecs.umich.educlass Execute;
605172Sgblack@eecs.umich.edu
615172Sgblack@eecs.umich.educlass LSQ : public Named
625172Sgblack@eecs.umich.edu{
637620Sgblack@eecs.umich.edu  protected:
647682Sgblack@eecs.umich.edu    /** My owner(s) */
657682Sgblack@eecs.umich.edu    MinorCPU &cpu;
667682Sgblack@eecs.umich.edu    Execute &execute;
675172Sgblack@eecs.umich.edu
685172Sgblack@eecs.umich.edu  protected:
695172Sgblack@eecs.umich.edu    /** State of memory access for head access. */
705172Sgblack@eecs.umich.edu    enum MemoryState
715449Sgblack@eecs.umich.edu    {
725449Sgblack@eecs.umich.edu        MemoryRunning, /* Default. Step dcache queues when possible. */
735449Sgblack@eecs.umich.edu        MemoryNeedsRetry /* Request rejected, will be asked to retry */
745172Sgblack@eecs.umich.edu    };
754590Sgblack@eecs.umich.edu
764590Sgblack@eecs.umich.edu    /** Print MemoryState values as shown in the enum definition */
775163Sgblack@eecs.umich.edu    friend std::ostream &operator <<(std::ostream &os,
785163Sgblack@eecs.umich.edu        MemoryState state);
795163Sgblack@eecs.umich.edu
805163Sgblack@eecs.umich.edu    /** Coverage of one address range with another */
815163Sgblack@eecs.umich.edu    enum AddrRangeCoverage
827620Sgblack@eecs.umich.edu    {
835163Sgblack@eecs.umich.edu        PartialAddrRangeCoverage, /* Two ranges partly overlap */
845163Sgblack@eecs.umich.edu        FullAddrRangeCoverage, /* One range fully covers another */
855163Sgblack@eecs.umich.edu        NoAddrRangeCoverage /* Two ranges are disjoint */
865163Sgblack@eecs.umich.edu    };
875163Sgblack@eecs.umich.edu
885163Sgblack@eecs.umich.edu    /** Exposable data port */
895163Sgblack@eecs.umich.edu    class DcachePort : public MinorCPU::MinorCPUPort
904519Sgblack@eecs.umich.edu    {
914519Sgblack@eecs.umich.edu      protected:
925163Sgblack@eecs.umich.edu        /** My owner */
935163Sgblack@eecs.umich.edu        LSQ &lsq;
945163Sgblack@eecs.umich.edu
955163Sgblack@eecs.umich.edu      public:
965163Sgblack@eecs.umich.edu        DcachePort(std::string name, LSQ &lsq_, MinorCPU &cpu) :
975163Sgblack@eecs.umich.edu            MinorCPU::MinorCPUPort(name, cpu), lsq(lsq_)
985163Sgblack@eecs.umich.edu        { }
995163Sgblack@eecs.umich.edu
1004519Sgblack@eecs.umich.edu      protected:
1014519Sgblack@eecs.umich.edu        bool recvTimingResp(PacketPtr pkt) override
1024519Sgblack@eecs.umich.edu        { return lsq.recvTimingResp(pkt); }
1035172Sgblack@eecs.umich.edu
1045172Sgblack@eecs.umich.edu        void recvReqRetry() override { lsq.recvReqRetry(); }
1055172Sgblack@eecs.umich.edu
1065172Sgblack@eecs.umich.edu        bool isSnooping() const override { return true; }
1075172Sgblack@eecs.umich.edu
1085173Sgblack@eecs.umich.edu        void recvTimingSnoopReq(PacketPtr pkt) override
1095172Sgblack@eecs.umich.edu        { return lsq.recvTimingSnoopReq(pkt); }
1105172Sgblack@eecs.umich.edu
1115172Sgblack@eecs.umich.edu        void recvFunctionalSnoop(PacketPtr pkt) override { }
1125172Sgblack@eecs.umich.edu    };
1134590Sgblack@eecs.umich.edu
1145163Sgblack@eecs.umich.edu    DcachePort dcachePort;
1155163Sgblack@eecs.umich.edu
1167620Sgblack@eecs.umich.edu  public:
1177620Sgblack@eecs.umich.edu    /** Derived SenderState to carry data access info. through address
1185163Sgblack@eecs.umich.edu     *  translation, the queues in this port and back from the memory
1194519Sgblack@eecs.umich.edu     *  system. */
1204519Sgblack@eecs.umich.edu    class LSQRequest :
1214519Sgblack@eecs.umich.edu        public BaseTLB::Translation, /* For TLB lookups */
1224519Sgblack@eecs.umich.edu        public Packet::SenderState /* For packing into a Packet */
1235163Sgblack@eecs.umich.edu    {
1245163Sgblack@eecs.umich.edu      public:
1257620Sgblack@eecs.umich.edu        /** Owning port */
1265163Sgblack@eecs.umich.edu        LSQ &port;
1277620Sgblack@eecs.umich.edu
1285163Sgblack@eecs.umich.edu        /** Instruction which made this request */
1297626Sgblack@eecs.umich.edu        MinorDynInstPtr inst;
1305163Sgblack@eecs.umich.edu
1315163Sgblack@eecs.umich.edu        /** Load/store indication used for building packet.  This isn't
1325163Sgblack@eecs.umich.edu         *  carried by Request so we need to keep it here */
1334696Sgblack@eecs.umich.edu        bool isLoad;
1345163Sgblack@eecs.umich.edu
1354696Sgblack@eecs.umich.edu        /** Dynamically allocated and populated data carried for
1364696Sgblack@eecs.umich.edu         *  building write packets */
1374696Sgblack@eecs.umich.edu        PacketDataPtr data;
1384696Sgblack@eecs.umich.edu
1394696Sgblack@eecs.umich.edu        /* Requests carry packets on their way to the memory system.
1404696Sgblack@eecs.umich.edu         *  When a Packet returns from the memory system, its
1414696Sgblack@eecs.umich.edu         *  request needs to have its packet updated as this
1424696Sgblack@eecs.umich.edu         *  may have changed in flight */
1434696Sgblack@eecs.umich.edu        PacketPtr packet;
1444696Sgblack@eecs.umich.edu
1454696Sgblack@eecs.umich.edu        /** The underlying request of this LSQRequest */
1464696Sgblack@eecs.umich.edu        Request request;
1475449Sgblack@eecs.umich.edu
1485449Sgblack@eecs.umich.edu        /** Fault generated performing this request */
1495449Sgblack@eecs.umich.edu        Fault fault;
1505449Sgblack@eecs.umich.edu
1515449Sgblack@eecs.umich.edu        /** Res from pushRequest */
1525449Sgblack@eecs.umich.edu        uint64_t *res;
1535449Sgblack@eecs.umich.edu
1545449Sgblack@eecs.umich.edu        /** Was skipped.  Set to indicate any reason (faulted, bad
1555449Sgblack@eecs.umich.edu         *  stream sequence number, in a fault shadow) that this
1565449Sgblack@eecs.umich.edu         *  request did not perform a memory transfer */
1574696Sgblack@eecs.umich.edu        bool skipped;
1584696Sgblack@eecs.umich.edu
1594519Sgblack@eecs.umich.edu        /** This in an access other than a normal cacheable load
1604590Sgblack@eecs.umich.edu         *  that's visited the memory system */
1615163Sgblack@eecs.umich.edu        bool issuedToMemory;
1625163Sgblack@eecs.umich.edu
1634590Sgblack@eecs.umich.edu        enum LSQRequestState
1645163Sgblack@eecs.umich.edu        {
1655163Sgblack@eecs.umich.edu            NotIssued, /* Newly created */
1665163Sgblack@eecs.umich.edu            InTranslation, /* TLB accessed, no reply yet */
1675163Sgblack@eecs.umich.edu            Translated, /* Finished address translation */
1685163Sgblack@eecs.umich.edu            Failed, /* The starting start of FailedDataRequests */
1695163Sgblack@eecs.umich.edu            RequestIssuing, /* Load/store issued to memory in the requests
1705163Sgblack@eecs.umich.edu                queue */
1714590Sgblack@eecs.umich.edu            StoreToStoreBuffer, /* Store in transfers on its way to the
1727620Sgblack@eecs.umich.edu                store buffer */
1737620Sgblack@eecs.umich.edu            RequestNeedsRetry, /* Retry needed for load */
1745163Sgblack@eecs.umich.edu            StoreInStoreBuffer, /* Store in the store buffer, before issuing
1755163Sgblack@eecs.umich.edu                a memory transfer */
1764590Sgblack@eecs.umich.edu            StoreBufferIssuing, /* Store in store buffer and has been
1775163Sgblack@eecs.umich.edu                issued */
1785163Sgblack@eecs.umich.edu            StoreBufferNeedsRetry, /* Retry needed for store */
1794590Sgblack@eecs.umich.edu            /* All completed states.  Includes
1805163Sgblack@eecs.umich.edu                completed loads, TLB faults and skipped requests whose
1815293Sgblack@eecs.umich.edu                seqNum's no longer match */
1825163Sgblack@eecs.umich.edu            Complete
1835163Sgblack@eecs.umich.edu        };
1845163Sgblack@eecs.umich.edu
1855163Sgblack@eecs.umich.edu        LSQRequestState state;
1865163Sgblack@eecs.umich.edu
1875293Sgblack@eecs.umich.edu      protected:
1885163Sgblack@eecs.umich.edu        /** BaseTLB::Translation interface */
1895163Sgblack@eecs.umich.edu        void markDelayed() { }
1905163Sgblack@eecs.umich.edu
1915163Sgblack@eecs.umich.edu      public:
1925163Sgblack@eecs.umich.edu        LSQRequest(LSQ &port_, MinorDynInstPtr inst_, bool isLoad_,
1934590Sgblack@eecs.umich.edu            PacketDataPtr data_ = NULL, uint64_t *res_ = NULL);
1945172Sgblack@eecs.umich.edu
1955172Sgblack@eecs.umich.edu        virtual ~LSQRequest();
1966047Sgblack@eecs.umich.edu
1975172Sgblack@eecs.umich.edu      public:
1985172Sgblack@eecs.umich.edu        /** Make a packet to use with the memory transaction */
1995172Sgblack@eecs.umich.edu        void makePacket();
2007620Sgblack@eecs.umich.edu
2017620Sgblack@eecs.umich.edu        /** Was no memory access attempted for this request? */
2025172Sgblack@eecs.umich.edu        bool skippedMemAccess() { return skipped; }
2035172Sgblack@eecs.umich.edu
2045172Sgblack@eecs.umich.edu        /** Set this request as having been skipped before a memory
2054519Sgblack@eecs.umich.edu         *  transfer was attempt */
206        void setSkipped() { skipped = true; }
207
208        /** Does address range req1 (req1_addr to req1_addr + req1_size - 1)
209         *  fully cover, partially cover or not cover at all the range req2 */
210        static AddrRangeCoverage containsAddrRangeOf(
211            Addr req1_addr, unsigned int req1_size,
212            Addr req2_addr, unsigned int req2_size);
213
214        /** Does this request's address range fully cover the range
215         *  of other_request? */
216        AddrRangeCoverage containsAddrRangeOf(LSQRequest *other_request);
217
218        /** Start the address translation process for this request.  This
219         *  will issue a translation request to the TLB. */
220        virtual void startAddrTranslation() = 0;
221
222        /** Get the next packet to issue for this request.  For split
223         *  transfers, it will be necessary to step through the available
224         *  packets by calling do { getHeadPacket ; stepToNextPacket } while
225         *  (!sentAllPackets) and by retiring response using retireResponse */
226        virtual PacketPtr getHeadPacket() = 0;
227
228        /** Step to the next packet for the next call to getHeadPacket */
229        virtual void stepToNextPacket() = 0;
230
231        /** Have all packets been sent? */
232        virtual bool sentAllPackets() = 0;
233
234        /** True if this request has any issued packets in the memory
235         *  system and so can't be interrupted until it gets responses */
236        virtual bool hasPacketsInMemSystem() = 0;
237
238        /** Retire a response packet into the LSQRequest packet possibly
239         *  completing this transfer */
240        virtual void retireResponse(PacketPtr packet_) = 0;
241
242        /** Is this a request a barrier? */
243        virtual bool isBarrier();
244
245        /** This request, once processed by the requests/transfers
246         *  queues, will need to go to the store buffer */
247        bool needsToBeSentToStoreBuffer();
248
249        /** Set state and output trace output */
250        void setState(LSQRequestState new_state);
251
252        /** Has this request been completed.  This includes *all* reasons
253         *  for completion: successful transfers, faults, skipped because
254         *  of preceding faults */
255        bool isComplete() const;
256
257        /** MinorTrace report interface */
258        void reportData(std::ostream &os) const;
259    };
260
261    typedef LSQRequest *LSQRequestPtr;
262
263    friend std::ostream & operator <<(std::ostream &os,
264        AddrRangeCoverage state);
265
266    friend std::ostream & operator <<(std::ostream &os,
267        LSQRequest::LSQRequestState state);
268
269  protected:
270    /** Special request types that don't actually issue memory requests */
271    class SpecialDataRequest : public LSQRequest
272    {
273      protected:
274        /** TLB interace */
275        void finish(const Fault &fault_, RequestPtr request_,
276                    ThreadContext *tc, BaseTLB::Mode mode)
277        { }
278
279      public:
280        /** Send single translation request */
281        void startAddrTranslation() { }
282
283        /** Get the head packet as counted by numIssuedFragments */
284        PacketPtr getHeadPacket()
285        { fatal("No packets in a SpecialDataRequest"); }
286
287        /** Step on numIssuedFragments */
288        void stepToNextPacket() { }
289
290        /** Has no packets to send */
291        bool sentAllPackets() { return true; }
292
293        /** Never sends any requests */
294        bool hasPacketsInMemSystem() { return false; }
295
296        /** Keep the given packet as the response packet
297         *  LSQRequest::packet */
298        void retireResponse(PacketPtr packet_) { }
299
300      public:
301        SpecialDataRequest(LSQ &port_, MinorDynInstPtr inst_) :
302            /* Say this is a load, not actually relevant */
303            LSQRequest(port_, inst_, true, NULL, 0)
304        { }
305    };
306
307    /** FailedDataRequest represents requests from instructions that
308     *  failed their predicates but need to ride the requests/transfers
309     *  queues to maintain trace ordering */
310    class FailedDataRequest : public SpecialDataRequest
311    {
312      public:
313        FailedDataRequest(LSQ &port_, MinorDynInstPtr inst_) :
314            SpecialDataRequest(port_, inst_)
315        { state = Failed; }
316    };
317
318    /** Request for doing barrier accounting in the store buffer.  Not
319     *  for use outside that unit */
320    class BarrierDataRequest : public SpecialDataRequest
321    {
322      public:
323        bool isBarrier() { return true; }
324
325      public:
326        BarrierDataRequest(LSQ &port_, MinorDynInstPtr inst_) :
327            SpecialDataRequest(port_, inst_)
328        { state = Complete; }
329    };
330
331    /** SingleDataRequest is used for requests that don't fragment */
332    class SingleDataRequest : public LSQRequest
333    {
334      protected:
335        /** TLB interace */
336        void finish(const Fault &fault_, RequestPtr request_,
337                    ThreadContext *tc, BaseTLB::Mode mode);
338
339        /** Has my only packet been sent to the memory system but has not
340         *  yet been responded to */
341        bool packetInFlight;
342
343        /** Has the packet been at least sent to the memory system? */
344        bool packetSent;
345
346      public:
347        /** Send single translation request */
348        void startAddrTranslation();
349
350        /** Get the head packet as counted by numIssuedFragments */
351        PacketPtr getHeadPacket() { return packet; }
352
353        /** Remember that the packet has been sent */
354        void stepToNextPacket() { packetInFlight = true; packetSent = true; }
355
356        /** Has packet been sent */
357        bool hasPacketsInMemSystem() { return packetInFlight; }
358
359        /** packetInFlight can become false again, so need to check
360         *  packetSent */
361        bool sentAllPackets() { return packetSent; }
362
363        /** Keep the given packet as the response packet
364         *  LSQRequest::packet */
365        void retireResponse(PacketPtr packet_);
366
367      public:
368        SingleDataRequest(LSQ &port_, MinorDynInstPtr inst_,
369            bool isLoad_, PacketDataPtr data_ = NULL, uint64_t *res_ = NULL) :
370            LSQRequest(port_, inst_, isLoad_, data_, res_),
371            packetInFlight(false),
372            packetSent(false)
373        { }
374    };
375
376    class SplitDataRequest : public LSQRequest
377    {
378      protected:
379        /** Event to step between translations */
380        EventFunctionWrapper translationEvent;
381      protected:
382        /** Number of fragments this request is split into */
383        unsigned int numFragments;
384
385        /** Number of fragments in the address translation mechanism */
386        unsigned int numInTranslationFragments;
387
388        /** Number of fragments that have completed address translation,
389         *  (numTranslatedFragments + numInTranslationFragments) <=
390         *  numFragments.  When numTranslatedFramgents == numFragments,
391         *  translation is complete */
392        unsigned int numTranslatedFragments;
393
394        /** Number of fragments already issued (<= numFragments) */
395        unsigned int numIssuedFragments;
396
397        /** Number of fragments retired back to this request */
398        unsigned int numRetiredFragments;
399
400        /** Fragment Requests corresponding to the address ranges of
401         *  each fragment */
402        std::vector<Request *> fragmentRequests;
403
404        /** Packets matching fragmentRequests to issue fragments to memory */
405        std::vector<Packet *> fragmentPackets;
406
407      protected:
408        /** TLB response interface */
409        void finish(const Fault &fault_, RequestPtr request_,
410                    ThreadContext *tc, BaseTLB::Mode mode);
411
412      public:
413        SplitDataRequest(LSQ &port_, MinorDynInstPtr inst_,
414            bool isLoad_, PacketDataPtr data_ = NULL,
415            uint64_t *res_ = NULL);
416
417        ~SplitDataRequest();
418
419      public:
420        /** Make all the Requests for this transfer's fragments so that those
421         *  requests can be sent for address translation */
422        void makeFragmentRequests();
423
424        /** Make the packets to go with the requests so they can be sent to
425         *  the memory system */
426        void makeFragmentPackets();
427
428        /** Start a loop of do { sendNextFragmentToTranslation ;
429         *  translateTiming ; finish } while (numTranslatedFragments !=
430         *  numFragments) to complete all this requests' fragments' address
431         *  translations */
432        void startAddrTranslation();
433
434        /** Get the head packet as counted by numIssuedFragments */
435        PacketPtr getHeadPacket();
436
437        /** Step on numIssuedFragments */
438        void stepToNextPacket();
439
440        bool hasPacketsInMemSystem()
441        { return numIssuedFragments != numRetiredFragments; }
442
443        /** Have we stepped past the end of fragmentPackets? */
444        bool sentAllPackets() { return numIssuedFragments == numFragments; }
445
446        /** For loads, paste the response data into the main
447         *  response packet */
448        void retireResponse(PacketPtr packet_);
449
450        /** Part of the address translation loop, see startAddTranslation */
451        void sendNextFragmentToTranslation();
452    };
453
454    /** Store buffer.  This contains stores which have been committed
455     *  but whose memory transfers have not yet been issued. Load data
456     *  can be forwarded out of the store buffer */
457    class StoreBuffer : public Named
458    {
459      public:
460        /** My owner */
461        LSQ &lsq;
462
463        /** Number of slots, this is a bound on the size of slots */
464        const unsigned int numSlots;
465
466        /** Maximum number of stores that can be issued per cycle */
467        const unsigned int storeLimitPerCycle;
468
469      public:
470        /** Queue of store requests on their way to memory */
471        std::deque<LSQRequestPtr> slots;
472
473        /** Number of occupied slots which have not yet issued a
474         *  memory access */
475        unsigned int numUnissuedAccesses;
476
477      public:
478        StoreBuffer(std::string name_, LSQ &lsq_,
479            unsigned int store_buffer_size,
480            unsigned int store_limit_per_cycle);
481
482      public:
483        /** Can a new request be inserted into the queue? */
484        bool canInsert() const;
485
486        /** Delete the given request and free the slot it occupied */
487        void deleteRequest(LSQRequestPtr request);
488
489        /** Insert a request at the back of the queue */
490        void insert(LSQRequestPtr request);
491
492        /** Look for a store which satisfies the given load.  Returns an
493         *  indication whether the forwarding request can be wholly,
494         *  partly or not all all satisfied.  If the request can be
495         *  wholly satisfied, the store buffer slot number which can be used
496         *  is returned in found_slot */
497        AddrRangeCoverage canForwardDataToLoad(LSQRequestPtr request,
498            unsigned int &found_slot);
499
500        /** Fill the given packet with appropriate date from slot
501         *  slot_number */
502        void forwardStoreData(LSQRequestPtr load, unsigned int slot_number);
503
504        /** Number of stores in the store buffer which have not been
505         *  completely issued to the memory system */
506        unsigned int numUnissuedStores() { return numUnissuedAccesses; }
507
508        /** Count a store being issued to memory by decrementing
509         *  numUnissuedAccesses.  Does not count barrier requests as they
510         *  will be handles as barriers are cleared from the buffer */
511        void countIssuedStore(LSQRequestPtr request);
512
513        /** Drained if there is absolutely nothing left in the buffer */
514        bool isDrained() const { return slots.empty(); }
515
516        /** Try to issue more stores to memory */
517        void step();
518
519        /** Report queue contents for MinorTrace */
520        void minorTrace() const;
521    };
522
523  protected:
524    /** Most recent execSeqNum of a memory barrier instruction or
525     *  0 if there are no in-flight barriers.  Useful as a
526     *  dependency for early-issued memory operations */
527    std::vector<InstSeqNum> lastMemBarrier;
528
529  public:
530    /** Retry state of last issued memory transfer */
531    MemoryState state;
532
533    /** Maximum number of in-flight accesses issued to the memory system */
534    const unsigned int inMemorySystemLimit;
535
536    /** Memory system access width (and snap) in bytes */
537    const unsigned int lineWidth;
538
539  public:
540    /** The LSQ consists of three queues: requests, transfers and the
541     *  store buffer storeBuffer. */
542
543    typedef Queue<LSQRequestPtr,
544        ReportTraitsPtrAdaptor<LSQRequestPtr>,
545        NoBubbleTraits<LSQRequestPtr> >
546        LSQQueue;
547
548    /** requests contains LSQRequests which have been issued to the TLB by
549     *  calling ExecContext::readMem/writeMem (which in turn calls
550     *  LSQ::pushRequest and LSQRequest::startAddrTranslation).  Once they
551     *  have a physical address, requests at the head of requests can be
552     *  issued to the memory system.  At this stage, it cannot be clear that
553     *  memory accesses *must* happen (that there are no preceding faults or
554     *  changes of flow of control) and so only cacheable reads are issued
555     *  to memory.
556     *  Cacheable stores are not issued at all (and just pass through
557     *  'transfers' in order) and all other transfers are stalled in requests
558     *  until their corresponding instructions are at the head of the
559     *  inMemInsts instruction queue and have the right streamSeqNum. */
560    LSQQueue requests;
561
562    /** Once issued to memory (or, for stores, just had their
563     *  state changed to StoreToStoreBuffer) LSQRequests pass through
564     *  transfers waiting for memory responses.  At the head of transfers,
565     *  Execute::commitInst can pick up the memory response for a request
566     *  using LSQ::findResponse.  Responses to be committed can then
567     *  have ExecContext::completeAcc on them.  Stores can then be pushed
568     *  into the store buffer.  All other transfers will then be complete. */
569    LSQQueue transfers;
570
571    /* The store buffer contains committed cacheable stores on
572     * their way to memory decoupled from subsequence instruction execution.
573     * Before trying to issue a cacheable read from 'requests' to memory,
574     * the store buffer is checked to see if a previous store contains the
575     * needed data (StoreBuffer::canForwardDataToLoad) which can be
576     * forwarded in lieu of a memory access.  If there are outstanding
577     * stores in the transfers queue, they must be promoted to the store
578     * buffer (and so be commited) before they can be correctly checked
579     * for forwarding. */
580    StoreBuffer storeBuffer;
581
582  protected:
583    /** Count of the number of mem. accesses which have left the
584     *  requests queue and are in the 'wild' in the memory system and who
585     *  *must not* be interrupted as they are not normal cacheable
586     *  accesses.  This is a count of the number of in-flight requests
587     *  with issuedToMemory set who have visited tryToSendRequest at least
588     *  once */
589    unsigned int numAccessesInMemorySystem;
590
591    /** Number of requests in the DTLB in the requests queue */
592    unsigned int numAccessesInDTLB;
593
594    /** The number of stores in the transfers queue.  Useful when
595     *  testing if the store buffer contains all the forwardable stores */
596    unsigned int numStoresInTransfers;
597
598    /** The number of accesses which have been issued to the memory
599     *  system but have not been committed/discarded *excluding*
600     *  cacheable normal loads which don't need to be tracked */
601    unsigned int numAccessesIssuedToMemory;
602
603    /** The request (from either requests or the store buffer) which is
604     *  currently waiting have its memory access retried */
605    LSQRequestPtr retryRequest;
606
607    /** Address Mask for a cache block (e.g. ~(cache_block_size-1)) */
608    Addr cacheBlockMask;
609
610  protected:
611    /** Try and issue a memory access for a translated request at the
612     *  head of the requests queue.  Also tries to move the request
613     *  between queues */
614    void tryToSendToTransfers(LSQRequestPtr request);
615
616    /** Try to send (or resend) a memory request's next/only packet to
617     *  the memory system.  Returns true if the request was successfully
618     *  sent to memory (and was also the last packet in a transfer) */
619    bool tryToSend(LSQRequestPtr request);
620
621    /** Clear a barrier (if it's the last one marked up in lastMemBarrier) */
622    void clearMemBarrier(MinorDynInstPtr inst);
623
624    /** Move a request between queues */
625    void moveFromRequestsToTransfers(LSQRequestPtr request);
626
627    /** Can a request be sent to the memory system */
628    bool canSendToMemorySystem();
629
630    /** Snoop other threads monitors on memory system accesses */
631    void threadSnoop(LSQRequestPtr request);
632
633  public:
634    LSQ(std::string name_, std::string dcache_port_name_,
635        MinorCPU &cpu_, Execute &execute_,
636        unsigned int max_accesses_in_memory_system, unsigned int line_width,
637        unsigned int requests_queue_size, unsigned int transfers_queue_size,
638        unsigned int store_buffer_size,
639        unsigned int store_buffer_cycle_store_limit);
640
641    virtual ~LSQ();
642
643  public:
644    /** Step checks the queues to see if their are issuable transfers
645     *  which were not otherwise picked up by tests at the end of other
646     *  events.
647     *
648     *  Steppable actions include deferred actions which couldn't be
649     *  cascaded on the end of a memory response/TLB response event
650     *  because of resource congestion. */
651    void step();
652
653    /** Is their space in the request queue to be able to push a request by
654     *  issuing an isMemRef instruction */
655    bool canRequest() { return requests.unreservedRemainingSpace() != 0; }
656
657    /** Returns a response if it's at the head of the transfers queue and
658     *  it's either complete or can be sent on to the store buffer.  After
659     *  calling, the request still remains on the transfer queue until
660     *  popResponse is called */
661    LSQRequestPtr findResponse(MinorDynInstPtr inst);
662
663    /** Sanity check and pop the head response */
664    void popResponse(LSQRequestPtr response);
665
666    /** Must check this before trying to insert into the store buffer */
667    bool canPushIntoStoreBuffer() const { return storeBuffer.canInsert(); }
668
669    /** A store has been committed, please move it to the store buffer */
670    void sendStoreToStoreBuffer(LSQRequestPtr request);
671
672    /** Are there any accesses other than normal cached loads in the
673     *  memory system or having received responses which need to be
674     *  handled for their instruction's to be completed */
675    bool accessesInFlight() const
676    { return numAccessesIssuedToMemory != 0; }
677
678    /** A memory barrier instruction has been issued, remember its
679     *  execSeqNum that we can avoid issuing memory ops until it is
680     *  committed */
681    void issuedMemBarrierInst(MinorDynInstPtr inst);
682
683    /** Get the execSeqNum of the last issued memory barrier */
684    InstSeqNum getLastMemBarrier(ThreadID thread_id) const
685    { return lastMemBarrier[thread_id]; }
686
687    /** Is there nothing left in the LSQ */
688    bool isDrained();
689
690    /** May need to be ticked next cycle as one of the queues contains
691     *  an actionable transfers or address translation */
692    bool needsToTick();
693
694    /** Complete a barrier instruction.  Where committed, makes a
695     *  BarrierDataRequest and pushed it into the store buffer */
696    void completeMemBarrierInst(MinorDynInstPtr inst,
697        bool committed);
698
699    /** Single interface for readMem/writeMem to issue requests into
700     *  the LSQ */
701    void pushRequest(MinorDynInstPtr inst, bool isLoad, uint8_t *data,
702                     unsigned int size, Addr addr, Request::Flags flags,
703                     uint64_t *res);
704
705    /** Push a predicate failed-representing request into the queues just
706     *  to maintain commit order */
707    void pushFailedRequest(MinorDynInstPtr inst);
708
709    /** Memory interface */
710    bool recvTimingResp(PacketPtr pkt);
711    void recvReqRetry();
712    void recvTimingSnoopReq(PacketPtr pkt);
713
714    /** Return the raw-bindable port */
715    MinorCPU::MinorCPUPort &getDcachePort() { return dcachePort; }
716
717    void minorTrace() const;
718};
719
720/** Make a suitable packet for the given request.  If the request is a store,
721 *  data will be the payload data.  If sender_state is NULL, it won't be
722 *  pushed into the packet as senderState */
723PacketPtr makePacketForRequest(Request &request, bool isLoad,
724    Packet::SenderState *sender_state = NULL, PacketDataPtr data = NULL);
725}
726
727#endif /* __CPU_MINOR_NEW_LSQ_HH__ */
728