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