lsq_unit.hh revision 4022
12068SN/A/* 22068SN/A * Copyright (c) 2004-2006 The Regents of The University of Michigan 32188SN/A * All rights reserved. 42068SN/A * 52068SN/A * Redistribution and use in source and binary forms, with or without 62068SN/A * modification, are permitted provided that the following conditions are 72068SN/A * met: redistributions of source code must retain the above copyright 82068SN/A * notice, this list of conditions and the following disclaimer; 92068SN/A * redistributions in binary form must reproduce the above copyright 102068SN/A * notice, this list of conditions and the following disclaimer in the 112068SN/A * documentation and/or other materials provided with the distribution; 122068SN/A * neither the name of the copyright holders nor the names of its 132068SN/A * contributors may be used to endorse or promote products derived from 142068SN/A * this software without specific prior written permission. 152068SN/A * 162068SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 172068SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 182068SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 192068SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 202068SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 212068SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 222068SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 232068SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 242068SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 252068SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 262068SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 272068SN/A * 282665Ssaidi@eecs.umich.edu * Authors: Kevin Lim 292665Ssaidi@eecs.umich.edu * Korey Sewell 302068SN/A */ 312649Ssaidi@eecs.umich.edu 322649Ssaidi@eecs.umich.edu#ifndef __CPU_O3_LSQ_UNIT_HH__ 332649Ssaidi@eecs.umich.edu#define __CPU_O3_LSQ_UNIT_HH__ 342649Ssaidi@eecs.umich.edu 352649Ssaidi@eecs.umich.edu#include <algorithm> 362068SN/A#include <map> 372068SN/A#include <queue> 382068SN/A 392068SN/A#include "arch/faults.hh" 402068SN/A#include "arch/locked_mem.hh" 412068SN/A#include "config/full_system.hh" 422068SN/A#include "base/hashmap.hh" 432068SN/A#include "cpu/inst_seq.hh" 442075SN/A#include "mem/packet.hh" 452075SN/A#include "mem/port.hh" 462075SN/A 472075SN/A/** 486076Sgblack@eecs.umich.edu * Class that implements the actual LQ and SQ for each specific 496076Sgblack@eecs.umich.edu * thread. Both are circular queues; load entries are freed upon 502068SN/A * committing, while store entries are freed once they writeback. The 512068SN/A * LSQUnit tracks if there are memory ordering violations, and also 522068SN/A * detects partial load to store forwarding cases (a store only has 532075SN/A * part of a load's data) that requires the load to wait until the 542075SN/A * store writes back. In the former case it holds onto the instruction 552068SN/A * until the dependence unit looks at it, and in the latter it stalls 562068SN/A * the LSQ until the store writes back. At that point the load is 572075SN/A * replayed. 582075SN/A */ 592068SN/Atemplate <class Impl> 602068SN/Aclass LSQUnit { 612068SN/A protected: 622075SN/A typedef TheISA::IntReg IntReg; 632075SN/A public: 642075SN/A typedef typename Impl::Params Params; 652075SN/A typedef typename Impl::O3CPU O3CPU; 662075SN/A typedef typename Impl::DynInstPtr DynInstPtr; 672075SN/A typedef typename Impl::CPUPol::IEW IEW; 682075SN/A typedef typename Impl::CPUPol::LSQ LSQ; 692068SN/A typedef typename Impl::CPUPol::IssueStruct IssueStruct; 702068SN/A 712068SN/A public: 722075SN/A /** Constructs an LSQ unit. init() must be called prior to use. */ 732068SN/A LSQUnit(); 742069SN/A 752068SN/A /** Initializes the LSQ unit with the specified number of entries. */ 762068SN/A void init(Params *params, LSQ *lsq_ptr, unsigned maxLQEntries, 774027Sstever@eecs.umich.edu unsigned maxSQEntries, unsigned id); 784027Sstever@eecs.umich.edu 794027Sstever@eecs.umich.edu /** Returns the name of the LSQ unit. */ 806076Sgblack@eecs.umich.edu std::string name() const; 812075SN/A 822068SN/A /** Registers statistics. */ 832069SN/A void regStats(); 842068SN/A 852068SN/A /** Sets the CPU pointer. */ 862068SN/A void setCPU(O3CPU *cpu_ptr); 872068SN/A 882068SN/A /** Sets the IEW stage pointer. */ 892068SN/A void setIEW(IEW *iew_ptr) 902068SN/A { iewStage = iew_ptr; } 912068SN/A 924027Sstever@eecs.umich.edu /** Sets the pointer to the dcache port. */ 934027Sstever@eecs.umich.edu void setDcachePort(Port *dcache_port) 944027Sstever@eecs.umich.edu { dcachePort = dcache_port; } 954027Sstever@eecs.umich.edu 964027Sstever@eecs.umich.edu /** Switches out LSQ unit. */ 974027Sstever@eecs.umich.edu void switchOut(); 986076Sgblack@eecs.umich.edu 992068SN/A /** Takes over from another CPU's thread. */ 1002068SN/A void takeOverFrom(); 1012068SN/A 1022068SN/A /** Returns if the LSQ is switched out. */ 1037799Sgblack@eecs.umich.edu bool isSwitchedOut() { return switchedOut; } 1042068SN/A 1052068SN/A /** Ticks the LSQ unit, which in this case only resets the number of 1062068SN/A * used cache ports. 1076227Snate@binkert.org * @todo: Move the number of used ports up to the LSQ level so it can 1082068SN/A * be shared by all LSQ units. 1092068SN/A */ 1102068SN/A void tick() { usedPorts = 0; } 1112147SN/A 1122068SN/A /** Inserts an instruction. */ 1132068SN/A void insert(DynInstPtr &inst); 1142068SN/A /** Inserts a load instruction. */ 1152068SN/A void insertLoad(DynInstPtr &load_inst); 1162068SN/A /** Inserts a store instruction. */ 1172068SN/A void insertStore(DynInstPtr &store_inst); 1182068SN/A 1192068SN/A /** Executes a load instruction. */ 1202068SN/A Fault executeLoad(DynInstPtr &inst); 1212068SN/A 1222068SN/A Fault executeLoad(int lq_idx) { panic("Not implemented"); return NoFault; } 1232147SN/A /** Executes a store instruction. */ 1242068SN/A Fault executeStore(DynInstPtr &inst); 1252068SN/A 1262068SN/A /** Commits the head load. */ 1272068SN/A void commitLoad(); 1282068SN/A /** Commits loads older than a specific sequence number. */ 1292068SN/A void commitLoads(InstSeqNum &youngest_inst); 1302068SN/A 1316227Snate@binkert.org /** Commits stores older than a specific sequence number. */ 1322068SN/A void commitStores(InstSeqNum &youngest_inst); 1332068SN/A 1342068SN/A /** Writes back stores. */ 1352068SN/A void writebackStores(); 1362068SN/A 1372147SN/A /** Completes the data access that has been returned from the 1382068SN/A * memory system. */ 1392068SN/A void completeDataAccess(PacketPtr pkt); 1402068SN/A 1412068SN/A /** Clears all the entries in the LQ. */ 1422068SN/A void clearLQ(); 1432068SN/A 1442068SN/A /** Clears all the entries in the SQ. */ 1452068SN/A void clearSQ(); 1462068SN/A 1472068SN/A /** Resizes the LQ to a given size. */ 1482068SN/A void resizeLQ(unsigned size); 1492068SN/A 1502068SN/A /** Resizes the SQ to a given size. */ 1512147SN/A void resizeSQ(unsigned size); 1522068SN/A 1532068SN/A /** Squashes all instructions younger than a specific sequence number. */ 1542068SN/A void squash(const InstSeqNum &squashed_num); 1552068SN/A 1562068SN/A /** Returns if there is a memory ordering violation. Value is reset upon 1572068SN/A * call to getMemDepViolator(). 1582068SN/A */ 1592068SN/A bool violation() { return memDepViolator; } 1602068SN/A 1612068SN/A /** Returns the memory ordering violator. */ 1622068SN/A DynInstPtr getMemDepViolator(); 1632068SN/A 1642068SN/A /** Returns if a load became blocked due to the memory system. */ 1652068SN/A bool loadBlocked() 1662068SN/A { return isLoadBlocked; } 1672068SN/A 1682068SN/A /** Clears the signal that a load became blocked. */ 1692068SN/A void clearLoadBlocked() 1702068SN/A { isLoadBlocked = false; } 1712068SN/A 1722068SN/A /** Returns if the blocked load was handled. */ 1732068SN/A bool isLoadBlockedHandled() 1742068SN/A { return loadBlockedHandled; } 1752068SN/A 1767799Sgblack@eecs.umich.edu /** Records the blocked load as being handled. */ 1772068SN/A void setLoadBlockedHandled() 1782068SN/A { loadBlockedHandled = true; } 1792068SN/A 1802068SN/A /** Returns the number of free entries (min of free LQ and SQ entries). */ 1812068SN/A unsigned numFreeEntries(); 1822068SN/A 1832068SN/A /** Returns the number of loads ready to execute. */ 1842068SN/A int numLoadsReady(); 1852068SN/A 1862068SN/A /** Returns the number of loads in the LQ. */ 1872068SN/A int numLoads() { return loads; } 1882068SN/A 1892068SN/A /** Returns the number of stores in the SQ. */ 1902068SN/A int numStores() { return stores; } 1912068SN/A 1922068SN/A /** Returns if either the LQ or SQ is full. */ 1932068SN/A bool isFull() { return lqFull() || sqFull(); } 1942068SN/A 1952068SN/A /** Returns if the LQ is full. */ 1962068SN/A bool lqFull() { return loads >= (LQEntries - 1); } 1972068SN/A 1982068SN/A /** Returns if the SQ is full. */ 1992068SN/A bool sqFull() { return stores >= (SQEntries - 1); } 2002068SN/A 2012068SN/A /** Returns the number of instructions in the LSQ. */ 2022068SN/A unsigned getCount() { return loads + stores; } 2032068SN/A 2042068SN/A /** Returns if there are any stores to writeback. */ 2052068SN/A bool hasStoresToWB() { return storesToWB; } 2068560Sgblack@eecs.umich.edu 2072068SN/A /** Returns the number of stores to writeback. */ 2082068SN/A int numStoresToWB() { return storesToWB; } 2092068SN/A 2102068SN/A /** Returns if the LSQ unit will writeback on this cycle. */ 2112068SN/A bool willWB() { return storeQueue[storeWBIdx].canWB && 2122068SN/A !storeQueue[storeWBIdx].completed && 2132068SN/A !isStoreBlocked; } 2142068SN/A 2152068SN/A /** Handles doing the retry. */ 2162068SN/A void recvRetry(); 2172068SN/A 2182068SN/A private: 2192068SN/A /** Writes back the instruction, sending it to IEW. */ 2202068SN/A void writeback(DynInstPtr &inst, PacketPtr pkt); 2212068SN/A 2222068SN/A /** Handles completing the send of a store to memory. */ 2232068SN/A void storePostSend(PacketPtr pkt); 2242068SN/A 2252068SN/A /** Completes the store at the specified index. */ 2262068SN/A void completeStore(int store_idx); 2272068SN/A 2282068SN/A /** Increments the given store index (circular queue). */ 2292068SN/A inline void incrStIdx(int &store_idx); 2302068SN/A /** Decrements the given store index (circular queue). */ 2312068SN/A inline void decrStIdx(int &store_idx); 2322068SN/A /** Increments the given load index (circular queue). */ 2332068SN/A inline void incrLdIdx(int &load_idx); 2342068SN/A /** Decrements the given load index (circular queue). */ 2352068SN/A inline void decrLdIdx(int &load_idx); 2362068SN/A 2372068SN/A public: 2382068SN/A /** Debugging function to dump instructions in the LSQ. */ 2392068SN/A void dumpInsts(); 2402068SN/A 2412068SN/A private: 2422068SN/A /** Pointer to the CPU. */ 2432068SN/A O3CPU *cpu; 2442068SN/A 2452068SN/A /** Pointer to the IEW stage. */ 2462068SN/A IEW *iewStage; 2472068SN/A 2482068SN/A /** Pointer to the LSQ. */ 2492068SN/A LSQ *lsq; 2502068SN/A 2512068SN/A /** Pointer to the dcache port. Used only for sending. */ 2522068SN/A Port *dcachePort; 2532068SN/A 2542068SN/A /** Derived class to hold any sender state the LSQ needs. */ 2552068SN/A class LSQSenderState : public Packet::SenderState 2562068SN/A { 2572068SN/A public: 2582068SN/A /** Default constructor. */ 2592068SN/A LSQSenderState() 2602068SN/A : noWB(false) 2612068SN/A { } 2622068SN/A 2632068SN/A /** Instruction who initiated the access to memory. */ 2642068SN/A DynInstPtr inst; 2652068SN/A /** Whether or not it is a load. */ 2662068SN/A bool isLoad; 2672068SN/A /** The LQ/SQ index of the instruction. */ 2682068SN/A int idx; 2692068SN/A /** Whether or not the instruction will need to writeback. */ 2702068SN/A bool noWB; 2712068SN/A }; 2722068SN/A 2732068SN/A /** Writeback event, specifically for when stores forward data to loads. */ 2742068SN/A class WritebackEvent : public Event { 2752068SN/A public: 2762068SN/A /** Constructs a writeback event. */ 2772068SN/A WritebackEvent(DynInstPtr &_inst, PacketPtr pkt, LSQUnit *lsq_ptr); 2782068SN/A 2792068SN/A /** Processes the writeback event. */ 2802068SN/A void process(); 2812068SN/A 2822068SN/A /** Returns the description of this event. */ 2832068SN/A const char *description(); 2842068SN/A 2852068SN/A private: 2867799Sgblack@eecs.umich.edu /** Instruction whose results are being written back. */ 2872068SN/A DynInstPtr inst; 2882068SN/A 2892068SN/A /** The packet that would have been sent to memory. */ 2902068SN/A PacketPtr pkt; 2912068SN/A 2922068SN/A /** The pointer to the LSQ unit that issued the store. */ 2932068SN/A LSQUnit<Impl> *lsqPtr; 2942068SN/A }; 2952068SN/A 2967799Sgblack@eecs.umich.edu public: 2972068SN/A struct SQEntry { 2982068SN/A /** Constructs an empty store queue entry. */ 2992068SN/A SQEntry() 3002068SN/A : inst(NULL), req(NULL), size(0), data(0), 3012068SN/A canWB(0), committed(0), completed(0) 3022068SN/A { } 3032068SN/A 3042147SN/A /** Constructs a store queue entry for a given instruction. */ 3052068SN/A SQEntry(DynInstPtr &_inst) 3062068SN/A : inst(_inst), req(NULL), size(0), data(0), 3072068SN/A canWB(0), committed(0), completed(0) 3082068SN/A { } 3092068SN/A 3102068SN/A /** The store instruction. */ 3112068SN/A DynInstPtr inst; 3122068SN/A /** The request for the store. */ 3132068SN/A RequestPtr req; 3142068SN/A /** The size of the store. */ 3152147SN/A int size; 3162068SN/A /** The store data. */ 3172068SN/A IntReg data; 3182068SN/A /** Whether or not the store can writeback. */ 3192068SN/A bool canWB; 3202068SN/A /** Whether or not the store is committed. */ 3212068SN/A bool committed; 3222068SN/A /** Whether or not the store is completed. */ 3236804Ssroy@cse.usf.edu bool completed; 3246804Ssroy@cse.usf.edu }; 3256804Ssroy@cse.usf.edu 3266804Ssroy@cse.usf.edu private: 3276804Ssroy@cse.usf.edu /** The LSQUnit thread id. */ 3286804Ssroy@cse.usf.edu unsigned lsqID; 3296804Ssroy@cse.usf.edu 3306804Ssroy@cse.usf.edu /** The store queue. */ 3316804Ssroy@cse.usf.edu std::vector<SQEntry> storeQueue; 3326804Ssroy@cse.usf.edu 3336804Ssroy@cse.usf.edu /** The load queue. */ 3346804Ssroy@cse.usf.edu std::vector<DynInstPtr> loadQueue; 3356804Ssroy@cse.usf.edu 3366804Ssroy@cse.usf.edu /** The number of LQ entries, plus a sentinel entry (circular queue). 3376804Ssroy@cse.usf.edu * @todo: Consider having var that records the true number of LQ entries. 3386804Ssroy@cse.usf.edu */ 3396804Ssroy@cse.usf.edu unsigned LQEntries; 3406804Ssroy@cse.usf.edu /** The number of SQ entries, plus a sentinel entry (circular queue). 3416804Ssroy@cse.usf.edu * @todo: Consider having var that records the true number of SQ entries. 3426804Ssroy@cse.usf.edu */ 3436804Ssroy@cse.usf.edu unsigned SQEntries; 3446804Ssroy@cse.usf.edu 3456804Ssroy@cse.usf.edu /** The number of load instructions in the LQ. */ 3466804Ssroy@cse.usf.edu int loads; 3476804Ssroy@cse.usf.edu /** The number of store instructions in the SQ. */ 3482068SN/A int stores; 3492068SN/A /** The number of store instructions in the SQ waiting to writeback. */ 3502068SN/A int storesToWB; 3512068SN/A 3522068SN/A /** The index of the head instruction in the LQ. */ 3532068SN/A int loadHead; 3542068SN/A /** The index of the tail instruction in the LQ. */ 3552068SN/A int loadTail; 3562068SN/A 3572068SN/A /** The index of the head instruction in the SQ. */ 3582068SN/A int storeHead; 3592068SN/A /** The index of the first instruction that may be ready to be 3602068SN/A * written back, and has not yet been written back. 3612068SN/A */ 3622068SN/A int storeWBIdx; 3632068SN/A /** The index of the tail instruction in the SQ. */ 3642068SN/A int storeTail; 3652068SN/A 3662068SN/A /// @todo Consider moving to a more advanced model with write vs read ports 3672068SN/A /** The number of cache ports available each cycle. */ 3682068SN/A int cachePorts; 3696804Ssroy@cse.usf.edu 3706804Ssroy@cse.usf.edu /** The number of used cache ports in this cycle. */ 3716804Ssroy@cse.usf.edu int usedPorts; 3722068SN/A 3732068SN/A /** Is the LSQ switched out. */ 3742068SN/A bool switchedOut; 3752068SN/A 3766804Ssroy@cse.usf.edu //list<InstSeqNum> mshrSeqNums; 3776804Ssroy@cse.usf.edu 3786804Ssroy@cse.usf.edu /** Wire to read information from the issue stage time queue. */ 3796804Ssroy@cse.usf.edu typename TimeBuffer<IssueStruct>::wire fromIssue; 3806804Ssroy@cse.usf.edu 3816804Ssroy@cse.usf.edu /** Whether or not the LSQ is stalled. */ 3826804Ssroy@cse.usf.edu bool stalled; 3836804Ssroy@cse.usf.edu /** The store that causes the stall due to partial store to load 3846804Ssroy@cse.usf.edu * forwarding. 3856804Ssroy@cse.usf.edu */ 3866804Ssroy@cse.usf.edu InstSeqNum stallingStoreIsn; 3876804Ssroy@cse.usf.edu /** The index of the above store. */ 3886804Ssroy@cse.usf.edu int stallingLoadIdx; 3896804Ssroy@cse.usf.edu 3906804Ssroy@cse.usf.edu /** The packet that needs to be retried. */ 3916804Ssroy@cse.usf.edu PacketPtr retryPkt; 3926804Ssroy@cse.usf.edu 3936804Ssroy@cse.usf.edu /** Whehter or not a store is blocked due to the memory system. */ 3946804Ssroy@cse.usf.edu bool isStoreBlocked; 3956804Ssroy@cse.usf.edu 3966804Ssroy@cse.usf.edu /** Whether or not a load is blocked due to the memory system. */ 3976804Ssroy@cse.usf.edu bool isLoadBlocked; 3986804Ssroy@cse.usf.edu 3996804Ssroy@cse.usf.edu /** Has the blocked load been handled. */ 4006804Ssroy@cse.usf.edu bool loadBlockedHandled; 4016804Ssroy@cse.usf.edu 4026804Ssroy@cse.usf.edu /** The sequence number of the blocked load. */ 4036804Ssroy@cse.usf.edu InstSeqNum blockedLoadSeqNum; 4046804Ssroy@cse.usf.edu 4056804Ssroy@cse.usf.edu /** The oldest load that caused a memory ordering violation. */ 4066804Ssroy@cse.usf.edu DynInstPtr memDepViolator; 4076804Ssroy@cse.usf.edu 4086804Ssroy@cse.usf.edu // Will also need how many read/write ports the Dcache has. Or keep track 4096804Ssroy@cse.usf.edu // of that in stage that is one level up, and only call executeLoad/Store 4106804Ssroy@cse.usf.edu // the appropriate number of times. 4116804Ssroy@cse.usf.edu /** Total number of loads forwaded from LSQ stores. */ 4126804Ssroy@cse.usf.edu Stats::Scalar<> lsqForwLoads; 4136804Ssroy@cse.usf.edu 4146804Ssroy@cse.usf.edu /** Total number of loads ignored due to invalid addresses. */ 4156804Ssroy@cse.usf.edu Stats::Scalar<> invAddrLoads; 4166804Ssroy@cse.usf.edu 4176804Ssroy@cse.usf.edu /** Total number of squashed loads. */ 4186804Ssroy@cse.usf.edu Stats::Scalar<> lsqSquashedLoads; 4196804Ssroy@cse.usf.edu 4206804Ssroy@cse.usf.edu /** Total number of responses from the memory system that are 4216804Ssroy@cse.usf.edu * ignored due to the instruction already being squashed. */ 4226804Ssroy@cse.usf.edu Stats::Scalar<> lsqIgnoredResponses; 4236804Ssroy@cse.usf.edu 4246804Ssroy@cse.usf.edu /** Tota number of memory ordering violations. */ 4256804Ssroy@cse.usf.edu Stats::Scalar<> lsqMemOrderViolation; 4266804Ssroy@cse.usf.edu 4276804Ssroy@cse.usf.edu /** Total number of squashed stores. */ 4286804Ssroy@cse.usf.edu Stats::Scalar<> lsqSquashedStores; 4296804Ssroy@cse.usf.edu 4306804Ssroy@cse.usf.edu /** Total number of software prefetches ignored due to invalid addresses. */ 4316804Ssroy@cse.usf.edu Stats::Scalar<> invAddrSwpfs; 4326804Ssroy@cse.usf.edu 4336804Ssroy@cse.usf.edu /** Ready loads blocked due to partial store-forwarding. */ 4346804Ssroy@cse.usf.edu Stats::Scalar<> lsqBlockedLoads; 4356804Ssroy@cse.usf.edu 4366804Ssroy@cse.usf.edu /** Number of loads that were rescheduled. */ 4376804Ssroy@cse.usf.edu Stats::Scalar<> lsqRescheduledLoads; 4386804Ssroy@cse.usf.edu 4396804Ssroy@cse.usf.edu /** Number of times the LSQ is blocked due to the cache. */ 4406804Ssroy@cse.usf.edu Stats::Scalar<> lsqCacheBlocked; 4416804Ssroy@cse.usf.edu 4426804Ssroy@cse.usf.edu public: 4436804Ssroy@cse.usf.edu /** Executes the load at the given index. */ 4446804Ssroy@cse.usf.edu template <class T> 4456804Ssroy@cse.usf.edu Fault read(Request *req, T &data, int load_idx); 4466804Ssroy@cse.usf.edu 4476804Ssroy@cse.usf.edu /** Executes the store at the given index. */ 4486804Ssroy@cse.usf.edu template <class T> 4496804Ssroy@cse.usf.edu Fault write(Request *req, T &data, int store_idx); 4506804Ssroy@cse.usf.edu 4516804Ssroy@cse.usf.edu /** Returns the index of the head load instruction. */ 4526804Ssroy@cse.usf.edu int getLoadHead() { return loadHead; } 4536804Ssroy@cse.usf.edu /** Returns the sequence number of the head load instruction. */ 4546804Ssroy@cse.usf.edu InstSeqNum getLoadHeadSeqNum() 4556804Ssroy@cse.usf.edu { 4566804Ssroy@cse.usf.edu if (loadQueue[loadHead]) { 4576804Ssroy@cse.usf.edu return loadQueue[loadHead]->seqNum; 4586804Ssroy@cse.usf.edu } else { 4596804Ssroy@cse.usf.edu return 0; 4606804Ssroy@cse.usf.edu } 4616804Ssroy@cse.usf.edu 4626804Ssroy@cse.usf.edu } 4636804Ssroy@cse.usf.edu 4646804Ssroy@cse.usf.edu /** Returns the index of the head store instruction. */ 4656804Ssroy@cse.usf.edu int getStoreHead() { return storeHead; } 4666804Ssroy@cse.usf.edu /** Returns the sequence number of the head store instruction. */ 4676804Ssroy@cse.usf.edu InstSeqNum getStoreHeadSeqNum() 4686804Ssroy@cse.usf.edu { 4696804Ssroy@cse.usf.edu if (storeQueue[storeHead].inst) { 4706804Ssroy@cse.usf.edu return storeQueue[storeHead].inst->seqNum; 4716804Ssroy@cse.usf.edu } else { 4726804Ssroy@cse.usf.edu return 0; 4736804Ssroy@cse.usf.edu } 4746804Ssroy@cse.usf.edu 4756804Ssroy@cse.usf.edu } 4766804Ssroy@cse.usf.edu 4776804Ssroy@cse.usf.edu /** Returns whether or not the LSQ unit is stalled. */ 4786804Ssroy@cse.usf.edu bool isStalled() { return stalled; } 4796804Ssroy@cse.usf.edu}; 4806804Ssroy@cse.usf.edu 4816804Ssroy@cse.usf.edutemplate <class Impl> 4826804Ssroy@cse.usf.edutemplate <class T> 4836804Ssroy@cse.usf.eduFault 4846804Ssroy@cse.usf.eduLSQUnit<Impl>::read(Request *req, T &data, int load_idx) 4856804Ssroy@cse.usf.edu{ 4866804Ssroy@cse.usf.edu DynInstPtr load_inst = loadQueue[load_idx]; 4876804Ssroy@cse.usf.edu 4886804Ssroy@cse.usf.edu assert(load_inst); 4896804Ssroy@cse.usf.edu 4906804Ssroy@cse.usf.edu assert(!load_inst->isExecuted()); 4916804Ssroy@cse.usf.edu 4926804Ssroy@cse.usf.edu // Make sure this isn't an uncacheable access 4936804Ssroy@cse.usf.edu // A bit of a hackish way to get uncached accesses to work only if they're 4946804Ssroy@cse.usf.edu // at the head of the LSQ and are ready to commit (at the head of the ROB 4956804Ssroy@cse.usf.edu // too). 4966804Ssroy@cse.usf.edu if (req->isUncacheable() && 4976804Ssroy@cse.usf.edu (load_idx != loadHead || !load_inst->isAtCommit())) { 4986804Ssroy@cse.usf.edu iewStage->rescheduleMemInst(load_inst); 4996804Ssroy@cse.usf.edu ++lsqRescheduledLoads; 5006804Ssroy@cse.usf.edu return TheISA::genMachineCheckFault(); 5016804Ssroy@cse.usf.edu } 5026804Ssroy@cse.usf.edu 5036804Ssroy@cse.usf.edu // Check the SQ for any previous stores that might lead to forwarding 5046804Ssroy@cse.usf.edu int store_idx = load_inst->sqIdx; 5056804Ssroy@cse.usf.edu 5066804Ssroy@cse.usf.edu int store_size = 0; 5076804Ssroy@cse.usf.edu 5086804Ssroy@cse.usf.edu DPRINTF(LSQUnit, "Read called, load idx: %i, store idx: %i, " 5096804Ssroy@cse.usf.edu "storeHead: %i addr: %#x\n", 5106804Ssroy@cse.usf.edu load_idx, store_idx, storeHead, req->getPaddr()); 5116804Ssroy@cse.usf.edu 5126804Ssroy@cse.usf.edu if (req->isLocked()) { 5136804Ssroy@cse.usf.edu // Disable recording the result temporarily. Writing to misc 5146804Ssroy@cse.usf.edu // regs normally updates the result, but this is not the 5156804Ssroy@cse.usf.edu // desired behavior when handling store conditionals. 5166804Ssroy@cse.usf.edu load_inst->recordResult = false; 5176804Ssroy@cse.usf.edu TheISA::handleLockedRead(load_inst.get(), req); 5186804Ssroy@cse.usf.edu load_inst->recordResult = true; 5196804Ssroy@cse.usf.edu } 5206804Ssroy@cse.usf.edu 5216804Ssroy@cse.usf.edu while (store_idx != -1) { 5226804Ssroy@cse.usf.edu // End once we've reached the top of the LSQ 5236804Ssroy@cse.usf.edu if (store_idx == storeWBIdx) { 5246804Ssroy@cse.usf.edu break; 5256804Ssroy@cse.usf.edu } 5262068SN/A 5272068SN/A // Move the index to one younger 5282068SN/A if (--store_idx < 0) 5292068SN/A store_idx += SQEntries; 5302068SN/A 5312068SN/A assert(storeQueue[store_idx].inst); 5322068SN/A 5332068SN/A store_size = storeQueue[store_idx].size; 5342068SN/A 5352068SN/A if (store_size == 0) 5362068SN/A continue; 5372068SN/A 5382068SN/A // Check if the store data is within the lower and upper bounds of 5392068SN/A // addresses that the request needs. 5402068SN/A bool store_has_lower_limit = 5412068SN/A req->getVaddr() >= storeQueue[store_idx].inst->effAddr; 5422068SN/A bool store_has_upper_limit = 5432068SN/A (req->getVaddr() + req->getSize()) <= 5442068SN/A (storeQueue[store_idx].inst->effAddr + store_size); 5452068SN/A bool lower_load_has_store_part = 5462068SN/A req->getVaddr() < (storeQueue[store_idx].inst->effAddr + 5472068SN/A store_size); 5482068SN/A bool upper_load_has_store_part = 5492068SN/A (req->getVaddr() + req->getSize()) > 5502068SN/A storeQueue[store_idx].inst->effAddr; 5512068SN/A 5522068SN/A // If the store's data has all of the data needed, we can forward. 5532068SN/A if (store_has_lower_limit && store_has_upper_limit) { 5542068SN/A // Get shift amount for offset into the store's data. 5552068SN/A int shift_amt = req->getVaddr() & (store_size - 1); 5562068SN/A // @todo: Magic number, assumes byte addressing 5572068SN/A shift_amt = shift_amt << 3; 5582068SN/A 5592068SN/A // Cast this to type T? 5602068SN/A data = storeQueue[store_idx].data >> shift_amt; 5612068SN/A 5622068SN/A // When the data comes from the store queue entry, it's in host 5632068SN/A // order. When it gets sent to the load, it needs to be in guest 5642068SN/A // order so when the load converts it again, it ends up back 5652068SN/A // in host order like the inst expects. 5662068SN/A data = TheISA::htog(data); 5672068SN/A 5682068SN/A assert(!load_inst->memData); 5692068SN/A load_inst->memData = new uint8_t[64]; 5702068SN/A 5712068SN/A memcpy(load_inst->memData, &data, req->getSize()); 5722068SN/A 5732068SN/A DPRINTF(LSQUnit, "Forwarding from store idx %i to load to " 5742068SN/A "addr %#x, data %#x\n", 5752068SN/A store_idx, req->getVaddr(), data); 5762068SN/A 5772068SN/A PacketPtr data_pkt = new Packet(req, MemCmd::ReadReq, 5782068SN/A Packet::Broadcast); 5792068SN/A data_pkt->dataStatic(load_inst->memData); 5802068SN/A 5812068SN/A WritebackEvent *wb = new WritebackEvent(load_inst, data_pkt, this); 5827799Sgblack@eecs.umich.edu 5832068SN/A // We'll say this has a 1 cycle load-store forwarding latency 5842068SN/A // for now. 5852068SN/A // @todo: Need to make this a parameter. 5862068SN/A wb->schedule(curTick); 5872068SN/A 5882068SN/A ++lsqForwLoads; 5892068SN/A return NoFault; 5902068SN/A } else if ((store_has_lower_limit && lower_load_has_store_part) || 5912068SN/A (store_has_upper_limit && upper_load_has_store_part) || 5922068SN/A (lower_load_has_store_part && upper_load_has_store_part)) { 5932068SN/A // This is the partial store-load forwarding case where a store 5942147SN/A // has only part of the load's data. 5952068SN/A 5962068SN/A // If it's already been written back, then don't worry about 5972068SN/A // stalling on it. 5982068SN/A if (storeQueue[store_idx].completed) { 5992068SN/A continue; 6002147SN/A } 6012068SN/A 6022068SN/A // Must stall load and force it to retry, so long as it's the oldest 6032068SN/A // load that needs to do so. 6042068SN/A if (!stalled || 6052068SN/A (stalled && 6062147SN/A load_inst->seqNum < 6072068SN/A loadQueue[stallingLoadIdx]->seqNum)) { 6082068SN/A stalled = true; 6092068SN/A stallingStoreIsn = storeQueue[store_idx].inst->seqNum; 6102068SN/A stallingLoadIdx = load_idx; 6112068SN/A } 6122068SN/A 6132068SN/A // Tell IQ/mem dep unit that this instruction will need to be 6142068SN/A // rescheduled eventually 6152068SN/A iewStage->rescheduleMemInst(load_inst); 6162068SN/A iewStage->decrWb(load_inst->seqNum); 6172068SN/A ++lsqRescheduledLoads; 6182068SN/A 6192068SN/A // Do not generate a writeback event as this instruction is not 6202068SN/A // complete. 6212068SN/A DPRINTF(LSQUnit, "Load-store forwarding mis-match. " 6222068SN/A "Store idx %i to load addr %#x\n", 6232068SN/A store_idx, req->getVaddr()); 6242068SN/A 6252068SN/A ++lsqBlockedLoads; 6262068SN/A return NoFault; 6272068SN/A } 6282068SN/A } 6292068SN/A 6302068SN/A // If there's no forwarding case, then go access memory 6312068SN/A DPRINTF(LSQUnit, "Doing memory access for inst [sn:%lli] PC %#x\n", 6322068SN/A load_inst->seqNum, load_inst->readPC()); 6332068SN/A 6342068SN/A assert(!load_inst->memData); 6352068SN/A load_inst->memData = new uint8_t[64]; 6362068SN/A 6372068SN/A ++usedPorts; 6382068SN/A 6392068SN/A // if we the cache is not blocked, do cache access 6402068SN/A if (!lsq->cacheBlocked()) { 6412068SN/A PacketPtr data_pkt = 6422068SN/A new Packet(req, MemCmd::ReadReq, Packet::Broadcast); 6432068SN/A data_pkt->dataStatic(load_inst->memData); 6442068SN/A 6452068SN/A LSQSenderState *state = new LSQSenderState; 6462068SN/A state->isLoad = true; 6472068SN/A state->idx = load_idx; 6482068SN/A state->inst = load_inst; 6492068SN/A data_pkt->senderState = state; 6502068SN/A 6512068SN/A if (!dcachePort->sendTiming(data_pkt)) { 6522068SN/A Packet::Result result = data_pkt->result; 6532068SN/A 6542068SN/A // Delete state and data packet because a load retry 6552068SN/A // initiates a pipeline restart; it does not retry. 6562068SN/A delete state; 6572068SN/A delete data_pkt; 6582068SN/A 6592068SN/A if (result == Packet::BadAddress) { 6602068SN/A return TheISA::genMachineCheckFault(); 6612068SN/A } 6622068SN/A 6632068SN/A // If the access didn't succeed, tell the LSQ by setting 6642068SN/A // the retry thread id. 6652068SN/A lsq->setRetryTid(lsqID); 6662068SN/A } 6672068SN/A } 6682068SN/A 6692068SN/A // If the cache was blocked, or has become blocked due to the access, 6702068SN/A // handle it. 6712068SN/A if (lsq->cacheBlocked()) { 6722068SN/A ++lsqCacheBlocked; 6732068SN/A 6742068SN/A iewStage->decrWb(load_inst->seqNum); 6752068SN/A // There's an older load that's already going to squash. 6762068SN/A if (isLoadBlocked && blockedLoadSeqNum < load_inst->seqNum) 6772068SN/A return NoFault; 6782068SN/A 6792068SN/A // Record that the load was blocked due to memory. This 6802068SN/A // load will squash all instructions after it, be 6812068SN/A // refetched, and re-executed. 6822068SN/A isLoadBlocked = true; 6832068SN/A loadBlockedHandled = false; 6842068SN/A blockedLoadSeqNum = load_inst->seqNum; 6852068SN/A // No fault occurred, even though the interface is blocked. 6862068SN/A return NoFault; 6872068SN/A } 6882068SN/A 6892068SN/A return NoFault; 6902068SN/A} 6912068SN/A 6922068SN/Atemplate <class Impl> 6932068SN/Atemplate <class T> 6942068SN/AFault 6952068SN/ALSQUnit<Impl>::write(Request *req, T &data, int store_idx) 6962068SN/A{ 6972068SN/A assert(storeQueue[store_idx].inst); 6982068SN/A 6992068SN/A DPRINTF(LSQUnit, "Doing write to store idx %i, addr %#x data %#x" 7002068SN/A " | storeHead:%i [sn:%i]\n", 7012068SN/A store_idx, req->getPaddr(), data, storeHead, 7022068SN/A storeQueue[store_idx].inst->seqNum); 7032068SN/A 7042068SN/A storeQueue[store_idx].req = req; 7052068SN/A storeQueue[store_idx].size = sizeof(T); 7062068SN/A storeQueue[store_idx].data = data; 7072068SN/A 7082068SN/A // This function only writes the data to the store queue, so no fault 7092068SN/A // can happen here. 7102068SN/A return NoFault; 7112068SN/A} 7122068SN/A 7132068SN/A#endif // __CPU_O3_LSQ_UNIT_HH__ 7142068SN/A