lsq.hh revision 10379
11758Ssaidi@eecs.umich.edu/*
21758Ssaidi@eecs.umich.edu * Copyright (c) 2013-2014 ARM Limited
31758Ssaidi@eecs.umich.edu * All rights reserved
41758Ssaidi@eecs.umich.edu *
51758Ssaidi@eecs.umich.edu * The license below extends only to copyright in the software and shall
61758Ssaidi@eecs.umich.edu * not be construed as granting a license to any other intellectual
71758Ssaidi@eecs.umich.edu * property including but not limited to intellectual property relating
81758Ssaidi@eecs.umich.edu * to a hardware implementation of the functionality of the software
91758Ssaidi@eecs.umich.edu * licensed hereunder.  You may use the software subject to the license
101758Ssaidi@eecs.umich.edu * terms below provided that you ensure that this notice is replicated
111758Ssaidi@eecs.umich.edu * unmodified and in its entirety in all distributions of the software,
121758Ssaidi@eecs.umich.edu * modified or unmodified, in source code or in binary form.
131758Ssaidi@eecs.umich.edu *
141758Ssaidi@eecs.umich.edu * Redistribution and use in source and binary forms, with or without
151758Ssaidi@eecs.umich.edu * modification, are permitted provided that the following conditions are
161758Ssaidi@eecs.umich.edu * met: redistributions of source code must retain the above copyright
171758Ssaidi@eecs.umich.edu * notice, this list of conditions and the following disclaimer;
181758Ssaidi@eecs.umich.edu * redistributions in binary form must reproduce the above copyright
191758Ssaidi@eecs.umich.edu * notice, this list of conditions and the following disclaimer in the
201758Ssaidi@eecs.umich.edu * documentation and/or other materials provided with the distribution;
211758Ssaidi@eecs.umich.edu * neither the name of the copyright holders nor the names of its
221758Ssaidi@eecs.umich.edu * contributors may be used to endorse or promote products derived from
231758Ssaidi@eecs.umich.edu * this software without specific prior written permission.
241758Ssaidi@eecs.umich.edu *
251758Ssaidi@eecs.umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
261758Ssaidi@eecs.umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
271049Sbinkertn@umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
281049Sbinkertn@umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
291049Sbinkertn@umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
301049Sbinkertn@umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
311049Sbinkertn@umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
321049Sbinkertn@umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
331049Sbinkertn@umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
341049Sbinkertn@umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
351049Sbinkertn@umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
361049Sbinkertn@umich.edu *
371049Sbinkertn@umich.edu * Authors: Andrew Bardsley
381049Sbinkertn@umich.edu */
391049Sbinkertn@umich.edu
401049Sbinkertn@umich.edu/**
411049Sbinkertn@umich.edu * @file
421049Sbinkertn@umich.edu *
431049Sbinkertn@umich.edu *  A load/store queue that allows outstanding reads and writes.
441049Sbinkertn@umich.edu *
451049Sbinkertn@umich.edu */
461049Sbinkertn@umich.edu
471049Sbinkertn@umich.edu#ifndef __CPU_MINOR_NEW_LSQ_HH__
481049Sbinkertn@umich.edu#define __CPU_MINOR_NEW_LSQ_HH__
491049Sbinkertn@umich.edu
501049Sbinkertn@umich.edu#include "cpu/minor/buffers.hh"
511049Sbinkertn@umich.edu#include "cpu/minor/cpu.hh"
521049Sbinkertn@umich.edu#include "cpu/minor/pipe_data.hh"
531049Sbinkertn@umich.edu#include "cpu/minor/trace.hh"
541049Sbinkertn@umich.edu
551049Sbinkertn@umich.edunamespace Minor
561049Sbinkertn@umich.edu{
571049Sbinkertn@umich.edu
581049Sbinkertn@umich.edu/* Forward declaration */
591049Sbinkertn@umich.educlass Execute;
601049Sbinkertn@umich.edu
611049Sbinkertn@umich.educlass LSQ : public Named
621049Sbinkertn@umich.edu{
631049Sbinkertn@umich.edu  protected:
641049Sbinkertn@umich.edu    /** My owner(s) */
651049Sbinkertn@umich.edu    MinorCPU &cpu;
661049Sbinkertn@umich.edu    Execute &execute;
671049Sbinkertn@umich.edu
681049Sbinkertn@umich.edu  protected:
691049Sbinkertn@umich.edu    /** State of memory access for head access. */
701049Sbinkertn@umich.edu    enum MemoryState
711049Sbinkertn@umich.edu    {
721049Sbinkertn@umich.edu        MemoryRunning, /* Default. Step dcache queues when possible. */
731049Sbinkertn@umich.edu        MemoryNeedsRetry /* Request rejected, will be asked to retry */
741049Sbinkertn@umich.edu    };
751049Sbinkertn@umich.edu
761049Sbinkertn@umich.edu    /** Print MemoryState values as shown in the enum definition */
771049Sbinkertn@umich.edu    friend std::ostream &operator <<(std::ostream &os,
781049Sbinkertn@umich.edu        MemoryState state);
791049Sbinkertn@umich.edu
801049Sbinkertn@umich.edu    /** Coverage of one address range with another */
811049Sbinkertn@umich.edu    enum AddrRangeCoverage
821049Sbinkertn@umich.edu    {
831049Sbinkertn@umich.edu        PartialAddrRangeCoverage, /* Two ranges partly overlap */
841049Sbinkertn@umich.edu        FullAddrRangeCoverage, /* One range fully covers another */
851049Sbinkertn@umich.edu        NoAddrRangeCoverage /* Two ranges are disjoint */
861049Sbinkertn@umich.edu    };
871049Sbinkertn@umich.edu
881049Sbinkertn@umich.edu    /** Exposable data port */
891049Sbinkertn@umich.edu    class DcachePort : public MinorCPU::MinorCPUPort
901049Sbinkertn@umich.edu    {
911049Sbinkertn@umich.edu      protected:
921049Sbinkertn@umich.edu        /** My owner */
931049Sbinkertn@umich.edu        LSQ &lsq;
941049Sbinkertn@umich.edu
951049Sbinkertn@umich.edu      public:
961049Sbinkertn@umich.edu        DcachePort(std::string name, LSQ &lsq_, MinorCPU &cpu) :
971049Sbinkertn@umich.edu            MinorCPU::MinorCPUPort(name, cpu), lsq(lsq_)
981049Sbinkertn@umich.edu        { }
991049Sbinkertn@umich.edu
1001049Sbinkertn@umich.edu      protected:
1011049Sbinkertn@umich.edu        bool recvTimingResp(PacketPtr pkt)
1021049Sbinkertn@umich.edu        { return lsq.recvTimingResp(pkt); }
1031049Sbinkertn@umich.edu
1041881Sbinkertn@umich.edu        void recvRetry() { lsq.recvRetry(); }
1051049Sbinkertn@umich.edu
1061929Sbinkertn@umich.edu        void recvTimingSnoopReq(PacketPtr pkt)
1071929Sbinkertn@umich.edu        { return lsq.recvTimingSnoopReq(pkt); }
1081929Sbinkertn@umich.edu    };
1091929Sbinkertn@umich.edu
1101929Sbinkertn@umich.edu    DcachePort dcachePort;
1111929Sbinkertn@umich.edu
1121929Sbinkertn@umich.edu  public:
1131929Sbinkertn@umich.edu    /** Derived SenderState to carry data access info. through address
1141929Sbinkertn@umich.edu     *  translation, the queues in this port and back from the memory
1151929Sbinkertn@umich.edu     *  system. */
1161929Sbinkertn@umich.edu    class LSQRequest :
1171929Sbinkertn@umich.edu        public BaseTLB::Translation, /* For TLB lookups */
1181929Sbinkertn@umich.edu        public Packet::SenderState /* For packing into a Packet */
1191929Sbinkertn@umich.edu    {
1201049Sbinkertn@umich.edu      public:
1211049Sbinkertn@umich.edu        /** Owning port */
1221049Sbinkertn@umich.edu        LSQ &port;
1231049Sbinkertn@umich.edu
1241049Sbinkertn@umich.edu        /** Instruction which made this request */
1251049Sbinkertn@umich.edu        MinorDynInstPtr inst;
1261049Sbinkertn@umich.edu
1271049Sbinkertn@umich.edu        /** Load/store indication used for building packet.  This isn't
1281049Sbinkertn@umich.edu         *  carried by Request so we need to keep it here */
1291049Sbinkertn@umich.edu        bool isLoad;
1301049Sbinkertn@umich.edu
1311049Sbinkertn@umich.edu        /** Dynamically allocated and populated data carried for
1321049Sbinkertn@umich.edu         *  building write packets */
1331049Sbinkertn@umich.edu        PacketDataPtr data;
1341049Sbinkertn@umich.edu
1351049Sbinkertn@umich.edu        /* Requests carry packets on their way to the memory system.
1361049Sbinkertn@umich.edu         *  When a Packet returns from the memory system, its
1371049Sbinkertn@umich.edu         *  request needs to have its packet updated as this
1381049Sbinkertn@umich.edu         *  may have changed in flight */
1391049Sbinkertn@umich.edu        PacketPtr packet;
1401049Sbinkertn@umich.edu
1411049Sbinkertn@umich.edu        /** The underlying request of this LSQRequest */
1421049Sbinkertn@umich.edu        Request request;
1431049Sbinkertn@umich.edu
1441049Sbinkertn@umich.edu        /** Fault generated performing this request */
1451049Sbinkertn@umich.edu        Fault fault;
1461049Sbinkertn@umich.edu
1471049Sbinkertn@umich.edu        /** Res from pushRequest */
1481049Sbinkertn@umich.edu        uint64_t *res;
1491049Sbinkertn@umich.edu
1501049Sbinkertn@umich.edu        /** Was skipped.  Set to indicate any reason (faulted, bad
1511049Sbinkertn@umich.edu         *  stream sequence number, in a fault shadow) that this
1521929Sbinkertn@umich.edu         *  request did not perform a memory transfer */
1531929Sbinkertn@umich.edu        bool skipped;
1541929Sbinkertn@umich.edu
1551929Sbinkertn@umich.edu        /** This in an access other than a normal cacheable load
1561929Sbinkertn@umich.edu         *  that's visited the memory system */
1571929Sbinkertn@umich.edu        bool issuedToMemory;
1581929Sbinkertn@umich.edu
1591929Sbinkertn@umich.edu        enum LSQRequestState
1601929Sbinkertn@umich.edu        {
1611929Sbinkertn@umich.edu            NotIssued, /* Newly created */
1621929Sbinkertn@umich.edu            InTranslation, /* TLB accessed, no reply yet */
1631929Sbinkertn@umich.edu            Translated, /* Finished address translation */
1641929Sbinkertn@umich.edu            Failed, /* The starting start of FailedDataRequests */
1651929Sbinkertn@umich.edu            RequestIssuing, /* Load/store issued to memory in the requests
1661929Sbinkertn@umich.edu                queue */
1671929Sbinkertn@umich.edu            StoreToStoreBuffer, /* Store in transfers on its way to the
1681929Sbinkertn@umich.edu                store buffer */
1691049Sbinkertn@umich.edu            RequestNeedsRetry, /* Retry needed for load */
1701049Sbinkertn@umich.edu            StoreInStoreBuffer, /* Store in the store buffer, before issuing
1711049Sbinkertn@umich.edu                a memory transfer */
1721049Sbinkertn@umich.edu            StoreBufferIssuing, /* Store in store buffer and has been
1731049Sbinkertn@umich.edu                issued */
1741049Sbinkertn@umich.edu            StoreBufferNeedsRetry, /* Retry needed for store */
1751049Sbinkertn@umich.edu            /* All completed states.  Includes
1761049Sbinkertn@umich.edu                completed loads, TLB faults and skipped requests whose
1771049Sbinkertn@umich.edu                seqNum's no longer match */
1781049Sbinkertn@umich.edu            Complete
1791049Sbinkertn@umich.edu        };
1801049Sbinkertn@umich.edu
1811049Sbinkertn@umich.edu        LSQRequestState state;
1821049Sbinkertn@umich.edu
1831049Sbinkertn@umich.edu      protected:
1841049Sbinkertn@umich.edu        /** BaseTLB::Translation interface */
1851049Sbinkertn@umich.edu        void markDelayed() { }
1861049Sbinkertn@umich.edu
1871049Sbinkertn@umich.edu      public:
1881049Sbinkertn@umich.edu        LSQRequest(LSQ &port_, MinorDynInstPtr inst_, bool isLoad_,
1891049Sbinkertn@umich.edu            PacketDataPtr data_ = NULL, uint64_t *res_ = NULL);
1901049Sbinkertn@umich.edu
1911049Sbinkertn@umich.edu        virtual ~LSQRequest();
1921049Sbinkertn@umich.edu
1931049Sbinkertn@umich.edu      public:
1941049Sbinkertn@umich.edu        /** Make a packet to use with the memory transaction */
1951049Sbinkertn@umich.edu        void makePacket();
1961049Sbinkertn@umich.edu
1971049Sbinkertn@umich.edu        /** Was no memory access attempted for this request? */
1981049Sbinkertn@umich.edu        bool skippedMemAccess() { return skipped; }
1991049Sbinkertn@umich.edu
2001049Sbinkertn@umich.edu        /** Set this request as having been skipped before a memory
2011049Sbinkertn@umich.edu         *  transfer was attempt */
2021049Sbinkertn@umich.edu        void setSkipped() { skipped = true; }
2031049Sbinkertn@umich.edu
2041049Sbinkertn@umich.edu        /** Does address range req1 (req1_addr to req1_addr + req1_size - 1)
2051049Sbinkertn@umich.edu         *  fully cover, partially cover or not cover at all the range req2 */
2061049Sbinkertn@umich.edu        static AddrRangeCoverage containsAddrRangeOf(
2071049Sbinkertn@umich.edu            Addr req1_addr, unsigned int req1_size,
2081049Sbinkertn@umich.edu            Addr req2_addr, unsigned int req2_size);
2091049Sbinkertn@umich.edu
2101049Sbinkertn@umich.edu        /** Does this request's address range fully cover the range
2111049Sbinkertn@umich.edu         *  of other_request? */
2121049Sbinkertn@umich.edu        AddrRangeCoverage containsAddrRangeOf(LSQRequest *other_request);
2131049Sbinkertn@umich.edu
2141049Sbinkertn@umich.edu        /** Start the address translation process for this request.  This
2151049Sbinkertn@umich.edu         *  will issue a translation request to the TLB. */
2161049Sbinkertn@umich.edu        virtual void startAddrTranslation() = 0;
2171049Sbinkertn@umich.edu
2181049Sbinkertn@umich.edu        /** Get the next packet to issue for this request.  For split
2191049Sbinkertn@umich.edu         *  transfers, it will be necessary to step through the available
2201049Sbinkertn@umich.edu         *  packets by calling do { getHeadPacket ; stepToNextPacket } while
2211049Sbinkertn@umich.edu         *  (!sentAllPackets) and by retiring response using retireResponse */
2221049Sbinkertn@umich.edu        virtual PacketPtr getHeadPacket() = 0;
2231049Sbinkertn@umich.edu
2241049Sbinkertn@umich.edu        /** Step to the next packet for the next call to getHeadPacket */
2251049Sbinkertn@umich.edu        virtual void stepToNextPacket() = 0;
2261049Sbinkertn@umich.edu
2271049Sbinkertn@umich.edu        /** Have all packets been sent? */
2281049Sbinkertn@umich.edu        virtual bool sentAllPackets() = 0;
2291049Sbinkertn@umich.edu
2301306Sbinkertn@umich.edu        /** True if this request has any issued packets in the memory
2311049Sbinkertn@umich.edu         *  system and so can't be interrupted until it gets responses */
2321049Sbinkertn@umich.edu        virtual bool hasPacketsInMemSystem() = 0;
2331049Sbinkertn@umich.edu
2341049Sbinkertn@umich.edu        /** Retire a response packet into the LSQRequest packet possibly
2351049Sbinkertn@umich.edu         *  completing this transfer */
2361929Sbinkertn@umich.edu        virtual void retireResponse(PacketPtr packet_) = 0;
2371049Sbinkertn@umich.edu
2381049Sbinkertn@umich.edu        /** Is this a request a barrier? */
2391049Sbinkertn@umich.edu        virtual bool isBarrier();
2401049Sbinkertn@umich.edu
2411049Sbinkertn@umich.edu        /** This request, once processed by the requests/transfers
2421049Sbinkertn@umich.edu         *  queues, will need to go to the store buffer */
2431049Sbinkertn@umich.edu        bool needsToBeSentToStoreBuffer();
2441049Sbinkertn@umich.edu
2451049Sbinkertn@umich.edu        /** Set state and output trace output */
2461049Sbinkertn@umich.edu        void setState(LSQRequestState new_state);
2471049Sbinkertn@umich.edu
2481049Sbinkertn@umich.edu        /** Has this request been completed.  This includes *all* reasons
2491049Sbinkertn@umich.edu         *  for completion: successful transfers, faults, skipped because
2501049Sbinkertn@umich.edu         *  of preceding faults */
2511049Sbinkertn@umich.edu        bool isComplete() const;
2521049Sbinkertn@umich.edu
2531049Sbinkertn@umich.edu        /** MinorTrace report interface */
2541049Sbinkertn@umich.edu        void reportData(std::ostream &os) const;
2551049Sbinkertn@umich.edu    };
2561049Sbinkertn@umich.edu
2571049Sbinkertn@umich.edu    typedef LSQRequest *LSQRequestPtr;
2581049Sbinkertn@umich.edu
2591049Sbinkertn@umich.edu    friend std::ostream & operator <<(std::ostream &os,
2601049Sbinkertn@umich.edu        AddrRangeCoverage state);
2611049Sbinkertn@umich.edu
2621049Sbinkertn@umich.edu    friend std::ostream & operator <<(std::ostream &os,
2631049Sbinkertn@umich.edu        LSQRequest::LSQRequestState state);
2641049Sbinkertn@umich.edu
2651049Sbinkertn@umich.edu  protected:
2661309Ssaidi@eecs.umich.edu    /** Special request types that don't actually issue memory requests */
2671049Sbinkertn@umich.edu    class SpecialDataRequest : public LSQRequest
2681049Sbinkertn@umich.edu    {
2691309Ssaidi@eecs.umich.edu      protected:
2701309Ssaidi@eecs.umich.edu        /** TLB interace */
2711309Ssaidi@eecs.umich.edu        void finish(const Fault &fault_, RequestPtr request_,
2721309Ssaidi@eecs.umich.edu                    ThreadContext *tc, BaseTLB::Mode mode)
2731309Ssaidi@eecs.umich.edu        { }
2741309Ssaidi@eecs.umich.edu
2751309Ssaidi@eecs.umich.edu      public:
2761309Ssaidi@eecs.umich.edu        /** Send single translation request */
2771309Ssaidi@eecs.umich.edu        void startAddrTranslation() { }
2781309Ssaidi@eecs.umich.edu
2791309Ssaidi@eecs.umich.edu        /** Get the head packet as counted by numIssuedFragments */
2801049Sbinkertn@umich.edu        PacketPtr getHeadPacket()
2811049Sbinkertn@umich.edu        { fatal("No packets in a SpecialDataRequest"); }
2821049Sbinkertn@umich.edu
2831049Sbinkertn@umich.edu        /** Step on numIssuedFragments */
2841309Ssaidi@eecs.umich.edu        void stepToNextPacket() { }
2851309Ssaidi@eecs.umich.edu
2861309Ssaidi@eecs.umich.edu        /** Has no packets to send */
2871309Ssaidi@eecs.umich.edu        bool sentAllPackets() { return true; }
2881309Ssaidi@eecs.umich.edu
2891309Ssaidi@eecs.umich.edu        /** Never sends any requests */
2901309Ssaidi@eecs.umich.edu        bool hasPacketsInMemSystem() { return false; }
2911309Ssaidi@eecs.umich.edu
2921309Ssaidi@eecs.umich.edu        /** Keep the given packet as the response packet
2931309Ssaidi@eecs.umich.edu         *  LSQRequest::packet */
2941309Ssaidi@eecs.umich.edu        void retireResponse(PacketPtr packet_) { }
2951309Ssaidi@eecs.umich.edu
2961309Ssaidi@eecs.umich.edu      public:
2971309Ssaidi@eecs.umich.edu        SpecialDataRequest(LSQ &port_, MinorDynInstPtr inst_) :
2981309Ssaidi@eecs.umich.edu            /* Say this is a load, not actually relevant */
2991309Ssaidi@eecs.umich.edu            LSQRequest(port_, inst_, true, NULL, 0)
3001309Ssaidi@eecs.umich.edu        { }
3011309Ssaidi@eecs.umich.edu    };
3021309Ssaidi@eecs.umich.edu
3031049Sbinkertn@umich.edu    /** FailedDataRequest represents requests from instructions that
3041049Sbinkertn@umich.edu     *  failed their predicates but need to ride the requests/transfers
3051049Sbinkertn@umich.edu     *  queues to maintain trace ordering */
3061049Sbinkertn@umich.edu    class FailedDataRequest : public SpecialDataRequest
3071049Sbinkertn@umich.edu    {
3081049Sbinkertn@umich.edu      public:
3091049Sbinkertn@umich.edu        FailedDataRequest(LSQ &port_, MinorDynInstPtr inst_) :
3101049Sbinkertn@umich.edu            SpecialDataRequest(port_, inst_)
3111049Sbinkertn@umich.edu        { state = Failed; }
3121049Sbinkertn@umich.edu    };
3131049Sbinkertn@umich.edu
3141049Sbinkertn@umich.edu    /** Request for doing barrier accounting in the store buffer.  Not
3151049Sbinkertn@umich.edu     *  for use outside that unit */
3161049Sbinkertn@umich.edu    class BarrierDataRequest : public SpecialDataRequest
3171049Sbinkertn@umich.edu    {
3181049Sbinkertn@umich.edu      public:
3191049Sbinkertn@umich.edu        bool isBarrier() { return true; }
3201049Sbinkertn@umich.edu
3211049Sbinkertn@umich.edu      public:
3221049Sbinkertn@umich.edu        BarrierDataRequest(LSQ &port_, MinorDynInstPtr inst_) :
3231049Sbinkertn@umich.edu            SpecialDataRequest(port_, inst_)
3241049Sbinkertn@umich.edu        { state = Complete; }
3251049Sbinkertn@umich.edu    };
3261049Sbinkertn@umich.edu
3271049Sbinkertn@umich.edu    /** SingleDataRequest is used for requests that don't fragment */
3281049Sbinkertn@umich.edu    class SingleDataRequest : public LSQRequest
3291049Sbinkertn@umich.edu    {
3301049Sbinkertn@umich.edu      protected:
3311049Sbinkertn@umich.edu        /** TLB interace */
3321049Sbinkertn@umich.edu        void finish(const Fault &fault_, RequestPtr request_,
3331049Sbinkertn@umich.edu                    ThreadContext *tc, BaseTLB::Mode mode);
3341049Sbinkertn@umich.edu
3351049Sbinkertn@umich.edu        /** Has my only packet been sent to the memory system but has not
3361049Sbinkertn@umich.edu         *  yet been responded to */
3371049Sbinkertn@umich.edu        bool packetInFlight;
3381049Sbinkertn@umich.edu
3391049Sbinkertn@umich.edu        /** Has the packet been at least sent to the memory system? */
3401049Sbinkertn@umich.edu        bool packetSent;
3411049Sbinkertn@umich.edu
3421049Sbinkertn@umich.edu      public:
3431049Sbinkertn@umich.edu        /** Send single translation request */
3441049Sbinkertn@umich.edu        void startAddrTranslation();
3451049Sbinkertn@umich.edu
3461049Sbinkertn@umich.edu        /** Get the head packet as counted by numIssuedFragments */
3471049Sbinkertn@umich.edu        PacketPtr getHeadPacket() { return packet; }
3481049Sbinkertn@umich.edu
3491049Sbinkertn@umich.edu        /** Remember that the packet has been sent */
3501049Sbinkertn@umich.edu        void stepToNextPacket() { packetInFlight = true; packetSent = true; }
3511049Sbinkertn@umich.edu
3521049Sbinkertn@umich.edu        /** Has packet been sent */
3531049Sbinkertn@umich.edu        bool hasPacketsInMemSystem() { return packetInFlight; }
3541049Sbinkertn@umich.edu
3551049Sbinkertn@umich.edu        /** packetInFlight can become false again, so need to check
3561049Sbinkertn@umich.edu         *  packetSent */
3571049Sbinkertn@umich.edu        bool sentAllPackets() { return packetSent; }
3581049Sbinkertn@umich.edu
3591049Sbinkertn@umich.edu        /** Keep the given packet as the response packet
3601049Sbinkertn@umich.edu         *  LSQRequest::packet */
3611049Sbinkertn@umich.edu        void retireResponse(PacketPtr packet_);
3621049Sbinkertn@umich.edu
3631049Sbinkertn@umich.edu      public:
3641049Sbinkertn@umich.edu        SingleDataRequest(LSQ &port_, MinorDynInstPtr inst_,
3651049Sbinkertn@umich.edu            bool isLoad_, PacketDataPtr data_ = NULL, uint64_t *res_ = NULL) :
3661049Sbinkertn@umich.edu            LSQRequest(port_, inst_, isLoad_, data_, res_),
3671049Sbinkertn@umich.edu            packetInFlight(false),
3681049Sbinkertn@umich.edu            packetSent(false)
3691049Sbinkertn@umich.edu        { }
3701049Sbinkertn@umich.edu    };
3711049Sbinkertn@umich.edu
3721049Sbinkertn@umich.edu    class SplitDataRequest : public LSQRequest
3731049Sbinkertn@umich.edu    {
3741049Sbinkertn@umich.edu      protected:
3751049Sbinkertn@umich.edu        /** Event to step between translations */
3761049Sbinkertn@umich.edu        class TranslationEvent : public Event
3771049Sbinkertn@umich.edu        {
3781049Sbinkertn@umich.edu          protected:
3791049Sbinkertn@umich.edu            SplitDataRequest &owner;
3801049Sbinkertn@umich.edu
3811049Sbinkertn@umich.edu          public:
3821049Sbinkertn@umich.edu            TranslationEvent(SplitDataRequest &owner_)
3831049Sbinkertn@umich.edu                : owner(owner_) { }
3841049Sbinkertn@umich.edu
3851049Sbinkertn@umich.edu            void process()
3861049Sbinkertn@umich.edu            { owner.sendNextFragmentToTranslation(); }
3871049Sbinkertn@umich.edu        };
3881049Sbinkertn@umich.edu
3891049Sbinkertn@umich.edu        TranslationEvent translationEvent;
3901049Sbinkertn@umich.edu      protected:
3911049Sbinkertn@umich.edu        /** Number of fragments this request is split into */
3921049Sbinkertn@umich.edu        unsigned int numFragments;
3931049Sbinkertn@umich.edu
3941049Sbinkertn@umich.edu        /** Number of fragments in the address translation mechanism */
3951049Sbinkertn@umich.edu        unsigned int numInTranslationFragments;
3961049Sbinkertn@umich.edu
3971049Sbinkertn@umich.edu        /** Number of fragments that have completed address translation,
3981049Sbinkertn@umich.edu         *  (numTranslatedFragments + numInTranslationFragments) <=
3991049Sbinkertn@umich.edu         *  numFragments.  When numTranslatedFramgents == numFragments,
4001049Sbinkertn@umich.edu         *  translation is complete */
4011049Sbinkertn@umich.edu        unsigned int numTranslatedFragments;
4021049Sbinkertn@umich.edu
4031049Sbinkertn@umich.edu        /** Number of fragments already issued (<= numFragments) */
4041049Sbinkertn@umich.edu        unsigned int numIssuedFragments;
4051049Sbinkertn@umich.edu
4061049Sbinkertn@umich.edu        /** Number of fragments retired back to this request */
4071049Sbinkertn@umich.edu        unsigned int numRetiredFragments;
4081049Sbinkertn@umich.edu
4091049Sbinkertn@umich.edu        /** Fragment Requests corresponding to the address ranges of
4101049Sbinkertn@umich.edu         *  each fragment */
4111049Sbinkertn@umich.edu        std::vector<Request *> fragmentRequests;
4121049Sbinkertn@umich.edu
4131049Sbinkertn@umich.edu        /** Packets matching fragmentRequests to issue fragments to memory */
4141049Sbinkertn@umich.edu        std::vector<Packet *> fragmentPackets;
4151049Sbinkertn@umich.edu
4161049Sbinkertn@umich.edu      protected:
4171049Sbinkertn@umich.edu        /** TLB response interface */
4181049Sbinkertn@umich.edu        void finish(const Fault &fault_, RequestPtr request_,
4191049Sbinkertn@umich.edu                    ThreadContext *tc, BaseTLB::Mode mode);
4201049Sbinkertn@umich.edu
4211049Sbinkertn@umich.edu      public:
4221049Sbinkertn@umich.edu        SplitDataRequest(LSQ &port_, MinorDynInstPtr inst_,
4231049Sbinkertn@umich.edu            bool isLoad_, PacketDataPtr data_ = NULL,
4241049Sbinkertn@umich.edu            uint64_t *res_ = NULL);
4251049Sbinkertn@umich.edu
4261049Sbinkertn@umich.edu        ~SplitDataRequest();
4271049Sbinkertn@umich.edu
4281049Sbinkertn@umich.edu      public:
4291049Sbinkertn@umich.edu        /** Make all the Requests for this transfer's fragments so that those
4301049Sbinkertn@umich.edu         *  requests can be sent for address translation */
4311049Sbinkertn@umich.edu        void makeFragmentRequests();
4321049Sbinkertn@umich.edu
4331049Sbinkertn@umich.edu        /** Make the packets to go with the requests so they can be sent to
4341049Sbinkertn@umich.edu         *  the memory system */
4351049Sbinkertn@umich.edu        void makeFragmentPackets();
4361049Sbinkertn@umich.edu
4371049Sbinkertn@umich.edu        /** Start a loop of do { sendNextFragmentToTranslation ;
4381049Sbinkertn@umich.edu         *  translateTiming ; finish } while (numTranslatedFragments !=
4391049Sbinkertn@umich.edu         *  numFragments) to complete all this requests' fragments' address
4401049Sbinkertn@umich.edu         *  translations */
4411049Sbinkertn@umich.edu        void startAddrTranslation();
4421049Sbinkertn@umich.edu
4431049Sbinkertn@umich.edu        /** Get the head packet as counted by numIssuedFragments */
4441049Sbinkertn@umich.edu        PacketPtr getHeadPacket();
4451049Sbinkertn@umich.edu
4461049Sbinkertn@umich.edu        /** Step on numIssuedFragments */
4471049Sbinkertn@umich.edu        void stepToNextPacket();
4481049Sbinkertn@umich.edu
4491049Sbinkertn@umich.edu        bool hasPacketsInMemSystem()
4501049Sbinkertn@umich.edu        { return numIssuedFragments != numRetiredFragments; }
4511049Sbinkertn@umich.edu
4521049Sbinkertn@umich.edu        /** Have we stepped past the end of fragmentPackets? */
4531049Sbinkertn@umich.edu        bool sentAllPackets() { return numIssuedFragments == numFragments; }
4541049Sbinkertn@umich.edu
4551929Sbinkertn@umich.edu        /** For loads, paste the response data into the main
4561929Sbinkertn@umich.edu         *  response packet */
4571049Sbinkertn@umich.edu        void retireResponse(PacketPtr packet_);
4581049Sbinkertn@umich.edu
4591049Sbinkertn@umich.edu        /** Part of the address translation loop, see startAddTranslation */
4601929Sbinkertn@umich.edu        void sendNextFragmentToTranslation();
4611049Sbinkertn@umich.edu    };
4621929Sbinkertn@umich.edu
4631049Sbinkertn@umich.edu    /** Store buffer.  This contains stores which have been committed
4641929Sbinkertn@umich.edu     *  but whose memory transfers have not yet been issued. Load data
4651049Sbinkertn@umich.edu     *  can be forwarded out of the store buffer */
4661049Sbinkertn@umich.edu    class StoreBuffer : public Named
4671049Sbinkertn@umich.edu    {
4681049Sbinkertn@umich.edu      public:
4691049Sbinkertn@umich.edu        /** My owner */
4701049Sbinkertn@umich.edu        LSQ &lsq;
4711049Sbinkertn@umich.edu
4721049Sbinkertn@umich.edu        /** Number of slots, this is a bound on the size of slots */
4731929Sbinkertn@umich.edu        const unsigned int numSlots;
4741049Sbinkertn@umich.edu
4751049Sbinkertn@umich.edu        /** Maximum number of stores that can be issued per cycle */
4761049Sbinkertn@umich.edu        const unsigned int storeLimitPerCycle;
4771929Sbinkertn@umich.edu
4781929Sbinkertn@umich.edu      public:
4791049Sbinkertn@umich.edu        /** Queue of store requests on their way to memory */
4801049Sbinkertn@umich.edu        std::deque<LSQRequestPtr> slots;
4811049Sbinkertn@umich.edu
4821049Sbinkertn@umich.edu        /** Number of occupied slots which have not yet issued a
4831049Sbinkertn@umich.edu         *  memory access */
4841049Sbinkertn@umich.edu        unsigned int numUnissuedAccesses;
4851049Sbinkertn@umich.edu
4861929Sbinkertn@umich.edu      public:
4871929Sbinkertn@umich.edu        StoreBuffer(std::string name_, LSQ &lsq_,
4881049Sbinkertn@umich.edu            unsigned int store_buffer_size,
4891929Sbinkertn@umich.edu            unsigned int store_limit_per_cycle);
4901929Sbinkertn@umich.edu
4911929Sbinkertn@umich.edu      public:
4921929Sbinkertn@umich.edu        /** Can a new request be inserted into the queue? */
4931929Sbinkertn@umich.edu        bool canInsert() const;
4941929Sbinkertn@umich.edu
4951929Sbinkertn@umich.edu        /** Delete the given request and free the slot it occupied */
4961929Sbinkertn@umich.edu        void deleteRequest(LSQRequestPtr request);
4971881Sbinkertn@umich.edu
4981881Sbinkertn@umich.edu        /** Insert a request at the back of the queue */
4991881Sbinkertn@umich.edu        void insert(LSQRequestPtr request);
500
501        /** Look for a store which satisfies the given load.  Returns an
502         *  indication whether the forwarding request can be wholly,
503         *  partly or not all all satisfied.  If the request can be
504         *  wholly satisfied, the store buffer slot number which can be used
505         *  is returned in found_slot */
506        AddrRangeCoverage canForwardDataToLoad(LSQRequestPtr request,
507            unsigned int &found_slot);
508
509        /** Fill the given packet with appropriate date from slot
510         *  slot_number */
511        void forwardStoreData(LSQRequestPtr load, unsigned int slot_number);
512
513        /** Number of stores in the store buffer which have not been
514         *  completely issued to the memory system */
515        unsigned int numUnissuedStores() { return numUnissuedAccesses; }
516
517        /** Drained if there is absolutely nothing left in the buffer */
518        bool isDrained() const { return slots.empty(); }
519
520        /** Try to issue more stores to memory */
521        void step();
522
523        /** Report queue contents for MinorTrace */
524        void minorTrace() const;
525    };
526
527  protected:
528    /** Most recent execSeqNum of a memory barrier instruction or
529     *  0 if there are no in-flight barriers.  Useful as a
530     *  dependency for early-issued memory operations */
531    InstSeqNum lastMemBarrier;
532
533  public:
534    /** Retry state of last issued memory transfer */
535    MemoryState state;
536
537    /** Maximum number of in-flight accesses issued to the memory system */
538    const unsigned int inMemorySystemLimit;
539
540    /** Memory system access width (and snap) in bytes */
541    const unsigned int lineWidth;
542
543  public:
544    /** The LSQ consists of three queues: requests, transfers and the
545     *  store buffer storeBuffer. */
546
547    typedef Queue<LSQRequestPtr,
548        ReportTraitsPtrAdaptor<LSQRequestPtr>,
549        NoBubbleTraits<LSQRequestPtr> >
550        LSQQueue;
551
552    /** requests contains LSQRequests which have been issued to the TLB by
553     *  calling ExecContext::readMem/writeMem (which in turn calls
554     *  LSQ::pushRequest and LSQRequest::startAddrTranslation).  Once they
555     *  have a physical address, requests at the head of requests can be
556     *  issued to the memory system.  At this stage, it cannot be clear that
557     *  memory accesses *must* happen (that there are no preceding faults or
558     *  changes of flow of control) and so only cacheable reads are issued
559     *  to memory.
560     *  Cacheable stores are not issued at all (and just pass through
561     *  'transfers' in order) and all other transfers are stalled in requests
562     *  until their corresponding instructions are at the head of the
563     *  inMemInsts instruction queue and have the right streamSeqNum. */
564    LSQQueue requests;
565
566    /** Once issued to memory (or, for stores, just had their
567     *  state changed to StoreToStoreBuffer) LSQRequests pass through
568     *  transfers waiting for memory responses.  At the head of transfers,
569     *  Execute::commitInst can pick up the memory response for a request
570     *  using LSQ::findResponse.  Responses to be committed can then
571     *  have ExecContext::completeAcc on them.  Stores can then be pushed
572     *  into the store buffer.  All other transfers will then be complete. */
573    LSQQueue transfers;
574
575    /* The store buffer contains committed cacheable stores on
576     * their way to memory decoupled from subsequence instruction execution.
577     * Before trying to issue a cacheable read from 'requests' to memory,
578     * the store buffer is checked to see if a previous store contains the
579     * needed data (StoreBuffer::canForwardDataToLoad) which can be
580     * forwarded in lieu of a memory access.  If there are outstanding
581     * stores in the transfers queue, they must be promoted to the store
582     * buffer (and so be commited) before they can be correctly checked
583     * for forwarding. */
584    StoreBuffer storeBuffer;
585
586  protected:
587    /** Count of the number of mem. accesses which have left the
588     *  requests queue and are in the 'wild' in the memory system and who
589     *  *must not* be interrupted as they are not normal cacheable
590     *  accesses.  This is a count of the number of in-flight requests
591     *  with issuedToMemory set who have visited tryToSendRequest at least
592     *  once */
593    unsigned int numAccessesInMemorySystem;
594
595    /** Number of requests in the DTLB in the requests queue */
596    unsigned int numAccessesInDTLB;
597
598    /** The number of stores in the transfers queue.  Useful when
599     *  testing if the store buffer contains all the forwardable stores */
600    unsigned int numStoresInTransfers;
601
602    /** The number of accesses which have been issued to the memory
603     *  system but have not been committed/discarded *excluding*
604     *  cacheable normal loads which don't need to be tracked */
605    unsigned int numAccessesIssuedToMemory;
606
607    /** The request (from either requests or the store buffer) which is
608     *  currently waiting have its memory access retried */
609    LSQRequestPtr retryRequest;
610
611    /** Address Mask for a cache block (e.g. ~(cache_block_size-1)) */
612    Addr cacheBlockMask;
613
614  protected:
615    /** Try and issue a memory access for a translated request at the
616     *  head of the requests queue.  Also tries to move the request
617     *  between queues */
618    void tryToSendToTransfers(LSQRequestPtr request);
619
620    /** Try to send (or resend) a memory request's next/only packet to
621     *  the memory system.  Returns true if the request was successfully
622     *  sent to memory (and was also the last packet in a transfer) */
623    bool tryToSend(LSQRequestPtr request);
624
625    /** Clear a barrier (if it's the last one marked up in lastMemBarrier) */
626    void clearMemBarrier(MinorDynInstPtr inst);
627
628    /** Move a request between queues */
629    void moveFromRequestsToTransfers(LSQRequestPtr request);
630
631    /** Can a request be sent to the memory system */
632    bool canSendToMemorySystem();
633
634  public:
635    LSQ(std::string name_, std::string dcache_port_name_,
636        MinorCPU &cpu_, Execute &execute_,
637        unsigned int max_accesses_in_memory_system, unsigned int line_width,
638        unsigned int requests_queue_size, unsigned int transfers_queue_size,
639        unsigned int store_buffer_size,
640        unsigned int store_buffer_cycle_store_limit);
641
642    virtual ~LSQ();
643
644  public:
645    /** Step checks the queues to see if their are issuable transfers
646     *  which were not otherwise picked up by tests at the end of other
647     *  events.
648     *
649     *  Steppable actions include deferred actions which couldn't be
650     *  cascaded on the end of a memory response/TLB response event
651     *  because of resource congestion. */
652    void step();
653
654    /** Is their space in the request queue to be able to push a request by
655     *  issuing an isMemRef instruction */
656    bool canRequest() { return requests.unreservedRemainingSpace() != 0; }
657
658    /** Returns a response if it's at the head of the transfers queue and
659     *  it's either complete or can be sent on to the store buffer.  After
660     *  calling, the request still remains on the transfer queue until
661     *  popResponse is called */
662    LSQRequestPtr findResponse(MinorDynInstPtr inst);
663
664    /** Sanity check and pop the head response */
665    void popResponse(LSQRequestPtr response);
666
667    /** Must check this before trying to insert into the store buffer */
668    bool canPushIntoStoreBuffer() const { return storeBuffer.canInsert(); }
669
670    /** A store has been committed, please move it to the store buffer */
671    void sendStoreToStoreBuffer(LSQRequestPtr request);
672
673    /** Are there any accesses other than normal cached loads in the
674     *  memory system or having received responses which need to be
675     *  handled for their instruction's to be completed */
676    bool accessesInFlight() const
677    { return numAccessesIssuedToMemory != 0; }
678
679    /** A memory barrier instruction has been issued, remember its
680     *  execSeqNum that we can avoid issuing memory ops until it is
681     *  committed */
682    void issuedMemBarrierInst(MinorDynInstPtr inst);
683
684    /** Get the execSeqNum of the last issued memory barrier */
685    InstSeqNum getLastMemBarrier() const { return lastMemBarrier; }
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, unsigned int flags, uint64_t *res);
703
704    /** Push a predicate failed-representing request into the queues just
705     *  to maintain commit order */
706    void pushFailedRequest(MinorDynInstPtr inst);
707
708    /** Memory interface */
709    bool recvTimingResp(PacketPtr pkt);
710    void recvRetry();
711    void recvTimingSnoopReq(PacketPtr pkt);
712
713    /** Return the raw-bindable port */
714    MinorCPU::MinorCPUPort &getDcachePort() { return dcachePort; }
715
716    void minorTrace() const;
717};
718
719/** Make a suitable packet for the given request.  If the request is a store,
720 *  data will be the payload data.  If sender_state is NULL, it won't be
721 *  pushed into the packet as senderState */
722PacketPtr makePacketForRequest(Request &request, bool isLoad,
723    Packet::SenderState *sender_state = NULL, PacketDataPtr data = NULL);
724}
725
726#endif /* __CPU_MINOR_NEW_LSQ_HH__ */
727