110259SAndrew.Bardsley@arm.com/*
213954Sgiacomo.gabrielli@arm.com * Copyright (c) 2013-2014, 2018 ARM Limited
310259SAndrew.Bardsley@arm.com * All rights reserved
410259SAndrew.Bardsley@arm.com *
510259SAndrew.Bardsley@arm.com * The license below extends only to copyright in the software and shall
610259SAndrew.Bardsley@arm.com * not be construed as granting a license to any other intellectual
710259SAndrew.Bardsley@arm.com * property including but not limited to intellectual property relating
810259SAndrew.Bardsley@arm.com * to a hardware implementation of the functionality of the software
910259SAndrew.Bardsley@arm.com * licensed hereunder.  You may use the software subject to the license
1010259SAndrew.Bardsley@arm.com * terms below provided that you ensure that this notice is replicated
1110259SAndrew.Bardsley@arm.com * unmodified and in its entirety in all distributions of the software,
1210259SAndrew.Bardsley@arm.com * modified or unmodified, in source code or in binary form.
1310259SAndrew.Bardsley@arm.com *
1410259SAndrew.Bardsley@arm.com * Redistribution and use in source and binary forms, with or without
1510259SAndrew.Bardsley@arm.com * modification, are permitted provided that the following conditions are
1610259SAndrew.Bardsley@arm.com * met: redistributions of source code must retain the above copyright
1710259SAndrew.Bardsley@arm.com * notice, this list of conditions and the following disclaimer;
1810259SAndrew.Bardsley@arm.com * redistributions in binary form must reproduce the above copyright
1910259SAndrew.Bardsley@arm.com * notice, this list of conditions and the following disclaimer in the
2010259SAndrew.Bardsley@arm.com * documentation and/or other materials provided with the distribution;
2110259SAndrew.Bardsley@arm.com * neither the name of the copyright holders nor the names of its
2210259SAndrew.Bardsley@arm.com * contributors may be used to endorse or promote products derived from
2310259SAndrew.Bardsley@arm.com * this software without specific prior written permission.
2410259SAndrew.Bardsley@arm.com *
2510259SAndrew.Bardsley@arm.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
2610259SAndrew.Bardsley@arm.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
2710259SAndrew.Bardsley@arm.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
2810259SAndrew.Bardsley@arm.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
2910259SAndrew.Bardsley@arm.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
3010259SAndrew.Bardsley@arm.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
3110259SAndrew.Bardsley@arm.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
3210259SAndrew.Bardsley@arm.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
3310259SAndrew.Bardsley@arm.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
3410259SAndrew.Bardsley@arm.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
3510259SAndrew.Bardsley@arm.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3610259SAndrew.Bardsley@arm.com *
3710259SAndrew.Bardsley@arm.com * Authors: Andrew Bardsley
3810259SAndrew.Bardsley@arm.com */
3910259SAndrew.Bardsley@arm.com
4010259SAndrew.Bardsley@arm.com/**
4110259SAndrew.Bardsley@arm.com * @file
4210259SAndrew.Bardsley@arm.com *
4310259SAndrew.Bardsley@arm.com *  A load/store queue that allows outstanding reads and writes.
4410259SAndrew.Bardsley@arm.com *
4510259SAndrew.Bardsley@arm.com */
4610259SAndrew.Bardsley@arm.com
4710259SAndrew.Bardsley@arm.com#ifndef __CPU_MINOR_NEW_LSQ_HH__
4810259SAndrew.Bardsley@arm.com#define __CPU_MINOR_NEW_LSQ_HH__
4910259SAndrew.Bardsley@arm.com
5010259SAndrew.Bardsley@arm.com#include "cpu/minor/buffers.hh"
5110259SAndrew.Bardsley@arm.com#include "cpu/minor/cpu.hh"
5210259SAndrew.Bardsley@arm.com#include "cpu/minor/pipe_data.hh"
5310259SAndrew.Bardsley@arm.com#include "cpu/minor/trace.hh"
5410259SAndrew.Bardsley@arm.com
5510259SAndrew.Bardsley@arm.comnamespace Minor
5610259SAndrew.Bardsley@arm.com{
5710259SAndrew.Bardsley@arm.com
5810259SAndrew.Bardsley@arm.com/* Forward declaration */
5910259SAndrew.Bardsley@arm.comclass Execute;
6010259SAndrew.Bardsley@arm.com
6110259SAndrew.Bardsley@arm.comclass LSQ : public Named
6210259SAndrew.Bardsley@arm.com{
6310259SAndrew.Bardsley@arm.com  protected:
6410259SAndrew.Bardsley@arm.com    /** My owner(s) */
6510259SAndrew.Bardsley@arm.com    MinorCPU &cpu;
6610259SAndrew.Bardsley@arm.com    Execute &execute;
6710259SAndrew.Bardsley@arm.com
6810259SAndrew.Bardsley@arm.com  protected:
6910259SAndrew.Bardsley@arm.com    /** State of memory access for head access. */
7010259SAndrew.Bardsley@arm.com    enum MemoryState
7110259SAndrew.Bardsley@arm.com    {
7210259SAndrew.Bardsley@arm.com        MemoryRunning, /* Default. Step dcache queues when possible. */
7310259SAndrew.Bardsley@arm.com        MemoryNeedsRetry /* Request rejected, will be asked to retry */
7410259SAndrew.Bardsley@arm.com    };
7510259SAndrew.Bardsley@arm.com
7610259SAndrew.Bardsley@arm.com    /** Print MemoryState values as shown in the enum definition */
7710259SAndrew.Bardsley@arm.com    friend std::ostream &operator <<(std::ostream &os,
7810259SAndrew.Bardsley@arm.com        MemoryState state);
7910259SAndrew.Bardsley@arm.com
8010259SAndrew.Bardsley@arm.com    /** Coverage of one address range with another */
8110259SAndrew.Bardsley@arm.com    enum AddrRangeCoverage
8210259SAndrew.Bardsley@arm.com    {
8310259SAndrew.Bardsley@arm.com        PartialAddrRangeCoverage, /* Two ranges partly overlap */
8410259SAndrew.Bardsley@arm.com        FullAddrRangeCoverage, /* One range fully covers another */
8510259SAndrew.Bardsley@arm.com        NoAddrRangeCoverage /* Two ranges are disjoint */
8610259SAndrew.Bardsley@arm.com    };
8710259SAndrew.Bardsley@arm.com
8810259SAndrew.Bardsley@arm.com    /** Exposable data port */
8910259SAndrew.Bardsley@arm.com    class DcachePort : public MinorCPU::MinorCPUPort
9010259SAndrew.Bardsley@arm.com    {
9110259SAndrew.Bardsley@arm.com      protected:
9210259SAndrew.Bardsley@arm.com        /** My owner */
9310259SAndrew.Bardsley@arm.com        LSQ &lsq;
9410259SAndrew.Bardsley@arm.com
9510259SAndrew.Bardsley@arm.com      public:
9610259SAndrew.Bardsley@arm.com        DcachePort(std::string name, LSQ &lsq_, MinorCPU &cpu) :
9710259SAndrew.Bardsley@arm.com            MinorCPU::MinorCPUPort(name, cpu), lsq(lsq_)
9810259SAndrew.Bardsley@arm.com        { }
9910259SAndrew.Bardsley@arm.com
10010259SAndrew.Bardsley@arm.com      protected:
10111341Sandreas.hansson@arm.com        bool recvTimingResp(PacketPtr pkt) override
10210259SAndrew.Bardsley@arm.com        { return lsq.recvTimingResp(pkt); }
10310259SAndrew.Bardsley@arm.com
10411341Sandreas.hansson@arm.com        void recvReqRetry() override { lsq.recvReqRetry(); }
10510259SAndrew.Bardsley@arm.com
10611331Sandreas.hansson@arm.com        bool isSnooping() const override { return true; }
10711331Sandreas.hansson@arm.com
10811341Sandreas.hansson@arm.com        void recvTimingSnoopReq(PacketPtr pkt) override
10910259SAndrew.Bardsley@arm.com        { return lsq.recvTimingSnoopReq(pkt); }
11011331Sandreas.hansson@arm.com
11111341Sandreas.hansson@arm.com        void recvFunctionalSnoop(PacketPtr pkt) override { }
11210259SAndrew.Bardsley@arm.com    };
11310259SAndrew.Bardsley@arm.com
11410259SAndrew.Bardsley@arm.com    DcachePort dcachePort;
11510259SAndrew.Bardsley@arm.com
11610259SAndrew.Bardsley@arm.com  public:
11710259SAndrew.Bardsley@arm.com    /** Derived SenderState to carry data access info. through address
11810259SAndrew.Bardsley@arm.com     *  translation, the queues in this port and back from the memory
11910259SAndrew.Bardsley@arm.com     *  system. */
12010259SAndrew.Bardsley@arm.com    class LSQRequest :
12110259SAndrew.Bardsley@arm.com        public BaseTLB::Translation, /* For TLB lookups */
12210259SAndrew.Bardsley@arm.com        public Packet::SenderState /* For packing into a Packet */
12310259SAndrew.Bardsley@arm.com    {
12410259SAndrew.Bardsley@arm.com      public:
12510259SAndrew.Bardsley@arm.com        /** Owning port */
12610259SAndrew.Bardsley@arm.com        LSQ &port;
12710259SAndrew.Bardsley@arm.com
12810259SAndrew.Bardsley@arm.com        /** Instruction which made this request */
12910259SAndrew.Bardsley@arm.com        MinorDynInstPtr inst;
13010259SAndrew.Bardsley@arm.com
13110259SAndrew.Bardsley@arm.com        /** Load/store indication used for building packet.  This isn't
13210259SAndrew.Bardsley@arm.com         *  carried by Request so we need to keep it here */
13310259SAndrew.Bardsley@arm.com        bool isLoad;
13410259SAndrew.Bardsley@arm.com
13510259SAndrew.Bardsley@arm.com        /** Dynamically allocated and populated data carried for
13610259SAndrew.Bardsley@arm.com         *  building write packets */
13710259SAndrew.Bardsley@arm.com        PacketDataPtr data;
13810259SAndrew.Bardsley@arm.com
13910259SAndrew.Bardsley@arm.com        /* Requests carry packets on their way to the memory system.
14010259SAndrew.Bardsley@arm.com         *  When a Packet returns from the memory system, its
14110259SAndrew.Bardsley@arm.com         *  request needs to have its packet updated as this
14210259SAndrew.Bardsley@arm.com         *  may have changed in flight */
14310259SAndrew.Bardsley@arm.com        PacketPtr packet;
14410259SAndrew.Bardsley@arm.com
14510259SAndrew.Bardsley@arm.com        /** The underlying request of this LSQRequest */
14612749Sgiacomo.travaglini@arm.com        RequestPtr request;
14710259SAndrew.Bardsley@arm.com
14810259SAndrew.Bardsley@arm.com        /** Res from pushRequest */
14910259SAndrew.Bardsley@arm.com        uint64_t *res;
15010259SAndrew.Bardsley@arm.com
15110259SAndrew.Bardsley@arm.com        /** Was skipped.  Set to indicate any reason (faulted, bad
15210259SAndrew.Bardsley@arm.com         *  stream sequence number, in a fault shadow) that this
15310259SAndrew.Bardsley@arm.com         *  request did not perform a memory transfer */
15410259SAndrew.Bardsley@arm.com        bool skipped;
15510259SAndrew.Bardsley@arm.com
15610259SAndrew.Bardsley@arm.com        /** This in an access other than a normal cacheable load
15710259SAndrew.Bardsley@arm.com         *  that's visited the memory system */
15810259SAndrew.Bardsley@arm.com        bool issuedToMemory;
15910259SAndrew.Bardsley@arm.com
16014105Sgabor.dozsa@arm.com        /** Address translation is delayed due to table walk */
16114105Sgabor.dozsa@arm.com        bool isTranslationDelayed;
16214105Sgabor.dozsa@arm.com
16310259SAndrew.Bardsley@arm.com        enum LSQRequestState
16410259SAndrew.Bardsley@arm.com        {
16510259SAndrew.Bardsley@arm.com            NotIssued, /* Newly created */
16610259SAndrew.Bardsley@arm.com            InTranslation, /* TLB accessed, no reply yet */
16710259SAndrew.Bardsley@arm.com            Translated, /* Finished address translation */
16810259SAndrew.Bardsley@arm.com            Failed, /* The starting start of FailedDataRequests */
16910259SAndrew.Bardsley@arm.com            RequestIssuing, /* Load/store issued to memory in the requests
17010259SAndrew.Bardsley@arm.com                queue */
17110259SAndrew.Bardsley@arm.com            StoreToStoreBuffer, /* Store in transfers on its way to the
17210259SAndrew.Bardsley@arm.com                store buffer */
17310259SAndrew.Bardsley@arm.com            RequestNeedsRetry, /* Retry needed for load */
17410259SAndrew.Bardsley@arm.com            StoreInStoreBuffer, /* Store in the store buffer, before issuing
17510259SAndrew.Bardsley@arm.com                a memory transfer */
17610259SAndrew.Bardsley@arm.com            StoreBufferIssuing, /* Store in store buffer and has been
17710259SAndrew.Bardsley@arm.com                issued */
17810259SAndrew.Bardsley@arm.com            StoreBufferNeedsRetry, /* Retry needed for store */
17910259SAndrew.Bardsley@arm.com            /* All completed states.  Includes
18010259SAndrew.Bardsley@arm.com                completed loads, TLB faults and skipped requests whose
18110259SAndrew.Bardsley@arm.com                seqNum's no longer match */
18210259SAndrew.Bardsley@arm.com            Complete
18310259SAndrew.Bardsley@arm.com        };
18410259SAndrew.Bardsley@arm.com
18510259SAndrew.Bardsley@arm.com        LSQRequestState state;
18610259SAndrew.Bardsley@arm.com
18710259SAndrew.Bardsley@arm.com      protected:
18810259SAndrew.Bardsley@arm.com        /** BaseTLB::Translation interface */
18914105Sgabor.dozsa@arm.com        void markDelayed() { isTranslationDelayed = true; }
19014105Sgabor.dozsa@arm.com
19114105Sgabor.dozsa@arm.com        /** Instructions may want to suppress translation faults (e.g.
19214105Sgabor.dozsa@arm.com         *  non-faulting vector loads).*/
19314105Sgabor.dozsa@arm.com        void tryToSuppressFault();
19410259SAndrew.Bardsley@arm.com
19513954Sgiacomo.gabrielli@arm.com        void disableMemAccess();
19614105Sgabor.dozsa@arm.com        void completeDisabledMemAccess();
19713954Sgiacomo.gabrielli@arm.com
19810259SAndrew.Bardsley@arm.com      public:
19910259SAndrew.Bardsley@arm.com        LSQRequest(LSQ &port_, MinorDynInstPtr inst_, bool isLoad_,
20010259SAndrew.Bardsley@arm.com            PacketDataPtr data_ = NULL, uint64_t *res_ = NULL);
20110259SAndrew.Bardsley@arm.com
20210259SAndrew.Bardsley@arm.com        virtual ~LSQRequest();
20310259SAndrew.Bardsley@arm.com
20410259SAndrew.Bardsley@arm.com      public:
20510259SAndrew.Bardsley@arm.com        /** Make a packet to use with the memory transaction */
20610259SAndrew.Bardsley@arm.com        void makePacket();
20710259SAndrew.Bardsley@arm.com
20810259SAndrew.Bardsley@arm.com        /** Was no memory access attempted for this request? */
20910259SAndrew.Bardsley@arm.com        bool skippedMemAccess() { return skipped; }
21010259SAndrew.Bardsley@arm.com
21110259SAndrew.Bardsley@arm.com        /** Set this request as having been skipped before a memory
21210259SAndrew.Bardsley@arm.com         *  transfer was attempt */
21310259SAndrew.Bardsley@arm.com        void setSkipped() { skipped = true; }
21410259SAndrew.Bardsley@arm.com
21510259SAndrew.Bardsley@arm.com        /** Does address range req1 (req1_addr to req1_addr + req1_size - 1)
21610259SAndrew.Bardsley@arm.com         *  fully cover, partially cover or not cover at all the range req2 */
21710259SAndrew.Bardsley@arm.com        static AddrRangeCoverage containsAddrRangeOf(
21810259SAndrew.Bardsley@arm.com            Addr req1_addr, unsigned int req1_size,
21910259SAndrew.Bardsley@arm.com            Addr req2_addr, unsigned int req2_size);
22010259SAndrew.Bardsley@arm.com
22110259SAndrew.Bardsley@arm.com        /** Does this request's address range fully cover the range
22210259SAndrew.Bardsley@arm.com         *  of other_request? */
22310259SAndrew.Bardsley@arm.com        AddrRangeCoverage containsAddrRangeOf(LSQRequest *other_request);
22410259SAndrew.Bardsley@arm.com
22510259SAndrew.Bardsley@arm.com        /** Start the address translation process for this request.  This
22610259SAndrew.Bardsley@arm.com         *  will issue a translation request to the TLB. */
22710259SAndrew.Bardsley@arm.com        virtual void startAddrTranslation() = 0;
22810259SAndrew.Bardsley@arm.com
22910259SAndrew.Bardsley@arm.com        /** Get the next packet to issue for this request.  For split
23010259SAndrew.Bardsley@arm.com         *  transfers, it will be necessary to step through the available
23110259SAndrew.Bardsley@arm.com         *  packets by calling do { getHeadPacket ; stepToNextPacket } while
23210259SAndrew.Bardsley@arm.com         *  (!sentAllPackets) and by retiring response using retireResponse */
23310259SAndrew.Bardsley@arm.com        virtual PacketPtr getHeadPacket() = 0;
23410259SAndrew.Bardsley@arm.com
23510259SAndrew.Bardsley@arm.com        /** Step to the next packet for the next call to getHeadPacket */
23610259SAndrew.Bardsley@arm.com        virtual void stepToNextPacket() = 0;
23710259SAndrew.Bardsley@arm.com
23810259SAndrew.Bardsley@arm.com        /** Have all packets been sent? */
23910259SAndrew.Bardsley@arm.com        virtual bool sentAllPackets() = 0;
24010259SAndrew.Bardsley@arm.com
24110259SAndrew.Bardsley@arm.com        /** True if this request has any issued packets in the memory
24210259SAndrew.Bardsley@arm.com         *  system and so can't be interrupted until it gets responses */
24310259SAndrew.Bardsley@arm.com        virtual bool hasPacketsInMemSystem() = 0;
24410259SAndrew.Bardsley@arm.com
24510259SAndrew.Bardsley@arm.com        /** Retire a response packet into the LSQRequest packet possibly
24610259SAndrew.Bardsley@arm.com         *  completing this transfer */
24710259SAndrew.Bardsley@arm.com        virtual void retireResponse(PacketPtr packet_) = 0;
24810259SAndrew.Bardsley@arm.com
24910259SAndrew.Bardsley@arm.com        /** Is this a request a barrier? */
25010259SAndrew.Bardsley@arm.com        virtual bool isBarrier();
25110259SAndrew.Bardsley@arm.com
25210259SAndrew.Bardsley@arm.com        /** This request, once processed by the requests/transfers
25310259SAndrew.Bardsley@arm.com         *  queues, will need to go to the store buffer */
25410259SAndrew.Bardsley@arm.com        bool needsToBeSentToStoreBuffer();
25510259SAndrew.Bardsley@arm.com
25610259SAndrew.Bardsley@arm.com        /** Set state and output trace output */
25710259SAndrew.Bardsley@arm.com        void setState(LSQRequestState new_state);
25810259SAndrew.Bardsley@arm.com
25910259SAndrew.Bardsley@arm.com        /** Has this request been completed.  This includes *all* reasons
26010259SAndrew.Bardsley@arm.com         *  for completion: successful transfers, faults, skipped because
26110259SAndrew.Bardsley@arm.com         *  of preceding faults */
26210259SAndrew.Bardsley@arm.com        bool isComplete() const;
26310259SAndrew.Bardsley@arm.com
26410259SAndrew.Bardsley@arm.com        /** MinorTrace report interface */
26510259SAndrew.Bardsley@arm.com        void reportData(std::ostream &os) const;
26610259SAndrew.Bardsley@arm.com    };
26710259SAndrew.Bardsley@arm.com
26810259SAndrew.Bardsley@arm.com    typedef LSQRequest *LSQRequestPtr;
26910259SAndrew.Bardsley@arm.com
27010259SAndrew.Bardsley@arm.com    friend std::ostream & operator <<(std::ostream &os,
27110259SAndrew.Bardsley@arm.com        AddrRangeCoverage state);
27210259SAndrew.Bardsley@arm.com
27310259SAndrew.Bardsley@arm.com    friend std::ostream & operator <<(std::ostream &os,
27410259SAndrew.Bardsley@arm.com        LSQRequest::LSQRequestState state);
27510259SAndrew.Bardsley@arm.com
27610259SAndrew.Bardsley@arm.com  protected:
27710259SAndrew.Bardsley@arm.com    /** Special request types that don't actually issue memory requests */
27810259SAndrew.Bardsley@arm.com    class SpecialDataRequest : public LSQRequest
27910259SAndrew.Bardsley@arm.com    {
28010259SAndrew.Bardsley@arm.com      protected:
28110259SAndrew.Bardsley@arm.com        /** TLB interace */
28212749Sgiacomo.travaglini@arm.com        void finish(const Fault &fault_, const RequestPtr &request_,
28310379Sandreas.hansson@arm.com                    ThreadContext *tc, BaseTLB::Mode mode)
28410259SAndrew.Bardsley@arm.com        { }
28510259SAndrew.Bardsley@arm.com
28610259SAndrew.Bardsley@arm.com      public:
28710259SAndrew.Bardsley@arm.com        /** Send single translation request */
28810259SAndrew.Bardsley@arm.com        void startAddrTranslation() { }
28910259SAndrew.Bardsley@arm.com
29010259SAndrew.Bardsley@arm.com        /** Get the head packet as counted by numIssuedFragments */
29110259SAndrew.Bardsley@arm.com        PacketPtr getHeadPacket()
29210259SAndrew.Bardsley@arm.com        { fatal("No packets in a SpecialDataRequest"); }
29310259SAndrew.Bardsley@arm.com
29410259SAndrew.Bardsley@arm.com        /** Step on numIssuedFragments */
29510259SAndrew.Bardsley@arm.com        void stepToNextPacket() { }
29610259SAndrew.Bardsley@arm.com
29710259SAndrew.Bardsley@arm.com        /** Has no packets to send */
29810259SAndrew.Bardsley@arm.com        bool sentAllPackets() { return true; }
29910259SAndrew.Bardsley@arm.com
30010259SAndrew.Bardsley@arm.com        /** Never sends any requests */
30110259SAndrew.Bardsley@arm.com        bool hasPacketsInMemSystem() { return false; }
30210259SAndrew.Bardsley@arm.com
30310259SAndrew.Bardsley@arm.com        /** Keep the given packet as the response packet
30410259SAndrew.Bardsley@arm.com         *  LSQRequest::packet */
30510259SAndrew.Bardsley@arm.com        void retireResponse(PacketPtr packet_) { }
30610259SAndrew.Bardsley@arm.com
30710259SAndrew.Bardsley@arm.com      public:
30810259SAndrew.Bardsley@arm.com        SpecialDataRequest(LSQ &port_, MinorDynInstPtr inst_) :
30910259SAndrew.Bardsley@arm.com            /* Say this is a load, not actually relevant */
31010259SAndrew.Bardsley@arm.com            LSQRequest(port_, inst_, true, NULL, 0)
31110259SAndrew.Bardsley@arm.com        { }
31210259SAndrew.Bardsley@arm.com    };
31310259SAndrew.Bardsley@arm.com
31410259SAndrew.Bardsley@arm.com    /** FailedDataRequest represents requests from instructions that
31510259SAndrew.Bardsley@arm.com     *  failed their predicates but need to ride the requests/transfers
31610259SAndrew.Bardsley@arm.com     *  queues to maintain trace ordering */
31710259SAndrew.Bardsley@arm.com    class FailedDataRequest : public SpecialDataRequest
31810259SAndrew.Bardsley@arm.com    {
31910259SAndrew.Bardsley@arm.com      public:
32010259SAndrew.Bardsley@arm.com        FailedDataRequest(LSQ &port_, MinorDynInstPtr inst_) :
32110259SAndrew.Bardsley@arm.com            SpecialDataRequest(port_, inst_)
32210259SAndrew.Bardsley@arm.com        { state = Failed; }
32310259SAndrew.Bardsley@arm.com    };
32410259SAndrew.Bardsley@arm.com
32510259SAndrew.Bardsley@arm.com    /** Request for doing barrier accounting in the store buffer.  Not
32610259SAndrew.Bardsley@arm.com     *  for use outside that unit */
32710259SAndrew.Bardsley@arm.com    class BarrierDataRequest : public SpecialDataRequest
32810259SAndrew.Bardsley@arm.com    {
32910259SAndrew.Bardsley@arm.com      public:
33010259SAndrew.Bardsley@arm.com        bool isBarrier() { return true; }
33110259SAndrew.Bardsley@arm.com
33210259SAndrew.Bardsley@arm.com      public:
33310259SAndrew.Bardsley@arm.com        BarrierDataRequest(LSQ &port_, MinorDynInstPtr inst_) :
33410259SAndrew.Bardsley@arm.com            SpecialDataRequest(port_, inst_)
33510259SAndrew.Bardsley@arm.com        { state = Complete; }
33610259SAndrew.Bardsley@arm.com    };
33710259SAndrew.Bardsley@arm.com
33810259SAndrew.Bardsley@arm.com    /** SingleDataRequest is used for requests that don't fragment */
33910259SAndrew.Bardsley@arm.com    class SingleDataRequest : public LSQRequest
34010259SAndrew.Bardsley@arm.com    {
34110259SAndrew.Bardsley@arm.com      protected:
34210259SAndrew.Bardsley@arm.com        /** TLB interace */
34312749Sgiacomo.travaglini@arm.com        void finish(const Fault &fault_, const RequestPtr &request_,
34410379Sandreas.hansson@arm.com                    ThreadContext *tc, BaseTLB::Mode mode);
34510259SAndrew.Bardsley@arm.com
34610259SAndrew.Bardsley@arm.com        /** Has my only packet been sent to the memory system but has not
34710259SAndrew.Bardsley@arm.com         *  yet been responded to */
34810259SAndrew.Bardsley@arm.com        bool packetInFlight;
34910259SAndrew.Bardsley@arm.com
35010259SAndrew.Bardsley@arm.com        /** Has the packet been at least sent to the memory system? */
35110259SAndrew.Bardsley@arm.com        bool packetSent;
35210259SAndrew.Bardsley@arm.com
35310259SAndrew.Bardsley@arm.com      public:
35410259SAndrew.Bardsley@arm.com        /** Send single translation request */
35510259SAndrew.Bardsley@arm.com        void startAddrTranslation();
35610259SAndrew.Bardsley@arm.com
35710259SAndrew.Bardsley@arm.com        /** Get the head packet as counted by numIssuedFragments */
35810259SAndrew.Bardsley@arm.com        PacketPtr getHeadPacket() { return packet; }
35910259SAndrew.Bardsley@arm.com
36010259SAndrew.Bardsley@arm.com        /** Remember that the packet has been sent */
36110259SAndrew.Bardsley@arm.com        void stepToNextPacket() { packetInFlight = true; packetSent = true; }
36210259SAndrew.Bardsley@arm.com
36310259SAndrew.Bardsley@arm.com        /** Has packet been sent */
36410259SAndrew.Bardsley@arm.com        bool hasPacketsInMemSystem() { return packetInFlight; }
36510259SAndrew.Bardsley@arm.com
36610259SAndrew.Bardsley@arm.com        /** packetInFlight can become false again, so need to check
36710259SAndrew.Bardsley@arm.com         *  packetSent */
36810259SAndrew.Bardsley@arm.com        bool sentAllPackets() { return packetSent; }
36910259SAndrew.Bardsley@arm.com
37010259SAndrew.Bardsley@arm.com        /** Keep the given packet as the response packet
37110259SAndrew.Bardsley@arm.com         *  LSQRequest::packet */
37210259SAndrew.Bardsley@arm.com        void retireResponse(PacketPtr packet_);
37310259SAndrew.Bardsley@arm.com
37410259SAndrew.Bardsley@arm.com      public:
37510259SAndrew.Bardsley@arm.com        SingleDataRequest(LSQ &port_, MinorDynInstPtr inst_,
37610259SAndrew.Bardsley@arm.com            bool isLoad_, PacketDataPtr data_ = NULL, uint64_t *res_ = NULL) :
37710259SAndrew.Bardsley@arm.com            LSQRequest(port_, inst_, isLoad_, data_, res_),
37810259SAndrew.Bardsley@arm.com            packetInFlight(false),
37910259SAndrew.Bardsley@arm.com            packetSent(false)
38010259SAndrew.Bardsley@arm.com        { }
38110259SAndrew.Bardsley@arm.com    };
38210259SAndrew.Bardsley@arm.com
38310259SAndrew.Bardsley@arm.com    class SplitDataRequest : public LSQRequest
38410259SAndrew.Bardsley@arm.com    {
38510259SAndrew.Bardsley@arm.com      protected:
38610259SAndrew.Bardsley@arm.com        /** Event to step between translations */
38712127Sspwilson2@wisc.edu        EventFunctionWrapper translationEvent;
38810259SAndrew.Bardsley@arm.com      protected:
38910259SAndrew.Bardsley@arm.com        /** Number of fragments this request is split into */
39010259SAndrew.Bardsley@arm.com        unsigned int numFragments;
39110259SAndrew.Bardsley@arm.com
39210259SAndrew.Bardsley@arm.com        /** Number of fragments in the address translation mechanism */
39310259SAndrew.Bardsley@arm.com        unsigned int numInTranslationFragments;
39410259SAndrew.Bardsley@arm.com
39510259SAndrew.Bardsley@arm.com        /** Number of fragments that have completed address translation,
39610259SAndrew.Bardsley@arm.com         *  (numTranslatedFragments + numInTranslationFragments) <=
39710259SAndrew.Bardsley@arm.com         *  numFragments.  When numTranslatedFramgents == numFragments,
39810259SAndrew.Bardsley@arm.com         *  translation is complete */
39910259SAndrew.Bardsley@arm.com        unsigned int numTranslatedFragments;
40010259SAndrew.Bardsley@arm.com
40110259SAndrew.Bardsley@arm.com        /** Number of fragments already issued (<= numFragments) */
40210259SAndrew.Bardsley@arm.com        unsigned int numIssuedFragments;
40310259SAndrew.Bardsley@arm.com
40410259SAndrew.Bardsley@arm.com        /** Number of fragments retired back to this request */
40510259SAndrew.Bardsley@arm.com        unsigned int numRetiredFragments;
40610259SAndrew.Bardsley@arm.com
40710259SAndrew.Bardsley@arm.com        /** Fragment Requests corresponding to the address ranges of
40810259SAndrew.Bardsley@arm.com         *  each fragment */
40912748Sgiacomo.travaglini@arm.com        std::vector<RequestPtr> fragmentRequests;
41010259SAndrew.Bardsley@arm.com
41110259SAndrew.Bardsley@arm.com        /** Packets matching fragmentRequests to issue fragments to memory */
41210259SAndrew.Bardsley@arm.com        std::vector<Packet *> fragmentPackets;
41310259SAndrew.Bardsley@arm.com
41410259SAndrew.Bardsley@arm.com      protected:
41510259SAndrew.Bardsley@arm.com        /** TLB response interface */
41612749Sgiacomo.travaglini@arm.com        void finish(const Fault &fault_, const RequestPtr &request_,
41710379Sandreas.hansson@arm.com                    ThreadContext *tc, BaseTLB::Mode mode);
41810259SAndrew.Bardsley@arm.com
41910259SAndrew.Bardsley@arm.com      public:
42010259SAndrew.Bardsley@arm.com        SplitDataRequest(LSQ &port_, MinorDynInstPtr inst_,
42110259SAndrew.Bardsley@arm.com            bool isLoad_, PacketDataPtr data_ = NULL,
42210259SAndrew.Bardsley@arm.com            uint64_t *res_ = NULL);
42310259SAndrew.Bardsley@arm.com
42410259SAndrew.Bardsley@arm.com        ~SplitDataRequest();
42510259SAndrew.Bardsley@arm.com
42610259SAndrew.Bardsley@arm.com      public:
42710259SAndrew.Bardsley@arm.com        /** Make all the Requests for this transfer's fragments so that those
42810259SAndrew.Bardsley@arm.com         *  requests can be sent for address translation */
42910259SAndrew.Bardsley@arm.com        void makeFragmentRequests();
43010259SAndrew.Bardsley@arm.com
43110259SAndrew.Bardsley@arm.com        /** Make the packets to go with the requests so they can be sent to
43210259SAndrew.Bardsley@arm.com         *  the memory system */
43310259SAndrew.Bardsley@arm.com        void makeFragmentPackets();
43410259SAndrew.Bardsley@arm.com
43510259SAndrew.Bardsley@arm.com        /** Start a loop of do { sendNextFragmentToTranslation ;
43610259SAndrew.Bardsley@arm.com         *  translateTiming ; finish } while (numTranslatedFragments !=
43710259SAndrew.Bardsley@arm.com         *  numFragments) to complete all this requests' fragments' address
43810259SAndrew.Bardsley@arm.com         *  translations */
43910259SAndrew.Bardsley@arm.com        void startAddrTranslation();
44010259SAndrew.Bardsley@arm.com
44110259SAndrew.Bardsley@arm.com        /** Get the head packet as counted by numIssuedFragments */
44210259SAndrew.Bardsley@arm.com        PacketPtr getHeadPacket();
44310259SAndrew.Bardsley@arm.com
44410259SAndrew.Bardsley@arm.com        /** Step on numIssuedFragments */
44510259SAndrew.Bardsley@arm.com        void stepToNextPacket();
44610259SAndrew.Bardsley@arm.com
44710259SAndrew.Bardsley@arm.com        bool hasPacketsInMemSystem()
44810259SAndrew.Bardsley@arm.com        { return numIssuedFragments != numRetiredFragments; }
44910259SAndrew.Bardsley@arm.com
45010259SAndrew.Bardsley@arm.com        /** Have we stepped past the end of fragmentPackets? */
45113954Sgiacomo.gabrielli@arm.com        bool sentAllPackets()
45213954Sgiacomo.gabrielli@arm.com        { return numIssuedFragments == numTranslatedFragments; }
45310259SAndrew.Bardsley@arm.com
45410259SAndrew.Bardsley@arm.com        /** For loads, paste the response data into the main
45510259SAndrew.Bardsley@arm.com         *  response packet */
45610259SAndrew.Bardsley@arm.com        void retireResponse(PacketPtr packet_);
45710259SAndrew.Bardsley@arm.com
45810259SAndrew.Bardsley@arm.com        /** Part of the address translation loop, see startAddTranslation */
45910259SAndrew.Bardsley@arm.com        void sendNextFragmentToTranslation();
46010259SAndrew.Bardsley@arm.com    };
46110259SAndrew.Bardsley@arm.com
46210259SAndrew.Bardsley@arm.com    /** Store buffer.  This contains stores which have been committed
46310259SAndrew.Bardsley@arm.com     *  but whose memory transfers have not yet been issued. Load data
46410259SAndrew.Bardsley@arm.com     *  can be forwarded out of the store buffer */
46510259SAndrew.Bardsley@arm.com    class StoreBuffer : public Named
46610259SAndrew.Bardsley@arm.com    {
46710259SAndrew.Bardsley@arm.com      public:
46810259SAndrew.Bardsley@arm.com        /** My owner */
46910259SAndrew.Bardsley@arm.com        LSQ &lsq;
47010259SAndrew.Bardsley@arm.com
47110259SAndrew.Bardsley@arm.com        /** Number of slots, this is a bound on the size of slots */
47210259SAndrew.Bardsley@arm.com        const unsigned int numSlots;
47310259SAndrew.Bardsley@arm.com
47410259SAndrew.Bardsley@arm.com        /** Maximum number of stores that can be issued per cycle */
47510259SAndrew.Bardsley@arm.com        const unsigned int storeLimitPerCycle;
47610259SAndrew.Bardsley@arm.com
47710259SAndrew.Bardsley@arm.com      public:
47810259SAndrew.Bardsley@arm.com        /** Queue of store requests on their way to memory */
47910259SAndrew.Bardsley@arm.com        std::deque<LSQRequestPtr> slots;
48010259SAndrew.Bardsley@arm.com
48110259SAndrew.Bardsley@arm.com        /** Number of occupied slots which have not yet issued a
48210259SAndrew.Bardsley@arm.com         *  memory access */
48310259SAndrew.Bardsley@arm.com        unsigned int numUnissuedAccesses;
48410259SAndrew.Bardsley@arm.com
48510259SAndrew.Bardsley@arm.com      public:
48610259SAndrew.Bardsley@arm.com        StoreBuffer(std::string name_, LSQ &lsq_,
48710259SAndrew.Bardsley@arm.com            unsigned int store_buffer_size,
48810259SAndrew.Bardsley@arm.com            unsigned int store_limit_per_cycle);
48910259SAndrew.Bardsley@arm.com
49010259SAndrew.Bardsley@arm.com      public:
49110259SAndrew.Bardsley@arm.com        /** Can a new request be inserted into the queue? */
49210259SAndrew.Bardsley@arm.com        bool canInsert() const;
49310259SAndrew.Bardsley@arm.com
49410259SAndrew.Bardsley@arm.com        /** Delete the given request and free the slot it occupied */
49510259SAndrew.Bardsley@arm.com        void deleteRequest(LSQRequestPtr request);
49610259SAndrew.Bardsley@arm.com
49710259SAndrew.Bardsley@arm.com        /** Insert a request at the back of the queue */
49810259SAndrew.Bardsley@arm.com        void insert(LSQRequestPtr request);
49910259SAndrew.Bardsley@arm.com
50010259SAndrew.Bardsley@arm.com        /** Look for a store which satisfies the given load.  Returns an
50110259SAndrew.Bardsley@arm.com         *  indication whether the forwarding request can be wholly,
50210259SAndrew.Bardsley@arm.com         *  partly or not all all satisfied.  If the request can be
50310259SAndrew.Bardsley@arm.com         *  wholly satisfied, the store buffer slot number which can be used
50410259SAndrew.Bardsley@arm.com         *  is returned in found_slot */
50510259SAndrew.Bardsley@arm.com        AddrRangeCoverage canForwardDataToLoad(LSQRequestPtr request,
50610259SAndrew.Bardsley@arm.com            unsigned int &found_slot);
50710259SAndrew.Bardsley@arm.com
50810259SAndrew.Bardsley@arm.com        /** Fill the given packet with appropriate date from slot
50910259SAndrew.Bardsley@arm.com         *  slot_number */
51010259SAndrew.Bardsley@arm.com        void forwardStoreData(LSQRequestPtr load, unsigned int slot_number);
51110259SAndrew.Bardsley@arm.com
51210259SAndrew.Bardsley@arm.com        /** Number of stores in the store buffer which have not been
51310259SAndrew.Bardsley@arm.com         *  completely issued to the memory system */
51410259SAndrew.Bardsley@arm.com        unsigned int numUnissuedStores() { return numUnissuedAccesses; }
51510259SAndrew.Bardsley@arm.com
51610581SAndrew.Bardsley@arm.com        /** Count a store being issued to memory by decrementing
51710581SAndrew.Bardsley@arm.com         *  numUnissuedAccesses.  Does not count barrier requests as they
51810581SAndrew.Bardsley@arm.com         *  will be handles as barriers are cleared from the buffer */
51910581SAndrew.Bardsley@arm.com        void countIssuedStore(LSQRequestPtr request);
52010581SAndrew.Bardsley@arm.com
52110259SAndrew.Bardsley@arm.com        /** Drained if there is absolutely nothing left in the buffer */
52210259SAndrew.Bardsley@arm.com        bool isDrained() const { return slots.empty(); }
52310259SAndrew.Bardsley@arm.com
52410259SAndrew.Bardsley@arm.com        /** Try to issue more stores to memory */
52510259SAndrew.Bardsley@arm.com        void step();
52610259SAndrew.Bardsley@arm.com
52710259SAndrew.Bardsley@arm.com        /** Report queue contents for MinorTrace */
52810259SAndrew.Bardsley@arm.com        void minorTrace() const;
52910259SAndrew.Bardsley@arm.com    };
53010259SAndrew.Bardsley@arm.com
53110259SAndrew.Bardsley@arm.com  protected:
53210259SAndrew.Bardsley@arm.com    /** Most recent execSeqNum of a memory barrier instruction or
53310259SAndrew.Bardsley@arm.com     *  0 if there are no in-flight barriers.  Useful as a
53410259SAndrew.Bardsley@arm.com     *  dependency for early-issued memory operations */
53511567Smitch.hayenga@arm.com    std::vector<InstSeqNum> lastMemBarrier;
53610259SAndrew.Bardsley@arm.com
53710259SAndrew.Bardsley@arm.com  public:
53810259SAndrew.Bardsley@arm.com    /** Retry state of last issued memory transfer */
53910259SAndrew.Bardsley@arm.com    MemoryState state;
54010259SAndrew.Bardsley@arm.com
54110259SAndrew.Bardsley@arm.com    /** Maximum number of in-flight accesses issued to the memory system */
54210259SAndrew.Bardsley@arm.com    const unsigned int inMemorySystemLimit;
54310259SAndrew.Bardsley@arm.com
54410259SAndrew.Bardsley@arm.com    /** Memory system access width (and snap) in bytes */
54510259SAndrew.Bardsley@arm.com    const unsigned int lineWidth;
54610259SAndrew.Bardsley@arm.com
54710259SAndrew.Bardsley@arm.com  public:
54810259SAndrew.Bardsley@arm.com    /** The LSQ consists of three queues: requests, transfers and the
54910259SAndrew.Bardsley@arm.com     *  store buffer storeBuffer. */
55010259SAndrew.Bardsley@arm.com
55110259SAndrew.Bardsley@arm.com    typedef Queue<LSQRequestPtr,
55210259SAndrew.Bardsley@arm.com        ReportTraitsPtrAdaptor<LSQRequestPtr>,
55310259SAndrew.Bardsley@arm.com        NoBubbleTraits<LSQRequestPtr> >
55410259SAndrew.Bardsley@arm.com        LSQQueue;
55510259SAndrew.Bardsley@arm.com
55610259SAndrew.Bardsley@arm.com    /** requests contains LSQRequests which have been issued to the TLB by
55710259SAndrew.Bardsley@arm.com     *  calling ExecContext::readMem/writeMem (which in turn calls
55810259SAndrew.Bardsley@arm.com     *  LSQ::pushRequest and LSQRequest::startAddrTranslation).  Once they
55910259SAndrew.Bardsley@arm.com     *  have a physical address, requests at the head of requests can be
56010259SAndrew.Bardsley@arm.com     *  issued to the memory system.  At this stage, it cannot be clear that
56110259SAndrew.Bardsley@arm.com     *  memory accesses *must* happen (that there are no preceding faults or
56210259SAndrew.Bardsley@arm.com     *  changes of flow of control) and so only cacheable reads are issued
56310259SAndrew.Bardsley@arm.com     *  to memory.
56410259SAndrew.Bardsley@arm.com     *  Cacheable stores are not issued at all (and just pass through
56510259SAndrew.Bardsley@arm.com     *  'transfers' in order) and all other transfers are stalled in requests
56610259SAndrew.Bardsley@arm.com     *  until their corresponding instructions are at the head of the
56710259SAndrew.Bardsley@arm.com     *  inMemInsts instruction queue and have the right streamSeqNum. */
56810259SAndrew.Bardsley@arm.com    LSQQueue requests;
56910259SAndrew.Bardsley@arm.com
57010259SAndrew.Bardsley@arm.com    /** Once issued to memory (or, for stores, just had their
57110259SAndrew.Bardsley@arm.com     *  state changed to StoreToStoreBuffer) LSQRequests pass through
57210259SAndrew.Bardsley@arm.com     *  transfers waiting for memory responses.  At the head of transfers,
57310259SAndrew.Bardsley@arm.com     *  Execute::commitInst can pick up the memory response for a request
57410259SAndrew.Bardsley@arm.com     *  using LSQ::findResponse.  Responses to be committed can then
57510259SAndrew.Bardsley@arm.com     *  have ExecContext::completeAcc on them.  Stores can then be pushed
57610259SAndrew.Bardsley@arm.com     *  into the store buffer.  All other transfers will then be complete. */
57710259SAndrew.Bardsley@arm.com    LSQQueue transfers;
57810259SAndrew.Bardsley@arm.com
57910259SAndrew.Bardsley@arm.com    /* The store buffer contains committed cacheable stores on
58010259SAndrew.Bardsley@arm.com     * their way to memory decoupled from subsequence instruction execution.
58110259SAndrew.Bardsley@arm.com     * Before trying to issue a cacheable read from 'requests' to memory,
58210259SAndrew.Bardsley@arm.com     * the store buffer is checked to see if a previous store contains the
58310259SAndrew.Bardsley@arm.com     * needed data (StoreBuffer::canForwardDataToLoad) which can be
58410259SAndrew.Bardsley@arm.com     * forwarded in lieu of a memory access.  If there are outstanding
58510259SAndrew.Bardsley@arm.com     * stores in the transfers queue, they must be promoted to the store
58610259SAndrew.Bardsley@arm.com     * buffer (and so be commited) before they can be correctly checked
58710259SAndrew.Bardsley@arm.com     * for forwarding. */
58810259SAndrew.Bardsley@arm.com    StoreBuffer storeBuffer;
58910259SAndrew.Bardsley@arm.com
59010259SAndrew.Bardsley@arm.com  protected:
59110259SAndrew.Bardsley@arm.com    /** Count of the number of mem. accesses which have left the
59210368SAndrew.Bardsley@arm.com     *  requests queue and are in the 'wild' in the memory system and who
59310368SAndrew.Bardsley@arm.com     *  *must not* be interrupted as they are not normal cacheable
59410368SAndrew.Bardsley@arm.com     *  accesses.  This is a count of the number of in-flight requests
59510368SAndrew.Bardsley@arm.com     *  with issuedToMemory set who have visited tryToSendRequest at least
59610368SAndrew.Bardsley@arm.com     *  once */
59710259SAndrew.Bardsley@arm.com    unsigned int numAccessesInMemorySystem;
59810259SAndrew.Bardsley@arm.com
59910259SAndrew.Bardsley@arm.com    /** Number of requests in the DTLB in the requests queue */
60010259SAndrew.Bardsley@arm.com    unsigned int numAccessesInDTLB;
60110259SAndrew.Bardsley@arm.com
60210259SAndrew.Bardsley@arm.com    /** The number of stores in the transfers queue.  Useful when
60310259SAndrew.Bardsley@arm.com     *  testing if the store buffer contains all the forwardable stores */
60410259SAndrew.Bardsley@arm.com    unsigned int numStoresInTransfers;
60510259SAndrew.Bardsley@arm.com
60610259SAndrew.Bardsley@arm.com    /** The number of accesses which have been issued to the memory
60710259SAndrew.Bardsley@arm.com     *  system but have not been committed/discarded *excluding*
60810259SAndrew.Bardsley@arm.com     *  cacheable normal loads which don't need to be tracked */
60910259SAndrew.Bardsley@arm.com    unsigned int numAccessesIssuedToMemory;
61010259SAndrew.Bardsley@arm.com
61110259SAndrew.Bardsley@arm.com    /** The request (from either requests or the store buffer) which is
61210259SAndrew.Bardsley@arm.com     *  currently waiting have its memory access retried */
61310259SAndrew.Bardsley@arm.com    LSQRequestPtr retryRequest;
61410259SAndrew.Bardsley@arm.com
61510259SAndrew.Bardsley@arm.com    /** Address Mask for a cache block (e.g. ~(cache_block_size-1)) */
61610259SAndrew.Bardsley@arm.com    Addr cacheBlockMask;
61710259SAndrew.Bardsley@arm.com
61810259SAndrew.Bardsley@arm.com  protected:
61910259SAndrew.Bardsley@arm.com    /** Try and issue a memory access for a translated request at the
62010259SAndrew.Bardsley@arm.com     *  head of the requests queue.  Also tries to move the request
62110259SAndrew.Bardsley@arm.com     *  between queues */
62210259SAndrew.Bardsley@arm.com    void tryToSendToTransfers(LSQRequestPtr request);
62310259SAndrew.Bardsley@arm.com
62410259SAndrew.Bardsley@arm.com    /** Try to send (or resend) a memory request's next/only packet to
62510259SAndrew.Bardsley@arm.com     *  the memory system.  Returns true if the request was successfully
62610259SAndrew.Bardsley@arm.com     *  sent to memory (and was also the last packet in a transfer) */
62710259SAndrew.Bardsley@arm.com    bool tryToSend(LSQRequestPtr request);
62810259SAndrew.Bardsley@arm.com
62910259SAndrew.Bardsley@arm.com    /** Clear a barrier (if it's the last one marked up in lastMemBarrier) */
63010259SAndrew.Bardsley@arm.com    void clearMemBarrier(MinorDynInstPtr inst);
63110259SAndrew.Bardsley@arm.com
63210259SAndrew.Bardsley@arm.com    /** Move a request between queues */
63310259SAndrew.Bardsley@arm.com    void moveFromRequestsToTransfers(LSQRequestPtr request);
63410259SAndrew.Bardsley@arm.com
63510259SAndrew.Bardsley@arm.com    /** Can a request be sent to the memory system */
63610259SAndrew.Bardsley@arm.com    bool canSendToMemorySystem();
63710259SAndrew.Bardsley@arm.com
63811567Smitch.hayenga@arm.com    /** Snoop other threads monitors on memory system accesses */
63911567Smitch.hayenga@arm.com    void threadSnoop(LSQRequestPtr request);
64011567Smitch.hayenga@arm.com
64110259SAndrew.Bardsley@arm.com  public:
64210259SAndrew.Bardsley@arm.com    LSQ(std::string name_, std::string dcache_port_name_,
64310259SAndrew.Bardsley@arm.com        MinorCPU &cpu_, Execute &execute_,
64410259SAndrew.Bardsley@arm.com        unsigned int max_accesses_in_memory_system, unsigned int line_width,
64510259SAndrew.Bardsley@arm.com        unsigned int requests_queue_size, unsigned int transfers_queue_size,
64610259SAndrew.Bardsley@arm.com        unsigned int store_buffer_size,
64710259SAndrew.Bardsley@arm.com        unsigned int store_buffer_cycle_store_limit);
64810259SAndrew.Bardsley@arm.com
64910259SAndrew.Bardsley@arm.com    virtual ~LSQ();
65010259SAndrew.Bardsley@arm.com
65110259SAndrew.Bardsley@arm.com  public:
65210259SAndrew.Bardsley@arm.com    /** Step checks the queues to see if their are issuable transfers
65310259SAndrew.Bardsley@arm.com     *  which were not otherwise picked up by tests at the end of other
65410259SAndrew.Bardsley@arm.com     *  events.
65510259SAndrew.Bardsley@arm.com     *
65610259SAndrew.Bardsley@arm.com     *  Steppable actions include deferred actions which couldn't be
65710259SAndrew.Bardsley@arm.com     *  cascaded on the end of a memory response/TLB response event
65810259SAndrew.Bardsley@arm.com     *  because of resource congestion. */
65910259SAndrew.Bardsley@arm.com    void step();
66010259SAndrew.Bardsley@arm.com
66110259SAndrew.Bardsley@arm.com    /** Is their space in the request queue to be able to push a request by
66210259SAndrew.Bardsley@arm.com     *  issuing an isMemRef instruction */
66310259SAndrew.Bardsley@arm.com    bool canRequest() { return requests.unreservedRemainingSpace() != 0; }
66410259SAndrew.Bardsley@arm.com
66510259SAndrew.Bardsley@arm.com    /** Returns a response if it's at the head of the transfers queue and
66610259SAndrew.Bardsley@arm.com     *  it's either complete or can be sent on to the store buffer.  After
66710259SAndrew.Bardsley@arm.com     *  calling, the request still remains on the transfer queue until
66810259SAndrew.Bardsley@arm.com     *  popResponse is called */
66910259SAndrew.Bardsley@arm.com    LSQRequestPtr findResponse(MinorDynInstPtr inst);
67010259SAndrew.Bardsley@arm.com
67110259SAndrew.Bardsley@arm.com    /** Sanity check and pop the head response */
67210259SAndrew.Bardsley@arm.com    void popResponse(LSQRequestPtr response);
67310259SAndrew.Bardsley@arm.com
67410259SAndrew.Bardsley@arm.com    /** Must check this before trying to insert into the store buffer */
67510259SAndrew.Bardsley@arm.com    bool canPushIntoStoreBuffer() const { return storeBuffer.canInsert(); }
67610259SAndrew.Bardsley@arm.com
67710259SAndrew.Bardsley@arm.com    /** A store has been committed, please move it to the store buffer */
67810259SAndrew.Bardsley@arm.com    void sendStoreToStoreBuffer(LSQRequestPtr request);
67910259SAndrew.Bardsley@arm.com
68010259SAndrew.Bardsley@arm.com    /** Are there any accesses other than normal cached loads in the
68110259SAndrew.Bardsley@arm.com     *  memory system or having received responses which need to be
68210259SAndrew.Bardsley@arm.com     *  handled for their instruction's to be completed */
68310259SAndrew.Bardsley@arm.com    bool accessesInFlight() const
68410259SAndrew.Bardsley@arm.com    { return numAccessesIssuedToMemory != 0; }
68510259SAndrew.Bardsley@arm.com
68610259SAndrew.Bardsley@arm.com    /** A memory barrier instruction has been issued, remember its
68710259SAndrew.Bardsley@arm.com     *  execSeqNum that we can avoid issuing memory ops until it is
68810259SAndrew.Bardsley@arm.com     *  committed */
68910259SAndrew.Bardsley@arm.com    void issuedMemBarrierInst(MinorDynInstPtr inst);
69010259SAndrew.Bardsley@arm.com
69110259SAndrew.Bardsley@arm.com    /** Get the execSeqNum of the last issued memory barrier */
69211567Smitch.hayenga@arm.com    InstSeqNum getLastMemBarrier(ThreadID thread_id) const
69311567Smitch.hayenga@arm.com    { return lastMemBarrier[thread_id]; }
69410259SAndrew.Bardsley@arm.com
69510259SAndrew.Bardsley@arm.com    /** Is there nothing left in the LSQ */
69610259SAndrew.Bardsley@arm.com    bool isDrained();
69710259SAndrew.Bardsley@arm.com
69810259SAndrew.Bardsley@arm.com    /** May need to be ticked next cycle as one of the queues contains
69910259SAndrew.Bardsley@arm.com     *  an actionable transfers or address translation */
70010259SAndrew.Bardsley@arm.com    bool needsToTick();
70110259SAndrew.Bardsley@arm.com
70210259SAndrew.Bardsley@arm.com    /** Complete a barrier instruction.  Where committed, makes a
70310259SAndrew.Bardsley@arm.com     *  BarrierDataRequest and pushed it into the store buffer */
70410259SAndrew.Bardsley@arm.com    void completeMemBarrierInst(MinorDynInstPtr inst,
70510259SAndrew.Bardsley@arm.com        bool committed);
70610259SAndrew.Bardsley@arm.com
70713652Sqtt2@cornell.edu    /** Single interface for readMem/writeMem/amoMem to issue requests into
70810259SAndrew.Bardsley@arm.com     *  the LSQ */
70914105Sgabor.dozsa@arm.com    Fault pushRequest(MinorDynInstPtr inst, bool isLoad, uint8_t *data,
71014105Sgabor.dozsa@arm.com                      unsigned int size, Addr addr, Request::Flags flags,
71114297Sjordi.vaquero@metempsy.com                      uint64_t *res, AtomicOpFunctorPtr amo_op,
71214105Sgabor.dozsa@arm.com                      const std::vector<bool>& byteEnable =
71314105Sgabor.dozsa@arm.com                          std::vector<bool>());
71410259SAndrew.Bardsley@arm.com
71510259SAndrew.Bardsley@arm.com    /** Push a predicate failed-representing request into the queues just
71610259SAndrew.Bardsley@arm.com     *  to maintain commit order */
71710259SAndrew.Bardsley@arm.com    void pushFailedRequest(MinorDynInstPtr inst);
71810259SAndrew.Bardsley@arm.com
71910259SAndrew.Bardsley@arm.com    /** Memory interface */
72010259SAndrew.Bardsley@arm.com    bool recvTimingResp(PacketPtr pkt);
72110713Sandreas.hansson@arm.com    void recvReqRetry();
72210259SAndrew.Bardsley@arm.com    void recvTimingSnoopReq(PacketPtr pkt);
72310259SAndrew.Bardsley@arm.com
72410259SAndrew.Bardsley@arm.com    /** Return the raw-bindable port */
72510259SAndrew.Bardsley@arm.com    MinorCPU::MinorCPUPort &getDcachePort() { return dcachePort; }
72610259SAndrew.Bardsley@arm.com
72710259SAndrew.Bardsley@arm.com    void minorTrace() const;
72810259SAndrew.Bardsley@arm.com};
72910259SAndrew.Bardsley@arm.com
73010259SAndrew.Bardsley@arm.com/** Make a suitable packet for the given request.  If the request is a store,
73110259SAndrew.Bardsley@arm.com *  data will be the payload data.  If sender_state is NULL, it won't be
73210259SAndrew.Bardsley@arm.com *  pushed into the packet as senderState */
73312749Sgiacomo.travaglini@arm.comPacketPtr makePacketForRequest(const RequestPtr &request, bool isLoad,
73410259SAndrew.Bardsley@arm.com    Packet::SenderState *sender_state = NULL, PacketDataPtr data = NULL);
73510259SAndrew.Bardsley@arm.com}
73610259SAndrew.Bardsley@arm.com
73710259SAndrew.Bardsley@arm.com#endif /* __CPU_MINOR_NEW_LSQ_HH__ */
738