lsq_unit.hh revision 5386:5614618f4027
17396Sgblack@eecs.umich.edu/* 27396Sgblack@eecs.umich.edu * Copyright (c) 2004-2006 The Regents of The University of Michigan 37396Sgblack@eecs.umich.edu * All rights reserved. 47396Sgblack@eecs.umich.edu * 57396Sgblack@eecs.umich.edu * Redistribution and use in source and binary forms, with or without 67396Sgblack@eecs.umich.edu * modification, are permitted provided that the following conditions are 77396Sgblack@eecs.umich.edu * met: redistributions of source code must retain the above copyright 87396Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer; 97396Sgblack@eecs.umich.edu * redistributions in binary form must reproduce the above copyright 107396Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer in the 117396Sgblack@eecs.umich.edu * documentation and/or other materials provided with the distribution; 127396Sgblack@eecs.umich.edu * neither the name of the copyright holders nor the names of its 137396Sgblack@eecs.umich.edu * contributors may be used to endorse or promote products derived from 147396Sgblack@eecs.umich.edu * this software without specific prior written permission. 157396Sgblack@eecs.umich.edu * 167396Sgblack@eecs.umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 177396Sgblack@eecs.umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 187396Sgblack@eecs.umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 197396Sgblack@eecs.umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 207396Sgblack@eecs.umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 217396Sgblack@eecs.umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 227396Sgblack@eecs.umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 237396Sgblack@eecs.umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 247396Sgblack@eecs.umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 257396Sgblack@eecs.umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 267396Sgblack@eecs.umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 277396Sgblack@eecs.umich.edu * 287396Sgblack@eecs.umich.edu * Authors: Kevin Lim 297396Sgblack@eecs.umich.edu * Korey Sewell 307396Sgblack@eecs.umich.edu */ 317396Sgblack@eecs.umich.edu 327396Sgblack@eecs.umich.edu#ifndef __CPU_O3_LSQ_UNIT_HH__ 337396Sgblack@eecs.umich.edu#define __CPU_O3_LSQ_UNIT_HH__ 347396Sgblack@eecs.umich.edu 357396Sgblack@eecs.umich.edu#include <algorithm> 367396Sgblack@eecs.umich.edu#include <cstring> 377396Sgblack@eecs.umich.edu#include <map> 387396Sgblack@eecs.umich.edu#include <queue> 397396Sgblack@eecs.umich.edu 407396Sgblack@eecs.umich.edu#include "arch/faults.hh" 417396Sgblack@eecs.umich.edu#include "arch/locked_mem.hh" 427434Sgblack@eecs.umich.edu#include "config/full_system.hh" 437434Sgblack@eecs.umich.edu#include "base/fast_alloc.hh" 447434Sgblack@eecs.umich.edu#include "base/hashmap.hh" 457434Sgblack@eecs.umich.edu#include "cpu/inst_seq.hh" 467434Sgblack@eecs.umich.edu#include "mem/packet.hh" 477434Sgblack@eecs.umich.edu#include "mem/port.hh" 487396Sgblack@eecs.umich.edu 497396Sgblack@eecs.umich.edu/** 507396Sgblack@eecs.umich.edu * Class that implements the actual LQ and SQ for each specific 517396Sgblack@eecs.umich.edu * thread. Both are circular queues; load entries are freed upon 527396Sgblack@eecs.umich.edu * committing, while store entries are freed once they writeback. The 537396Sgblack@eecs.umich.edu * LSQUnit tracks if there are memory ordering violations, and also 547396Sgblack@eecs.umich.edu * detects partial load to store forwarding cases (a store only has 557396Sgblack@eecs.umich.edu * part of a load's data) that requires the load to wait until the 567396Sgblack@eecs.umich.edu * store writes back. In the former case it holds onto the instruction 577396Sgblack@eecs.umich.edu * until the dependence unit looks at it, and in the latter it stalls 587396Sgblack@eecs.umich.edu * the LSQ until the store writes back. At that point the load is 597396Sgblack@eecs.umich.edu * replayed. 607396Sgblack@eecs.umich.edu */ 617396Sgblack@eecs.umich.edutemplate <class Impl> 627396Sgblack@eecs.umich.educlass LSQUnit { 637396Sgblack@eecs.umich.edu protected: 647396Sgblack@eecs.umich.edu typedef TheISA::IntReg IntReg; 657396Sgblack@eecs.umich.edu public: 667396Sgblack@eecs.umich.edu typedef typename Impl::Params Params; 677396Sgblack@eecs.umich.edu typedef typename Impl::O3CPU O3CPU; 687396Sgblack@eecs.umich.edu typedef typename Impl::DynInstPtr DynInstPtr; 697396Sgblack@eecs.umich.edu typedef typename Impl::CPUPol::IEW IEW; 707396Sgblack@eecs.umich.edu typedef typename Impl::CPUPol::LSQ LSQ; 717396Sgblack@eecs.umich.edu typedef typename Impl::CPUPol::IssueStruct IssueStruct; 727396Sgblack@eecs.umich.edu 737396Sgblack@eecs.umich.edu public: 747396Sgblack@eecs.umich.edu /** Constructs an LSQ unit. init() must be called prior to use. */ 757396Sgblack@eecs.umich.edu LSQUnit(); 767396Sgblack@eecs.umich.edu 777396Sgblack@eecs.umich.edu /** Initializes the LSQ unit with the specified number of entries. */ 787396Sgblack@eecs.umich.edu void init(O3CPU *cpu_ptr, IEW *iew_ptr, Params *params, LSQ *lsq_ptr, 797396Sgblack@eecs.umich.edu unsigned maxLQEntries, unsigned maxSQEntries, unsigned id); 807396Sgblack@eecs.umich.edu 817396Sgblack@eecs.umich.edu /** Returns the name of the LSQ unit. */ 827396Sgblack@eecs.umich.edu std::string name() const; 837396Sgblack@eecs.umich.edu 847396Sgblack@eecs.umich.edu /** Registers statistics. */ 857396Sgblack@eecs.umich.edu void regStats(); 867396Sgblack@eecs.umich.edu 877396Sgblack@eecs.umich.edu /** Sets the pointer to the dcache port. */ 887396Sgblack@eecs.umich.edu void setDcachePort(Port *dcache_port); 897396Sgblack@eecs.umich.edu 907396Sgblack@eecs.umich.edu /** Switches out LSQ unit. */ 917396Sgblack@eecs.umich.edu void switchOut(); 927396Sgblack@eecs.umich.edu 937430Sgblack@eecs.umich.edu /** Takes over from another CPU's thread. */ 947430Sgblack@eecs.umich.edu void takeOverFrom(); 957430Sgblack@eecs.umich.edu 967430Sgblack@eecs.umich.edu /** Returns if the LSQ is switched out. */ 977430Sgblack@eecs.umich.edu bool isSwitchedOut() { return switchedOut; } 987430Sgblack@eecs.umich.edu 997430Sgblack@eecs.umich.edu /** Ticks the LSQ unit, which in this case only resets the number of 1007430Sgblack@eecs.umich.edu * used cache ports. 1017430Sgblack@eecs.umich.edu * @todo: Move the number of used ports up to the LSQ level so it can 1027430Sgblack@eecs.umich.edu * be shared by all LSQ units. 1037430Sgblack@eecs.umich.edu */ 1047430Sgblack@eecs.umich.edu void tick() { usedPorts = 0; } 1057430Sgblack@eecs.umich.edu 1067430Sgblack@eecs.umich.edu /** Inserts an instruction. */ 1077430Sgblack@eecs.umich.edu void insert(DynInstPtr &inst); 1087430Sgblack@eecs.umich.edu /** Inserts a load instruction. */ 1097430Sgblack@eecs.umich.edu void insertLoad(DynInstPtr &load_inst); 1107430Sgblack@eecs.umich.edu /** Inserts a store instruction. */ 1117430Sgblack@eecs.umich.edu void insertStore(DynInstPtr &store_inst); 1127430Sgblack@eecs.umich.edu 1137430Sgblack@eecs.umich.edu /** Executes a load instruction. */ 1147430Sgblack@eecs.umich.edu Fault executeLoad(DynInstPtr &inst); 1157430Sgblack@eecs.umich.edu 1167430Sgblack@eecs.umich.edu Fault executeLoad(int lq_idx) { panic("Not implemented"); return NoFault; } 1177430Sgblack@eecs.umich.edu /** Executes a store instruction. */ 1187430Sgblack@eecs.umich.edu Fault executeStore(DynInstPtr &inst); 1197430Sgblack@eecs.umich.edu 1207430Sgblack@eecs.umich.edu /** Commits the head load. */ 1217430Sgblack@eecs.umich.edu void commitLoad(); 1227430Sgblack@eecs.umich.edu /** Commits loads older than a specific sequence number. */ 1237430Sgblack@eecs.umich.edu void commitLoads(InstSeqNum &youngest_inst); 1247430Sgblack@eecs.umich.edu 1257430Sgblack@eecs.umich.edu /** Commits stores older than a specific sequence number. */ 1267430Sgblack@eecs.umich.edu void commitStores(InstSeqNum &youngest_inst); 1277430Sgblack@eecs.umich.edu 1287430Sgblack@eecs.umich.edu /** Writes back stores. */ 1297430Sgblack@eecs.umich.edu void writebackStores(); 1307430Sgblack@eecs.umich.edu 1317430Sgblack@eecs.umich.edu /** Completes the data access that has been returned from the 1327430Sgblack@eecs.umich.edu * memory system. */ 1337430Sgblack@eecs.umich.edu void completeDataAccess(PacketPtr pkt); 1347430Sgblack@eecs.umich.edu 1357430Sgblack@eecs.umich.edu /** Clears all the entries in the LQ. */ 1367430Sgblack@eecs.umich.edu void clearLQ(); 1377430Sgblack@eecs.umich.edu 1387430Sgblack@eecs.umich.edu /** Clears all the entries in the SQ. */ 1397430Sgblack@eecs.umich.edu void clearSQ(); 1407430Sgblack@eecs.umich.edu 1417430Sgblack@eecs.umich.edu /** Resizes the LQ to a given size. */ 1427430Sgblack@eecs.umich.edu void resizeLQ(unsigned size); 1437430Sgblack@eecs.umich.edu 1447430Sgblack@eecs.umich.edu /** Resizes the SQ to a given size. */ 1457430Sgblack@eecs.umich.edu void resizeSQ(unsigned size); 1467430Sgblack@eecs.umich.edu 1477430Sgblack@eecs.umich.edu /** Squashes all instructions younger than a specific sequence number. */ 1487430Sgblack@eecs.umich.edu void squash(const InstSeqNum &squashed_num); 1497430Sgblack@eecs.umich.edu 1507430Sgblack@eecs.umich.edu /** Returns if there is a memory ordering violation. Value is reset upon 1517430Sgblack@eecs.umich.edu * call to getMemDepViolator(). 1527430Sgblack@eecs.umich.edu */ 1537430Sgblack@eecs.umich.edu bool violation() { return memDepViolator; } 1547430Sgblack@eecs.umich.edu 1557430Sgblack@eecs.umich.edu /** Returns the memory ordering violator. */ 1567430Sgblack@eecs.umich.edu DynInstPtr getMemDepViolator(); 1577430Sgblack@eecs.umich.edu 1587430Sgblack@eecs.umich.edu /** Returns if a load became blocked due to the memory system. */ 1597430Sgblack@eecs.umich.edu bool loadBlocked() 1607430Sgblack@eecs.umich.edu { return isLoadBlocked; } 1617430Sgblack@eecs.umich.edu 1627430Sgblack@eecs.umich.edu /** Clears the signal that a load became blocked. */ 1637430Sgblack@eecs.umich.edu void clearLoadBlocked() 1647430Sgblack@eecs.umich.edu { isLoadBlocked = false; } 1657430Sgblack@eecs.umich.edu 1667430Sgblack@eecs.umich.edu /** Returns if the blocked load was handled. */ 1677430Sgblack@eecs.umich.edu bool isLoadBlockedHandled() 1687430Sgblack@eecs.umich.edu { return loadBlockedHandled; } 1697430Sgblack@eecs.umich.edu 1707430Sgblack@eecs.umich.edu /** Records the blocked load as being handled. */ 1717430Sgblack@eecs.umich.edu void setLoadBlockedHandled() 1727430Sgblack@eecs.umich.edu { loadBlockedHandled = true; } 1737430Sgblack@eecs.umich.edu 1747430Sgblack@eecs.umich.edu /** Returns the number of free entries (min of free LQ and SQ entries). */ 1757430Sgblack@eecs.umich.edu unsigned numFreeEntries(); 1767430Sgblack@eecs.umich.edu 1777430Sgblack@eecs.umich.edu /** Returns the number of loads ready to execute. */ 1787430Sgblack@eecs.umich.edu int numLoadsReady(); 1797430Sgblack@eecs.umich.edu 1807430Sgblack@eecs.umich.edu /** Returns the number of loads in the LQ. */ 1817430Sgblack@eecs.umich.edu int numLoads() { return loads; } 1827430Sgblack@eecs.umich.edu 1837430Sgblack@eecs.umich.edu /** Returns the number of stores in the SQ. */ 1847430Sgblack@eecs.umich.edu int numStores() { return stores; } 1857430Sgblack@eecs.umich.edu 1867430Sgblack@eecs.umich.edu /** Returns if either the LQ or SQ is full. */ 1877430Sgblack@eecs.umich.edu bool isFull() { return lqFull() || sqFull(); } 1887430Sgblack@eecs.umich.edu 1897430Sgblack@eecs.umich.edu /** Returns if the LQ is full. */ 1907430Sgblack@eecs.umich.edu bool lqFull() { return loads >= (LQEntries - 1); } 1917430Sgblack@eecs.umich.edu 1927430Sgblack@eecs.umich.edu /** Returns if the SQ is full. */ 1937430Sgblack@eecs.umich.edu bool sqFull() { return stores >= (SQEntries - 1); } 1947430Sgblack@eecs.umich.edu 1957430Sgblack@eecs.umich.edu /** Returns the number of instructions in the LSQ. */ 1967430Sgblack@eecs.umich.edu unsigned getCount() { return loads + stores; } 1977430Sgblack@eecs.umich.edu 1987430Sgblack@eecs.umich.edu /** Returns if there are any stores to writeback. */ 1997430Sgblack@eecs.umich.edu bool hasStoresToWB() { return storesToWB; } 2007430Sgblack@eecs.umich.edu 2017430Sgblack@eecs.umich.edu /** Returns the number of stores to writeback. */ 2027430Sgblack@eecs.umich.edu int numStoresToWB() { return storesToWB; } 2037430Sgblack@eecs.umich.edu 2047430Sgblack@eecs.umich.edu /** Returns if the LSQ unit will writeback on this cycle. */ 2057430Sgblack@eecs.umich.edu bool willWB() { return storeQueue[storeWBIdx].canWB && 2067430Sgblack@eecs.umich.edu !storeQueue[storeWBIdx].completed && 2077430Sgblack@eecs.umich.edu !isStoreBlocked; } 2087430Sgblack@eecs.umich.edu 2097430Sgblack@eecs.umich.edu /** Handles doing the retry. */ 2107430Sgblack@eecs.umich.edu void recvRetry(); 2117430Sgblack@eecs.umich.edu 2127430Sgblack@eecs.umich.edu private: 2137430Sgblack@eecs.umich.edu /** Writes back the instruction, sending it to IEW. */ 2147430Sgblack@eecs.umich.edu void writeback(DynInstPtr &inst, PacketPtr pkt); 2157430Sgblack@eecs.umich.edu 2167430Sgblack@eecs.umich.edu /** Handles completing the send of a store to memory. */ 2177430Sgblack@eecs.umich.edu void storePostSend(PacketPtr pkt); 2187430Sgblack@eecs.umich.edu 2197430Sgblack@eecs.umich.edu /** Completes the store at the specified index. */ 2207430Sgblack@eecs.umich.edu void completeStore(int store_idx); 2217430Sgblack@eecs.umich.edu 2227430Sgblack@eecs.umich.edu /** Increments the given store index (circular queue). */ 2237430Sgblack@eecs.umich.edu inline void incrStIdx(int &store_idx); 2247430Sgblack@eecs.umich.edu /** Decrements the given store index (circular queue). */ 2257430Sgblack@eecs.umich.edu inline void decrStIdx(int &store_idx); 2267430Sgblack@eecs.umich.edu /** Increments the given load index (circular queue). */ 2277430Sgblack@eecs.umich.edu inline void incrLdIdx(int &load_idx); 2287430Sgblack@eecs.umich.edu /** Decrements the given load index (circular queue). */ 2297430Sgblack@eecs.umich.edu inline void decrLdIdx(int &load_idx); 2307430Sgblack@eecs.umich.edu 2317430Sgblack@eecs.umich.edu public: 2327430Sgblack@eecs.umich.edu /** Debugging function to dump instructions in the LSQ. */ 2337430Sgblack@eecs.umich.edu void dumpInsts(); 2347430Sgblack@eecs.umich.edu 2357430Sgblack@eecs.umich.edu private: 2367430Sgblack@eecs.umich.edu /** Pointer to the CPU. */ 2377430Sgblack@eecs.umich.edu O3CPU *cpu; 2387430Sgblack@eecs.umich.edu 2397430Sgblack@eecs.umich.edu /** Pointer to the IEW stage. */ 2407430Sgblack@eecs.umich.edu IEW *iewStage; 2417430Sgblack@eecs.umich.edu 2427430Sgblack@eecs.umich.edu /** Pointer to the LSQ. */ 2437430Sgblack@eecs.umich.edu LSQ *lsq; 2447430Sgblack@eecs.umich.edu 2457430Sgblack@eecs.umich.edu /** Pointer to the dcache port. Used only for sending. */ 2467430Sgblack@eecs.umich.edu Port *dcachePort; 2477430Sgblack@eecs.umich.edu 2487430Sgblack@eecs.umich.edu /** Derived class to hold any sender state the LSQ needs. */ 2497430Sgblack@eecs.umich.edu class LSQSenderState : public Packet::SenderState, public FastAlloc 2507430Sgblack@eecs.umich.edu { 2517430Sgblack@eecs.umich.edu public: 2527430Sgblack@eecs.umich.edu /** Default constructor. */ 2537430Sgblack@eecs.umich.edu LSQSenderState() 2547430Sgblack@eecs.umich.edu : noWB(false) 2557430Sgblack@eecs.umich.edu { } 2567430Sgblack@eecs.umich.edu 2577430Sgblack@eecs.umich.edu /** Instruction who initiated the access to memory. */ 2587430Sgblack@eecs.umich.edu DynInstPtr inst; 2597430Sgblack@eecs.umich.edu /** Whether or not it is a load. */ 2607430Sgblack@eecs.umich.edu bool isLoad; 2617430Sgblack@eecs.umich.edu /** The LQ/SQ index of the instruction. */ 2627430Sgblack@eecs.umich.edu int idx; 2637430Sgblack@eecs.umich.edu /** Whether or not the instruction will need to writeback. */ 2647430Sgblack@eecs.umich.edu bool noWB; 2657430Sgblack@eecs.umich.edu }; 2667430Sgblack@eecs.umich.edu 2677430Sgblack@eecs.umich.edu /** Writeback event, specifically for when stores forward data to loads. */ 2687430Sgblack@eecs.umich.edu class WritebackEvent : public Event { 2697430Sgblack@eecs.umich.edu public: 2707430Sgblack@eecs.umich.edu /** Constructs a writeback event. */ 2717430Sgblack@eecs.umich.edu WritebackEvent(DynInstPtr &_inst, PacketPtr pkt, LSQUnit *lsq_ptr); 2727430Sgblack@eecs.umich.edu 2737430Sgblack@eecs.umich.edu /** Processes the writeback event. */ 2747430Sgblack@eecs.umich.edu void process(); 2757430Sgblack@eecs.umich.edu 2767430Sgblack@eecs.umich.edu /** Returns the description of this event. */ 2777430Sgblack@eecs.umich.edu const char *description() const; 2787430Sgblack@eecs.umich.edu 2797430Sgblack@eecs.umich.edu private: 2807430Sgblack@eecs.umich.edu /** Instruction whose results are being written back. */ 2817430Sgblack@eecs.umich.edu DynInstPtr inst; 2827430Sgblack@eecs.umich.edu 2837430Sgblack@eecs.umich.edu /** The packet that would have been sent to memory. */ 2847430Sgblack@eecs.umich.edu PacketPtr pkt; 2857430Sgblack@eecs.umich.edu 2867430Sgblack@eecs.umich.edu /** The pointer to the LSQ unit that issued the store. */ 2877430Sgblack@eecs.umich.edu LSQUnit<Impl> *lsqPtr; 2887430Sgblack@eecs.umich.edu }; 2897430Sgblack@eecs.umich.edu 2907430Sgblack@eecs.umich.edu public: 2917430Sgblack@eecs.umich.edu struct SQEntry { 2927430Sgblack@eecs.umich.edu /** Constructs an empty store queue entry. */ 2937430Sgblack@eecs.umich.edu SQEntry() 2947430Sgblack@eecs.umich.edu : inst(NULL), req(NULL), size(0), 2957430Sgblack@eecs.umich.edu canWB(0), committed(0), completed(0) 2967430Sgblack@eecs.umich.edu { 2977430Sgblack@eecs.umich.edu std::memset(data, 0, sizeof(data)); 2987430Sgblack@eecs.umich.edu } 2997430Sgblack@eecs.umich.edu 3007430Sgblack@eecs.umich.edu /** Constructs a store queue entry for a given instruction. */ 3017430Sgblack@eecs.umich.edu SQEntry(DynInstPtr &_inst) 3027430Sgblack@eecs.umich.edu : inst(_inst), req(NULL), size(0), 3037430Sgblack@eecs.umich.edu canWB(0), committed(0), completed(0) 3047430Sgblack@eecs.umich.edu { 3057430Sgblack@eecs.umich.edu std::memset(data, 0, sizeof(data)); 3067430Sgblack@eecs.umich.edu } 3077430Sgblack@eecs.umich.edu 3087430Sgblack@eecs.umich.edu /** The store instruction. */ 3097430Sgblack@eecs.umich.edu DynInstPtr inst; 3107430Sgblack@eecs.umich.edu /** The request for the store. */ 3117430Sgblack@eecs.umich.edu RequestPtr req; 3127430Sgblack@eecs.umich.edu /** The size of the store. */ 3137430Sgblack@eecs.umich.edu int size; 3147430Sgblack@eecs.umich.edu /** The store data. */ 3157430Sgblack@eecs.umich.edu char data[sizeof(IntReg)]; 3167430Sgblack@eecs.umich.edu /** Whether or not the store can writeback. */ 3177430Sgblack@eecs.umich.edu bool canWB; 3187430Sgblack@eecs.umich.edu /** Whether or not the store is committed. */ 3197430Sgblack@eecs.umich.edu bool committed; 3207430Sgblack@eecs.umich.edu /** Whether or not the store is completed. */ 3217430Sgblack@eecs.umich.edu bool completed; 3227430Sgblack@eecs.umich.edu }; 3237430Sgblack@eecs.umich.edu 3247430Sgblack@eecs.umich.edu private: 3257430Sgblack@eecs.umich.edu /** The LSQUnit thread id. */ 3267430Sgblack@eecs.umich.edu unsigned lsqID; 3277430Sgblack@eecs.umich.edu 3287430Sgblack@eecs.umich.edu /** The store queue. */ 3297430Sgblack@eecs.umich.edu std::vector<SQEntry> storeQueue; 3307430Sgblack@eecs.umich.edu 3317430Sgblack@eecs.umich.edu /** The load queue. */ 3327430Sgblack@eecs.umich.edu std::vector<DynInstPtr> loadQueue; 3337430Sgblack@eecs.umich.edu 3347430Sgblack@eecs.umich.edu /** The number of LQ entries, plus a sentinel entry (circular queue). 3357430Sgblack@eecs.umich.edu * @todo: Consider having var that records the true number of LQ entries. 3367430Sgblack@eecs.umich.edu */ 3377430Sgblack@eecs.umich.edu unsigned LQEntries; 3387430Sgblack@eecs.umich.edu /** The number of SQ entries, plus a sentinel entry (circular queue). 3397430Sgblack@eecs.umich.edu * @todo: Consider having var that records the true number of SQ entries. 3407430Sgblack@eecs.umich.edu */ 3417430Sgblack@eecs.umich.edu unsigned SQEntries; 3427430Sgblack@eecs.umich.edu 3437430Sgblack@eecs.umich.edu /** The number of load instructions in the LQ. */ 3447430Sgblack@eecs.umich.edu int loads; 3457430Sgblack@eecs.umich.edu /** The number of store instructions in the SQ. */ 3467430Sgblack@eecs.umich.edu int stores; 3477430Sgblack@eecs.umich.edu /** The number of store instructions in the SQ waiting to writeback. */ 3487430Sgblack@eecs.umich.edu int storesToWB; 3497430Sgblack@eecs.umich.edu 3507430Sgblack@eecs.umich.edu /** The index of the head instruction in the LQ. */ 3517430Sgblack@eecs.umich.edu int loadHead; 3527430Sgblack@eecs.umich.edu /** The index of the tail instruction in the LQ. */ 3537430Sgblack@eecs.umich.edu int loadTail; 3547430Sgblack@eecs.umich.edu 3557430Sgblack@eecs.umich.edu /** The index of the head instruction in the SQ. */ 3567430Sgblack@eecs.umich.edu int storeHead; 3577430Sgblack@eecs.umich.edu /** The index of the first instruction that may be ready to be 3587430Sgblack@eecs.umich.edu * written back, and has not yet been written back. 3597430Sgblack@eecs.umich.edu */ 3607430Sgblack@eecs.umich.edu int storeWBIdx; 3617430Sgblack@eecs.umich.edu /** The index of the tail instruction in the SQ. */ 3627430Sgblack@eecs.umich.edu int storeTail; 3637430Sgblack@eecs.umich.edu 3647430Sgblack@eecs.umich.edu /// @todo Consider moving to a more advanced model with write vs read ports 3657430Sgblack@eecs.umich.edu /** The number of cache ports available each cycle. */ 3667430Sgblack@eecs.umich.edu int cachePorts; 3677430Sgblack@eecs.umich.edu 3687430Sgblack@eecs.umich.edu /** The number of used cache ports in this cycle. */ 3697430Sgblack@eecs.umich.edu int usedPorts; 3707430Sgblack@eecs.umich.edu 3717430Sgblack@eecs.umich.edu /** Is the LSQ switched out. */ 3727430Sgblack@eecs.umich.edu bool switchedOut; 3737430Sgblack@eecs.umich.edu 3747430Sgblack@eecs.umich.edu //list<InstSeqNum> mshrSeqNums; 3757430Sgblack@eecs.umich.edu 3767430Sgblack@eecs.umich.edu /** Wire to read information from the issue stage time queue. */ 3777430Sgblack@eecs.umich.edu typename TimeBuffer<IssueStruct>::wire fromIssue; 3787430Sgblack@eecs.umich.edu 3797430Sgblack@eecs.umich.edu /** Whether or not the LSQ is stalled. */ 3807430Sgblack@eecs.umich.edu bool stalled; 3817430Sgblack@eecs.umich.edu /** The store that causes the stall due to partial store to load 3827430Sgblack@eecs.umich.edu * forwarding. 3837430Sgblack@eecs.umich.edu */ 3847430Sgblack@eecs.umich.edu InstSeqNum stallingStoreIsn; 3857430Sgblack@eecs.umich.edu /** The index of the above store. */ 3867430Sgblack@eecs.umich.edu int stallingLoadIdx; 3877430Sgblack@eecs.umich.edu 3887430Sgblack@eecs.umich.edu /** The packet that needs to be retried. */ 3897430Sgblack@eecs.umich.edu PacketPtr retryPkt; 3907430Sgblack@eecs.umich.edu 3917430Sgblack@eecs.umich.edu /** Whehter or not a store is blocked due to the memory system. */ 3927430Sgblack@eecs.umich.edu bool isStoreBlocked; 3937430Sgblack@eecs.umich.edu 3947430Sgblack@eecs.umich.edu /** Whether or not a load is blocked due to the memory system. */ 3957430Sgblack@eecs.umich.edu bool isLoadBlocked; 3967430Sgblack@eecs.umich.edu 3977430Sgblack@eecs.umich.edu /** Has the blocked load been handled. */ 3987430Sgblack@eecs.umich.edu bool loadBlockedHandled; 3997430Sgblack@eecs.umich.edu 4007430Sgblack@eecs.umich.edu /** The sequence number of the blocked load. */ 4017430Sgblack@eecs.umich.edu InstSeqNum blockedLoadSeqNum; 4027430Sgblack@eecs.umich.edu 4037430Sgblack@eecs.umich.edu /** The oldest load that caused a memory ordering violation. */ 4047430Sgblack@eecs.umich.edu DynInstPtr memDepViolator; 4057430Sgblack@eecs.umich.edu 4067430Sgblack@eecs.umich.edu // Will also need how many read/write ports the Dcache has. Or keep track 4077430Sgblack@eecs.umich.edu // of that in stage that is one level up, and only call executeLoad/Store 4087430Sgblack@eecs.umich.edu // the appropriate number of times. 4097430Sgblack@eecs.umich.edu /** Total number of loads forwaded from LSQ stores. */ 4107430Sgblack@eecs.umich.edu Stats::Scalar<> lsqForwLoads; 4117430Sgblack@eecs.umich.edu 4127430Sgblack@eecs.umich.edu /** Total number of loads ignored due to invalid addresses. */ 4137430Sgblack@eecs.umich.edu Stats::Scalar<> invAddrLoads; 4147430Sgblack@eecs.umich.edu 4157430Sgblack@eecs.umich.edu /** Total number of squashed loads. */ 4167430Sgblack@eecs.umich.edu Stats::Scalar<> lsqSquashedLoads; 4177430Sgblack@eecs.umich.edu 4187430Sgblack@eecs.umich.edu /** Total number of responses from the memory system that are 4197430Sgblack@eecs.umich.edu * ignored due to the instruction already being squashed. */ 4207430Sgblack@eecs.umich.edu Stats::Scalar<> lsqIgnoredResponses; 4217430Sgblack@eecs.umich.edu 4227430Sgblack@eecs.umich.edu /** Tota number of memory ordering violations. */ 4237430Sgblack@eecs.umich.edu Stats::Scalar<> lsqMemOrderViolation; 4247430Sgblack@eecs.umich.edu 4257430Sgblack@eecs.umich.edu /** Total number of squashed stores. */ 4267430Sgblack@eecs.umich.edu Stats::Scalar<> lsqSquashedStores; 4277430Sgblack@eecs.umich.edu 4287430Sgblack@eecs.umich.edu /** Total number of software prefetches ignored due to invalid addresses. */ 4297430Sgblack@eecs.umich.edu Stats::Scalar<> invAddrSwpfs; 4307430Sgblack@eecs.umich.edu 4317430Sgblack@eecs.umich.edu /** Ready loads blocked due to partial store-forwarding. */ 4327430Sgblack@eecs.umich.edu Stats::Scalar<> lsqBlockedLoads; 4337430Sgblack@eecs.umich.edu 4347430Sgblack@eecs.umich.edu /** Number of loads that were rescheduled. */ 4357430Sgblack@eecs.umich.edu Stats::Scalar<> lsqRescheduledLoads; 4367430Sgblack@eecs.umich.edu 4377430Sgblack@eecs.umich.edu /** Number of times the LSQ is blocked due to the cache. */ 4387430Sgblack@eecs.umich.edu Stats::Scalar<> lsqCacheBlocked; 4397430Sgblack@eecs.umich.edu 4407430Sgblack@eecs.umich.edu public: 4417430Sgblack@eecs.umich.edu /** Executes the load at the given index. */ 4427430Sgblack@eecs.umich.edu template <class T> 4437430Sgblack@eecs.umich.edu Fault read(Request *req, T &data, int load_idx); 4447430Sgblack@eecs.umich.edu 4457430Sgblack@eecs.umich.edu /** Executes the store at the given index. */ 4467430Sgblack@eecs.umich.edu template <class T> 4477430Sgblack@eecs.umich.edu Fault write(Request *req, T &data, int store_idx); 4487430Sgblack@eecs.umich.edu 4497430Sgblack@eecs.umich.edu /** Returns the index of the head load instruction. */ 4507430Sgblack@eecs.umich.edu int getLoadHead() { return loadHead; } 4517430Sgblack@eecs.umich.edu /** Returns the sequence number of the head load instruction. */ 4527430Sgblack@eecs.umich.edu InstSeqNum getLoadHeadSeqNum() 4537430Sgblack@eecs.umich.edu { 4547430Sgblack@eecs.umich.edu if (loadQueue[loadHead]) { 4557430Sgblack@eecs.umich.edu return loadQueue[loadHead]->seqNum; 4567430Sgblack@eecs.umich.edu } else { 4577430Sgblack@eecs.umich.edu return 0; 4587430Sgblack@eecs.umich.edu } 4597430Sgblack@eecs.umich.edu 4607430Sgblack@eecs.umich.edu } 4617430Sgblack@eecs.umich.edu 4627430Sgblack@eecs.umich.edu /** Returns the index of the head store instruction. */ 4637430Sgblack@eecs.umich.edu int getStoreHead() { return storeHead; } 4647430Sgblack@eecs.umich.edu /** Returns the sequence number of the head store instruction. */ 4657430Sgblack@eecs.umich.edu InstSeqNum getStoreHeadSeqNum() 4667430Sgblack@eecs.umich.edu { 4677430Sgblack@eecs.umich.edu if (storeQueue[storeHead].inst) { 4687430Sgblack@eecs.umich.edu return storeQueue[storeHead].inst->seqNum; 4697430Sgblack@eecs.umich.edu } else { 4707430Sgblack@eecs.umich.edu return 0; 4717430Sgblack@eecs.umich.edu } 4727430Sgblack@eecs.umich.edu 4737430Sgblack@eecs.umich.edu } 4747430Sgblack@eecs.umich.edu 4757430Sgblack@eecs.umich.edu /** Returns whether or not the LSQ unit is stalled. */ 4767430Sgblack@eecs.umich.edu bool isStalled() { return stalled; } 4777430Sgblack@eecs.umich.edu}; 4787430Sgblack@eecs.umich.edu 4797430Sgblack@eecs.umich.edutemplate <class Impl> 4807430Sgblack@eecs.umich.edutemplate <class T> 4817430Sgblack@eecs.umich.eduFault 4827430Sgblack@eecs.umich.eduLSQUnit<Impl>::read(Request *req, T &data, int load_idx) 4837430Sgblack@eecs.umich.edu{ 4847430Sgblack@eecs.umich.edu DynInstPtr load_inst = loadQueue[load_idx]; 4857430Sgblack@eecs.umich.edu 4867430Sgblack@eecs.umich.edu assert(load_inst); 4877430Sgblack@eecs.umich.edu 4887430Sgblack@eecs.umich.edu assert(!load_inst->isExecuted()); 4897430Sgblack@eecs.umich.edu 4907430Sgblack@eecs.umich.edu // Make sure this isn't an uncacheable access 4917430Sgblack@eecs.umich.edu // A bit of a hackish way to get uncached accesses to work only if they're 4927430Sgblack@eecs.umich.edu // at the head of the LSQ and are ready to commit (at the head of the ROB 4937430Sgblack@eecs.umich.edu // too). 4947430Sgblack@eecs.umich.edu if (req->isUncacheable() && 4957430Sgblack@eecs.umich.edu (load_idx != loadHead || !load_inst->isAtCommit())) { 4967430Sgblack@eecs.umich.edu iewStage->rescheduleMemInst(load_inst); 4977430Sgblack@eecs.umich.edu ++lsqRescheduledLoads; 4987430Sgblack@eecs.umich.edu 4997430Sgblack@eecs.umich.edu // Must delete request now that it wasn't handed off to 5007430Sgblack@eecs.umich.edu // memory. This is quite ugly. @todo: Figure out the proper 5017430Sgblack@eecs.umich.edu // place to really handle request deletes. 5027430Sgblack@eecs.umich.edu delete req; 5037430Sgblack@eecs.umich.edu return TheISA::genMachineCheckFault(); 5047430Sgblack@eecs.umich.edu } 5057430Sgblack@eecs.umich.edu 5067430Sgblack@eecs.umich.edu // Check the SQ for any previous stores that might lead to forwarding 5077430Sgblack@eecs.umich.edu int store_idx = load_inst->sqIdx; 5087430Sgblack@eecs.umich.edu 5097430Sgblack@eecs.umich.edu int store_size = 0; 5107430Sgblack@eecs.umich.edu 5117430Sgblack@eecs.umich.edu DPRINTF(LSQUnit, "Read called, load idx: %i, store idx: %i, " 5127430Sgblack@eecs.umich.edu "storeHead: %i addr: %#x\n", 5137430Sgblack@eecs.umich.edu load_idx, store_idx, storeHead, req->getPaddr()); 5147430Sgblack@eecs.umich.edu 5157430Sgblack@eecs.umich.edu if (req->isLocked()) { 5167430Sgblack@eecs.umich.edu // Disable recording the result temporarily. Writing to misc 5177430Sgblack@eecs.umich.edu // regs normally updates the result, but this is not the 5187430Sgblack@eecs.umich.edu // desired behavior when handling store conditionals. 5197430Sgblack@eecs.umich.edu load_inst->recordResult = false; 5207430Sgblack@eecs.umich.edu TheISA::handleLockedRead(load_inst.get(), req); 5217430Sgblack@eecs.umich.edu load_inst->recordResult = true; 5227430Sgblack@eecs.umich.edu } 5237430Sgblack@eecs.umich.edu 5247430Sgblack@eecs.umich.edu while (store_idx != -1) { 5257430Sgblack@eecs.umich.edu // End once we've reached the top of the LSQ 5267430Sgblack@eecs.umich.edu if (store_idx == storeWBIdx) { 5277430Sgblack@eecs.umich.edu break; 5287430Sgblack@eecs.umich.edu } 5297430Sgblack@eecs.umich.edu 5307430Sgblack@eecs.umich.edu // Move the index to one younger 5317430Sgblack@eecs.umich.edu if (--store_idx < 0) 5327430Sgblack@eecs.umich.edu store_idx += SQEntries; 5337430Sgblack@eecs.umich.edu 5347430Sgblack@eecs.umich.edu assert(storeQueue[store_idx].inst); 5357430Sgblack@eecs.umich.edu 5367430Sgblack@eecs.umich.edu store_size = storeQueue[store_idx].size; 5377430Sgblack@eecs.umich.edu 5387430Sgblack@eecs.umich.edu if (store_size == 0) 5397430Sgblack@eecs.umich.edu continue; 5407430Sgblack@eecs.umich.edu else if (storeQueue[store_idx].inst->uncacheable()) 5417430Sgblack@eecs.umich.edu continue; 5427430Sgblack@eecs.umich.edu 5437430Sgblack@eecs.umich.edu assert(storeQueue[store_idx].inst->effAddrValid); 5447430Sgblack@eecs.umich.edu 5457430Sgblack@eecs.umich.edu // Check if the store data is within the lower and upper bounds of 5467430Sgblack@eecs.umich.edu // addresses that the request needs. 5477430Sgblack@eecs.umich.edu bool store_has_lower_limit = 5487430Sgblack@eecs.umich.edu req->getVaddr() >= storeQueue[store_idx].inst->effAddr; 5497430Sgblack@eecs.umich.edu bool store_has_upper_limit = 5507430Sgblack@eecs.umich.edu (req->getVaddr() + req->getSize()) <= 5517430Sgblack@eecs.umich.edu (storeQueue[store_idx].inst->effAddr + store_size); 5527430Sgblack@eecs.umich.edu bool lower_load_has_store_part = 5537430Sgblack@eecs.umich.edu req->getVaddr() < (storeQueue[store_idx].inst->effAddr + 5547430Sgblack@eecs.umich.edu store_size); 5557430Sgblack@eecs.umich.edu bool upper_load_has_store_part = 5567430Sgblack@eecs.umich.edu (req->getVaddr() + req->getSize()) > 5577430Sgblack@eecs.umich.edu storeQueue[store_idx].inst->effAddr; 5587430Sgblack@eecs.umich.edu 5597430Sgblack@eecs.umich.edu // If the store's data has all of the data needed, we can forward. 5607430Sgblack@eecs.umich.edu if ((store_has_lower_limit && store_has_upper_limit)) { 5617430Sgblack@eecs.umich.edu // Get shift amount for offset into the store's data. 5627430Sgblack@eecs.umich.edu int shift_amt = req->getVaddr() & (store_size - 1); 5637430Sgblack@eecs.umich.edu 5647430Sgblack@eecs.umich.edu memcpy(&data, storeQueue[store_idx].data + shift_amt, sizeof(T)); 5657430Sgblack@eecs.umich.edu 5667430Sgblack@eecs.umich.edu assert(!load_inst->memData); 5677430Sgblack@eecs.umich.edu load_inst->memData = new uint8_t[64]; 5687430Sgblack@eecs.umich.edu 5697430Sgblack@eecs.umich.edu memcpy(load_inst->memData, 5707430Sgblack@eecs.umich.edu storeQueue[store_idx].data + shift_amt, req->getSize()); 5717430Sgblack@eecs.umich.edu 5727430Sgblack@eecs.umich.edu DPRINTF(LSQUnit, "Forwarding from store idx %i to load to " 5737430Sgblack@eecs.umich.edu "addr %#x, data %#x\n", 5747430Sgblack@eecs.umich.edu store_idx, req->getVaddr(), data); 5757430Sgblack@eecs.umich.edu 5767430Sgblack@eecs.umich.edu PacketPtr data_pkt = new Packet(req, MemCmd::ReadReq, 5777430Sgblack@eecs.umich.edu Packet::Broadcast); 5787430Sgblack@eecs.umich.edu data_pkt->dataStatic(load_inst->memData); 5797430Sgblack@eecs.umich.edu 5807430Sgblack@eecs.umich.edu WritebackEvent *wb = new WritebackEvent(load_inst, data_pkt, this); 5817430Sgblack@eecs.umich.edu 5827430Sgblack@eecs.umich.edu // We'll say this has a 1 cycle load-store forwarding latency 5837430Sgblack@eecs.umich.edu // for now. 5847430Sgblack@eecs.umich.edu // @todo: Need to make this a parameter. 5857430Sgblack@eecs.umich.edu wb->schedule(curTick); 5867430Sgblack@eecs.umich.edu 5877430Sgblack@eecs.umich.edu ++lsqForwLoads; 5887430Sgblack@eecs.umich.edu return NoFault; 5897430Sgblack@eecs.umich.edu } else if ((store_has_lower_limit && lower_load_has_store_part) || 5907430Sgblack@eecs.umich.edu (store_has_upper_limit && upper_load_has_store_part) || 5917430Sgblack@eecs.umich.edu (lower_load_has_store_part && upper_load_has_store_part)) { 5927430Sgblack@eecs.umich.edu // This is the partial store-load forwarding case where a store 5937430Sgblack@eecs.umich.edu // has only part of the load's data. 5947430Sgblack@eecs.umich.edu 5957430Sgblack@eecs.umich.edu // If it's already been written back, then don't worry about 5967430Sgblack@eecs.umich.edu // stalling on it. 5977430Sgblack@eecs.umich.edu if (storeQueue[store_idx].completed) { 5987430Sgblack@eecs.umich.edu panic("Should not check one of these"); 5997430Sgblack@eecs.umich.edu continue; 6007430Sgblack@eecs.umich.edu } 6017430Sgblack@eecs.umich.edu 6027430Sgblack@eecs.umich.edu // Must stall load and force it to retry, so long as it's the oldest 6037430Sgblack@eecs.umich.edu // load that needs to do so. 6047430Sgblack@eecs.umich.edu if (!stalled || 6057430Sgblack@eecs.umich.edu (stalled && 6067430Sgblack@eecs.umich.edu load_inst->seqNum < 6077430Sgblack@eecs.umich.edu loadQueue[stallingLoadIdx]->seqNum)) { 6087430Sgblack@eecs.umich.edu stalled = true; 6097430Sgblack@eecs.umich.edu stallingStoreIsn = storeQueue[store_idx].inst->seqNum; 6107430Sgblack@eecs.umich.edu stallingLoadIdx = load_idx; 6117430Sgblack@eecs.umich.edu } 6127430Sgblack@eecs.umich.edu 6137430Sgblack@eecs.umich.edu // Tell IQ/mem dep unit that this instruction will need to be 6147430Sgblack@eecs.umich.edu // rescheduled eventually 6157430Sgblack@eecs.umich.edu iewStage->rescheduleMemInst(load_inst); 6167430Sgblack@eecs.umich.edu iewStage->decrWb(load_inst->seqNum); 6177430Sgblack@eecs.umich.edu load_inst->clearIssued(); 6187430Sgblack@eecs.umich.edu ++lsqRescheduledLoads; 6197430Sgblack@eecs.umich.edu 6207430Sgblack@eecs.umich.edu // Do not generate a writeback event as this instruction is not 6217430Sgblack@eecs.umich.edu // complete. 6227430Sgblack@eecs.umich.edu DPRINTF(LSQUnit, "Load-store forwarding mis-match. " 6237430Sgblack@eecs.umich.edu "Store idx %i to load addr %#x\n", 6247430Sgblack@eecs.umich.edu store_idx, req->getVaddr()); 6257430Sgblack@eecs.umich.edu 6267430Sgblack@eecs.umich.edu // Must delete request now that it wasn't handed off to 6277430Sgblack@eecs.umich.edu // memory. This is quite ugly. @todo: Figure out the 6287430Sgblack@eecs.umich.edu // proper place to really handle request deletes. 6297430Sgblack@eecs.umich.edu delete req; 6307430Sgblack@eecs.umich.edu 6317430Sgblack@eecs.umich.edu return NoFault; 6327430Sgblack@eecs.umich.edu } 6337430Sgblack@eecs.umich.edu } 6347430Sgblack@eecs.umich.edu 6357430Sgblack@eecs.umich.edu // If there's no forwarding case, then go access memory 6367430Sgblack@eecs.umich.edu DPRINTF(LSQUnit, "Doing memory access for inst [sn:%lli] PC %#x\n", 6377430Sgblack@eecs.umich.edu load_inst->seqNum, load_inst->readPC()); 6387430Sgblack@eecs.umich.edu 6397430Sgblack@eecs.umich.edu assert(!load_inst->memData); 6407430Sgblack@eecs.umich.edu load_inst->memData = new uint8_t[64]; 6417430Sgblack@eecs.umich.edu 6427430Sgblack@eecs.umich.edu ++usedPorts; 6437430Sgblack@eecs.umich.edu 6447430Sgblack@eecs.umich.edu // if we the cache is not blocked, do cache access 6457430Sgblack@eecs.umich.edu if (!lsq->cacheBlocked()) { 6467430Sgblack@eecs.umich.edu PacketPtr data_pkt = 6477430Sgblack@eecs.umich.edu new Packet(req, 6487430Sgblack@eecs.umich.edu (req->isLocked() ? 6497430Sgblack@eecs.umich.edu MemCmd::LoadLockedReq : MemCmd::ReadReq), 6507430Sgblack@eecs.umich.edu Packet::Broadcast); 6517430Sgblack@eecs.umich.edu data_pkt->dataStatic(load_inst->memData); 6527430Sgblack@eecs.umich.edu 6537430Sgblack@eecs.umich.edu LSQSenderState *state = new LSQSenderState; 6547430Sgblack@eecs.umich.edu state->isLoad = true; 6557430Sgblack@eecs.umich.edu state->idx = load_idx; 6567430Sgblack@eecs.umich.edu state->inst = load_inst; 6577430Sgblack@eecs.umich.edu data_pkt->senderState = state; 6587430Sgblack@eecs.umich.edu 6597430Sgblack@eecs.umich.edu if (!dcachePort->sendTiming(data_pkt)) { 6607430Sgblack@eecs.umich.edu // Delete state and data packet because a load retry 6617430Sgblack@eecs.umich.edu // initiates a pipeline restart; it does not retry. 6627430Sgblack@eecs.umich.edu delete state; 6637430Sgblack@eecs.umich.edu delete data_pkt->req; 6647430Sgblack@eecs.umich.edu delete data_pkt; 6657430Sgblack@eecs.umich.edu 6667430Sgblack@eecs.umich.edu req = NULL; 6677430Sgblack@eecs.umich.edu 6687430Sgblack@eecs.umich.edu // If the access didn't succeed, tell the LSQ by setting 6697430Sgblack@eecs.umich.edu // the retry thread id. 6707430Sgblack@eecs.umich.edu lsq->setRetryTid(lsqID); 6717430Sgblack@eecs.umich.edu } 6727430Sgblack@eecs.umich.edu } 6737430Sgblack@eecs.umich.edu 6747430Sgblack@eecs.umich.edu // If the cache was blocked, or has become blocked due to the access, 6757430Sgblack@eecs.umich.edu // handle it. 6767430Sgblack@eecs.umich.edu if (lsq->cacheBlocked()) { 6777430Sgblack@eecs.umich.edu if (req) 6787430Sgblack@eecs.umich.edu delete req; 6797430Sgblack@eecs.umich.edu 6807430Sgblack@eecs.umich.edu ++lsqCacheBlocked; 6817430Sgblack@eecs.umich.edu 6827430Sgblack@eecs.umich.edu iewStage->decrWb(load_inst->seqNum); 6837430Sgblack@eecs.umich.edu // There's an older load that's already going to squash. 6847430Sgblack@eecs.umich.edu if (isLoadBlocked && blockedLoadSeqNum < load_inst->seqNum) 6857430Sgblack@eecs.umich.edu return NoFault; 6867430Sgblack@eecs.umich.edu 6877430Sgblack@eecs.umich.edu // Record that the load was blocked due to memory. This 6887430Sgblack@eecs.umich.edu // load will squash all instructions after it, be 6897430Sgblack@eecs.umich.edu // refetched, and re-executed. 6907430Sgblack@eecs.umich.edu isLoadBlocked = true; 6917430Sgblack@eecs.umich.edu loadBlockedHandled = false; 6927430Sgblack@eecs.umich.edu blockedLoadSeqNum = load_inst->seqNum; 6937430Sgblack@eecs.umich.edu // No fault occurred, even though the interface is blocked. 6947430Sgblack@eecs.umich.edu return NoFault; 6957430Sgblack@eecs.umich.edu } 6967430Sgblack@eecs.umich.edu 6977430Sgblack@eecs.umich.edu return NoFault; 6987430Sgblack@eecs.umich.edu} 6997430Sgblack@eecs.umich.edu 7007430Sgblack@eecs.umich.edutemplate <class Impl> 7017430Sgblack@eecs.umich.edutemplate <class T> 7027430Sgblack@eecs.umich.eduFault 7037430Sgblack@eecs.umich.eduLSQUnit<Impl>::write(Request *req, T &data, int store_idx) 7047430Sgblack@eecs.umich.edu{ 7057430Sgblack@eecs.umich.edu assert(storeQueue[store_idx].inst); 7067430Sgblack@eecs.umich.edu 7077430Sgblack@eecs.umich.edu DPRINTF(LSQUnit, "Doing write to store idx %i, addr %#x data %#x" 7087430Sgblack@eecs.umich.edu " | storeHead:%i [sn:%i]\n", 7097430Sgblack@eecs.umich.edu store_idx, req->getPaddr(), data, storeHead, 7107430Sgblack@eecs.umich.edu storeQueue[store_idx].inst->seqNum); 7117430Sgblack@eecs.umich.edu 7127430Sgblack@eecs.umich.edu storeQueue[store_idx].req = req; 7137430Sgblack@eecs.umich.edu storeQueue[store_idx].size = sizeof(T); 7147430Sgblack@eecs.umich.edu assert(sizeof(T) <= sizeof(storeQueue[store_idx].data)); 7157430Sgblack@eecs.umich.edu 7167430Sgblack@eecs.umich.edu T gData = htog(data); 7177430Sgblack@eecs.umich.edu memcpy(storeQueue[store_idx].data, &gData, sizeof(T)); 7187430Sgblack@eecs.umich.edu 7197430Sgblack@eecs.umich.edu // This function only writes the data to the store queue, so no fault 7207430Sgblack@eecs.umich.edu // can happen here. 7217430Sgblack@eecs.umich.edu return NoFault; 7227430Sgblack@eecs.umich.edu} 7237430Sgblack@eecs.umich.edu 7247430Sgblack@eecs.umich.edu#endif // __CPU_O3_LSQ_UNIT_HH__ 7257430Sgblack@eecs.umich.edu