lsq_unit.hh revision 4395
12SN/A/* 27338SAli.Saidi@ARM.com * Copyright (c) 2004-2006 The Regents of The University of Michigan 37338SAli.Saidi@ARM.com * All rights reserved. 47338SAli.Saidi@ARM.com * 57338SAli.Saidi@ARM.com * Redistribution and use in source and binary forms, with or without 67338SAli.Saidi@ARM.com * modification, are permitted provided that the following conditions are 77338SAli.Saidi@ARM.com * met: redistributions of source code must retain the above copyright 87338SAli.Saidi@ARM.com * notice, this list of conditions and the following disclaimer; 97338SAli.Saidi@ARM.com * redistributions in binary form must reproduce the above copyright 107338SAli.Saidi@ARM.com * notice, this list of conditions and the following disclaimer in the 117338SAli.Saidi@ARM.com * documentation and/or other materials provided with the distribution; 127338SAli.Saidi@ARM.com * neither the name of the copyright holders nor the names of its 137338SAli.Saidi@ARM.com * contributors may be used to endorse or promote products derived from 141762SN/A * this software without specific prior written permission. 152SN/A * 162SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 172SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 182SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 192SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 202SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 212SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 222SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 232SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 242SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 252SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 262SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 272SN/A * 282SN/A * Authors: Kevin Lim 292SN/A * Korey Sewell 302SN/A */ 312SN/A 322SN/A#ifndef __CPU_O3_LSQ_UNIT_HH__ 332SN/A#define __CPU_O3_LSQ_UNIT_HH__ 342SN/A 352SN/A#include <algorithm> 362SN/A#include <cstring> 372SN/A#include <map> 382SN/A#include <queue> 392665Ssaidi@eecs.umich.edu 402665Ssaidi@eecs.umich.edu#include "arch/faults.hh" 412SN/A#include "arch/locked_mem.hh" 422SN/A#include "config/full_system.hh" 436216Snate@binkert.org#include "base/hashmap.hh" 442439SN/A#include "cpu/inst_seq.hh" 458229Snate@binkert.org#include "mem/packet.hh" 466216Snate@binkert.org#include "mem/port.hh" 47146SN/A 48146SN/A/** 49146SN/A * Class that implements the actual LQ and SQ for each specific 50146SN/A * thread. Both are circular queues; load entries are freed upon 51146SN/A * committing, while store entries are freed once they writeback. The 52146SN/A * LSQUnit tracks if there are memory ordering violations, and also 536216Snate@binkert.org * detects partial load to store forwarding cases (a store only has 546658Snate@binkert.org * part of a load's data) that requires the load to wait until the 558229Snate@binkert.org * store writes back. In the former case it holds onto the instruction 561717SN/A * until the dependence unit looks at it, and in the latter it stalls 57146SN/A * the LSQ until the store writes back. At that point the load is 581977SN/A * replayed. 592683Sktlim@umich.edu */ 601717SN/Atemplate <class Impl> 61146SN/Aclass LSQUnit { 622683Sktlim@umich.edu protected: 638232Snate@binkert.org typedef TheISA::IntReg IntReg; 648232Snate@binkert.org public: 658232Snate@binkert.org typedef typename Impl::Params Params; 663348Sbinkertn@umich.edu typedef typename Impl::O3CPU O3CPU; 676105Ssteve.reinhardt@amd.com typedef typename Impl::DynInstPtr DynInstPtr; 686216Snate@binkert.org typedef typename Impl::CPUPol::IEW IEW; 692036SN/A typedef typename Impl::CPUPol::LSQ LSQ; 70146SN/A typedef typename Impl::CPUPol::IssueStruct IssueStruct; 7156SN/A 7256SN/A public: 73695SN/A /** Constructs an LSQ unit. init() must be called prior to use. */ 742901Ssaidi@eecs.umich.edu LSQUnit(); 752SN/A 761858SN/A /** Initializes the LSQ unit with the specified number of entries. */ 773565Sgblack@eecs.umich.edu void init(O3CPU *cpu_ptr, IEW *iew_ptr, Params *params, LSQ *lsq_ptr, 783565Sgblack@eecs.umich.edu unsigned maxLQEntries, unsigned maxSQEntries, unsigned id); 792171SN/A 802170SN/A /** Returns the name of the LSQ unit. */ 81146SN/A std::string name() const; 822462SN/A 83146SN/A /** Registers statistics. */ 842SN/A void regStats(); 852SN/A 862449SN/A /** Sets the pointer to the dcache port. */ 871355SN/A void setDcachePort(Port *dcache_port); 885529Snate@binkert.org 894495Sacolyte@umich.edu /** Switches out LSQ unit. */ 90224SN/A void switchOut(); 911858SN/A 922683Sktlim@umich.edu /** Takes over from another CPU's thread. */ 932420SN/A void takeOverFrom(); 945529Snate@binkert.org 956331Sgblack@eecs.umich.edu /** Returns if the LSQ is switched out. */ 962420SN/A bool isSwitchedOut() { return switchedOut; } 972SN/A 986029Ssteve.reinhardt@amd.com /** Ticks the LSQ unit, which in this case only resets the number of 992672Sktlim@umich.edu * used cache ports. 1002683Sktlim@umich.edu * @todo: Move the number of used ports up to the LSQ level so it can 1012SN/A * be shared by all LSQ units. 1022SN/A */ 103334SN/A void tick() { usedPorts = 0; } 104140SN/A 105334SN/A /** Inserts an instruction. */ 1062SN/A void insert(DynInstPtr &inst); 1072SN/A /** Inserts a load instruction. */ 1082SN/A void insertLoad(DynInstPtr &load_inst); 1092680Sktlim@umich.edu /** Inserts a store instruction. */ 1104377Sgblack@eecs.umich.edu void insertStore(DynInstPtr &store_inst); 1115169Ssaidi@eecs.umich.edu 1124377Sgblack@eecs.umich.edu /** Executes a load instruction. */ 1134377Sgblack@eecs.umich.edu Fault executeLoad(DynInstPtr &inst); 1142SN/A 1152SN/A Fault executeLoad(int lq_idx) { panic("Not implemented"); return NoFault; } 1162623SN/A /** Executes a store instruction. */ 1172SN/A Fault executeStore(DynInstPtr &inst); 1182SN/A 1192SN/A /** Commits the head load. */ 120180SN/A void commitLoad(); 1212623SN/A /** Commits loads older than a specific sequence number. */ 122393SN/A void commitLoads(InstSeqNum &youngest_inst); 123393SN/A 124393SN/A /** Commits stores older than a specific sequence number. */ 125393SN/A void commitStores(InstSeqNum &youngest_inst); 126384SN/A 127384SN/A /** Writes back stores. */ 128393SN/A void writebackStores(); 1292623SN/A 130393SN/A /** Completes the data access that has been returned from the 131393SN/A * memory system. */ 132393SN/A void completeDataAccess(PacketPtr pkt); 133393SN/A 134384SN/A /** Clears all the entries in the LQ. */ 135189SN/A void clearLQ(); 136189SN/A 1372623SN/A /** Clears all the entries in the SQ. */ 1382SN/A void clearSQ(); 139729SN/A 140334SN/A /** Resizes the LQ to a given size. */ 1412SN/A void resizeLQ(unsigned size); 1422SN/A 1432SN/A /** Resizes the SQ to a given size. */ 1442SN/A void resizeSQ(unsigned size); 1452SN/A 1462SN/A /** Squashes all instructions younger than a specific sequence number. */ 1472SN/A void squash(const InstSeqNum &squashed_num); 1487897Shestness@cs.utexas.edu 1497897Shestness@cs.utexas.edu /** Returns if there is a memory ordering violation. Value is reset upon 1507897Shestness@cs.utexas.edu * call to getMemDepViolator(). 1517897Shestness@cs.utexas.edu */ 1527897Shestness@cs.utexas.edu bool violation() { return memDepViolator; } 1537897Shestness@cs.utexas.edu 1547897Shestness@cs.utexas.edu /** Returns the memory ordering violator. */ 1557897Shestness@cs.utexas.edu DynInstPtr getMemDepViolator(); 1567897Shestness@cs.utexas.edu 1577897Shestness@cs.utexas.edu /** Returns if a load became blocked due to the memory system. */ 1587897Shestness@cs.utexas.edu bool loadBlocked() 1597897Shestness@cs.utexas.edu { return isLoadBlocked; } 1607897Shestness@cs.utexas.edu 1617897Shestness@cs.utexas.edu /** Clears the signal that a load became blocked. */ 1627897Shestness@cs.utexas.edu void clearLoadBlocked() 1637897Shestness@cs.utexas.edu { isLoadBlocked = false; } 1647897Shestness@cs.utexas.edu 1657897Shestness@cs.utexas.edu /** Returns if the blocked load was handled. */ 1667897Shestness@cs.utexas.edu bool isLoadBlockedHandled() 1677897Shestness@cs.utexas.edu { return loadBlockedHandled; } 1687897Shestness@cs.utexas.edu 1697897Shestness@cs.utexas.edu /** Records the blocked load as being handled. */ 1707897Shestness@cs.utexas.edu void setLoadBlockedHandled() 1717897Shestness@cs.utexas.edu { loadBlockedHandled = true; } 1727897Shestness@cs.utexas.edu 1737897Shestness@cs.utexas.edu /** Returns the number of free entries (min of free LQ and SQ entries). */ 1747897Shestness@cs.utexas.edu unsigned numFreeEntries(); 1757897Shestness@cs.utexas.edu 1767897Shestness@cs.utexas.edu /** Returns the number of loads ready to execute. */ 1777897Shestness@cs.utexas.edu int numLoadsReady(); 1787897Shestness@cs.utexas.edu 1797897Shestness@cs.utexas.edu /** Returns the number of loads in the LQ. */ 1807897Shestness@cs.utexas.edu int numLoads() { return loads; } 1817897Shestness@cs.utexas.edu 1827897Shestness@cs.utexas.edu /** Returns the number of stores in the SQ. */ 1837897Shestness@cs.utexas.edu int numStores() { return stores; } 1847897Shestness@cs.utexas.edu 1857897Shestness@cs.utexas.edu /** Returns if either the LQ or SQ is full. */ 1867897Shestness@cs.utexas.edu bool isFull() { return lqFull() || sqFull(); } 1877897Shestness@cs.utexas.edu 1887897Shestness@cs.utexas.edu /** Returns if the LQ is full. */ 1897897Shestness@cs.utexas.edu bool lqFull() { return loads >= (LQEntries - 1); } 1907897Shestness@cs.utexas.edu 1917897Shestness@cs.utexas.edu /** Returns if the SQ is full. */ 1927897Shestness@cs.utexas.edu bool sqFull() { return stores >= (SQEntries - 1); } 1937897Shestness@cs.utexas.edu 1947897Shestness@cs.utexas.edu /** Returns the number of instructions in the LSQ. */ 1957897Shestness@cs.utexas.edu unsigned getCount() { return loads + stores; } 1967897Shestness@cs.utexas.edu 1977897Shestness@cs.utexas.edu /** Returns if there are any stores to writeback. */ 1982SN/A bool hasStoresToWB() { return storesToWB; } 1997897Shestness@cs.utexas.edu 2007897Shestness@cs.utexas.edu /** Returns the number of stores to writeback. */ 2017897Shestness@cs.utexas.edu int numStoresToWB() { return storesToWB; } 2027897Shestness@cs.utexas.edu 2037897Shestness@cs.utexas.edu /** Returns if the LSQ unit will writeback on this cycle. */ 2047897Shestness@cs.utexas.edu bool willWB() { return storeQueue[storeWBIdx].canWB && 2057897Shestness@cs.utexas.edu !storeQueue[storeWBIdx].completed && 2067897Shestness@cs.utexas.edu !isStoreBlocked; } 2077897Shestness@cs.utexas.edu 2087897Shestness@cs.utexas.edu /** Handles doing the retry. */ 2097897Shestness@cs.utexas.edu void recvRetry(); 2107897Shestness@cs.utexas.edu 2112SN/A private: 2122SN/A /** Writes back the instruction, sending it to IEW. */ 2131001SN/A void writeback(DynInstPtr &inst, PacketPtr pkt); 2141001SN/A 2151001SN/A /** Handles completing the send of a store to memory. */ 2161001SN/A void storePostSend(PacketPtr pkt); 2171001SN/A 2182SN/A /** Completes the store at the specified index. */ 2192SN/A void completeStore(int store_idx); 2202SN/A 2212SN/A /** Increments the given store index (circular queue). */ 2222SN/A inline void incrStIdx(int &store_idx); 2237897Shestness@cs.utexas.edu /** Decrements the given store index (circular queue). */ 2247897Shestness@cs.utexas.edu inline void decrStIdx(int &store_idx); 2257897Shestness@cs.utexas.edu /** Increments the given load index (circular queue). */ 2267897Shestness@cs.utexas.edu inline void incrLdIdx(int &load_idx); 2277897Shestness@cs.utexas.edu /** Decrements the given load index (circular queue). */ 2287897Shestness@cs.utexas.edu inline void decrLdIdx(int &load_idx); 2297897Shestness@cs.utexas.edu 2307897Shestness@cs.utexas.edu public: 2317897Shestness@cs.utexas.edu /** Debugging function to dump instructions in the LSQ. */ 2327897Shestness@cs.utexas.edu void dumpInsts(); 2332SN/A 2342SN/A private: 2352SN/A /** Pointer to the CPU. */ 2362SN/A O3CPU *cpu; 2372SN/A 2382SN/A /** Pointer to the IEW stage. */ 2392SN/A IEW *iewStage; 2402SN/A 2412SN/A /** Pointer to the LSQ. */ 2422SN/A LSQ *lsq; 2432SN/A 2442SN/A /** Pointer to the dcache port. Used only for sending. */ 2452390SN/A Port *dcachePort; 2462390SN/A 2472390SN/A /** Derived class to hold any sender state the LSQ needs. */ 2482390SN/A class LSQSenderState : public Packet::SenderState 2492390SN/A { 2502390SN/A public: 2512390SN/A /** Default constructor. */ 2522390SN/A LSQSenderState() 2532390SN/A : noWB(false) 2542390SN/A { } 2552390SN/A 2562390SN/A /** Instruction who initiated the access to memory. */ 257385SN/A DynInstPtr inst; 2587897Shestness@cs.utexas.edu /** Whether or not it is a load. */ 2597897Shestness@cs.utexas.edu bool isLoad; 2602SN/A /** The LQ/SQ index of the instruction. */ 2612SN/A int idx; 2622SN/A /** Whether or not the instruction will need to writeback. */ 2632623SN/A bool noWB; 264334SN/A }; 2652361SN/A 2665496Ssaidi@eecs.umich.edu /** Writeback event, specifically for when stores forward data to loads. */ 267334SN/A class WritebackEvent : public Event { 268334SN/A public: 269334SN/A /** Constructs a writeback event. */ 2702623SN/A WritebackEvent(DynInstPtr &_inst, PacketPtr pkt, LSQUnit *lsq_ptr); 2712SN/A 2725496Ssaidi@eecs.umich.edu /** Processes the writeback event. */ 273921SN/A void process(); 2742915Sktlim@umich.edu 2752915Sktlim@umich.edu /** Returns the description of this event. */ 2762683Sktlim@umich.edu const char *description(); 2772SN/A 2782SN/A private: 2792SN/A /** Instruction whose results are being written back. */ 2802623SN/A DynInstPtr inst; 2812SN/A 2825496Ssaidi@eecs.umich.edu /** The packet that would have been sent to memory. */ 283921SN/A PacketPtr pkt; 2842915Sktlim@umich.edu 2852915Sktlim@umich.edu /** The pointer to the LSQ unit that issued the store. */ 2862SN/A LSQUnit<Impl> *lsqPtr; 2872SN/A }; 2882SN/A 2896221Snate@binkert.org public: 2902SN/A struct SQEntry { 2912SN/A /** Constructs an empty store queue entry. */ 2922SN/A SQEntry() 2931858SN/A : inst(NULL), req(NULL), size(0), 2942SN/A canWB(0), committed(0), completed(0) 2952623SN/A { 2962SN/A std::memset(data, 0, sizeof(data)); 2972680Sktlim@umich.edu } 2982SN/A 2992SN/A /** Constructs a store queue entry for a given instruction. */ 3002SN/A SQEntry(DynInstPtr &_inst) 3011858SN/A : inst(_inst), req(NULL), size(0), 3022SN/A canWB(0), committed(0), completed(0) 3035807Snate@binkert.org { 3042SN/A std::memset(data, 0, sizeof(data)); 3055807Snate@binkert.org } 3065807Snate@binkert.org 3072SN/A /** The store instruction. */ 3085807Snate@binkert.org DynInstPtr inst; 3095807Snate@binkert.org /** The request for the store. */ 3102SN/A RequestPtr req; 3112SN/A /** The size of the store. */ 3122SN/A int size; 3132SN/A /** The store data. */ 3142623SN/A char data[sizeof(IntReg)]; 3152SN/A /** Whether or not the store can writeback. */ 3161858SN/A bool canWB; 3175704Snate@binkert.org /** Whether or not the store is committed. */ 3185647Sgblack@eecs.umich.edu bool committed; 3192SN/A /** Whether or not the store is completed. */ 3203520Sgblack@eecs.umich.edu bool completed; 3217338SAli.Saidi@ARM.com }; 3225647Sgblack@eecs.umich.edu 3233520Sgblack@eecs.umich.edu private: 3247408Sgblack@eecs.umich.edu /** The LSQUnit thread id. */ 3252SN/A unsigned lsqID; 3262SN/A 3272SN/A /** The store queue. */ 3282623SN/A std::vector<SQEntry> storeQueue; 3292SN/A 3302623SN/A /** The load queue. */ 3315894Sgblack@eecs.umich.edu std::vector<DynInstPtr> loadQueue; 3322662Sstever@eecs.umich.edu 3332623SN/A /** The number of LQ entries, plus a sentinel entry (circular queue). 3347720Sgblack@eecs.umich.edu * @todo: Consider having var that records the true number of LQ entries. 3354495Sacolyte@umich.edu */ 3362623SN/A unsigned LQEntries; 3377720Sgblack@eecs.umich.edu /** The number of SQ entries, plus a sentinel entry (circular queue). 3382623SN/A * @todo: Consider having var that records the true number of SQ entries. 3397720Sgblack@eecs.umich.edu */ 3407720Sgblack@eecs.umich.edu unsigned SQEntries; 3412623SN/A 3422623SN/A /** The number of load instructions in the LQ. */ 3432623SN/A int loads; 3442623SN/A /** The number of store instructions in the SQ. */ 3452623SN/A int stores; 3462623SN/A /** The number of store instructions in the SQ waiting to writeback. */ 3472SN/A int storesToWB; 3482683Sktlim@umich.edu 3492427SN/A /** The index of the head instruction in the LQ. */ 3502683Sktlim@umich.edu int loadHead; 3512427SN/A /** The index of the tail instruction in the LQ. */ 3522SN/A int loadTail; 3532623SN/A 3542623SN/A /** The index of the head instruction in the SQ. */ 3557897Shestness@cs.utexas.edu int storeHead; 3562SN/A /** The index of the first instruction that may be ready to be 3572623SN/A * written back, and has not yet been written back. 3582623SN/A */ 3594377Sgblack@eecs.umich.edu int storeWBIdx; 3607720Sgblack@eecs.umich.edu /** The index of the tail instruction in the SQ. */ 3614377Sgblack@eecs.umich.edu int storeTail; 3627720Sgblack@eecs.umich.edu 3635665Sgblack@eecs.umich.edu /// @todo Consider moving to a more advanced model with write vs read ports 3647720Sgblack@eecs.umich.edu /** The number of cache ports available each cycle. */ 3657720Sgblack@eecs.umich.edu int cachePorts; 3665665Sgblack@eecs.umich.edu 3675665Sgblack@eecs.umich.edu /** The number of used cache ports in this cycle. */ 3684181Sgblack@eecs.umich.edu int usedPorts; 3694181Sgblack@eecs.umich.edu 3704181Sgblack@eecs.umich.edu /** Is the LSQ switched out. */ 3714182Sgblack@eecs.umich.edu bool switchedOut; 3724182Sgblack@eecs.umich.edu 3734182Sgblack@eecs.umich.edu //list<InstSeqNum> mshrSeqNums; 3747720Sgblack@eecs.umich.edu 3754593Sgblack@eecs.umich.edu /** Wire to read information from the issue stage time queue. */ 3767720Sgblack@eecs.umich.edu typename TimeBuffer<IssueStruct>::wire fromIssue; 3774593Sgblack@eecs.umich.edu 3784593Sgblack@eecs.umich.edu /** Whether or not the LSQ is stalled. */ 3794377Sgblack@eecs.umich.edu bool stalled; 3804377Sgblack@eecs.umich.edu /** The store that causes the stall due to partial store to load 3814377Sgblack@eecs.umich.edu * forwarding. 3824377Sgblack@eecs.umich.edu */ 3834377Sgblack@eecs.umich.edu InstSeqNum stallingStoreIsn; 3847720Sgblack@eecs.umich.edu /** The index of the above store. */ 3857720Sgblack@eecs.umich.edu int stallingLoadIdx; 3867720Sgblack@eecs.umich.edu 3874377Sgblack@eecs.umich.edu /** The packet that needs to be retried. */ 3884377Sgblack@eecs.umich.edu PacketPtr retryPkt; 3894377Sgblack@eecs.umich.edu 3904377Sgblack@eecs.umich.edu /** Whehter or not a store is blocked due to the memory system. */ 3914181Sgblack@eecs.umich.edu bool isStoreBlocked; 3924181Sgblack@eecs.umich.edu 3934181Sgblack@eecs.umich.edu /** Whether or not a load is blocked due to the memory system. */ 3944539Sgblack@eecs.umich.edu bool isLoadBlocked; 3953276Sgblack@eecs.umich.edu 3967720Sgblack@eecs.umich.edu /** Has the blocked load been handled. */ 3973280Sgblack@eecs.umich.edu bool loadBlockedHandled; 3983280Sgblack@eecs.umich.edu 3993276Sgblack@eecs.umich.edu /** The sequence number of the blocked load. */ 4003276Sgblack@eecs.umich.edu InstSeqNum blockedLoadSeqNum; 4013276Sgblack@eecs.umich.edu 4027720Sgblack@eecs.umich.edu /** The oldest load that caused a memory ordering violation. */ 4033276Sgblack@eecs.umich.edu DynInstPtr memDepViolator; 4043276Sgblack@eecs.umich.edu 4054181Sgblack@eecs.umich.edu // Will also need how many read/write ports the Dcache has. Or keep track 4064181Sgblack@eecs.umich.edu // of that in stage that is one level up, and only call executeLoad/Store 4074181Sgblack@eecs.umich.edu // the appropriate number of times. 4084522Ssaidi@eecs.umich.edu /** Total number of loads forwaded from LSQ stores. */ 4097823Ssteve.reinhardt@amd.com Stats::Scalar<> lsqForwLoads; 4107720Sgblack@eecs.umich.edu 4112470SN/A /** Total number of loads ignored due to invalid addresses. */ 4124181Sgblack@eecs.umich.edu Stats::Scalar<> invAddrLoads; 4134181Sgblack@eecs.umich.edu 4144522Ssaidi@eecs.umich.edu /** Total number of squashed loads. */ 4154181Sgblack@eecs.umich.edu Stats::Scalar<> lsqSquashedLoads; 4162623SN/A 4172623SN/A /** Total number of responses from the memory system that are 4182623SN/A * ignored due to the instruction already being squashed. */ 4192623SN/A Stats::Scalar<> lsqIgnoredResponses; 4202623SN/A 4217720Sgblack@eecs.umich.edu /** Tota number of memory ordering violations. */ 4227720Sgblack@eecs.umich.edu Stats::Scalar<> lsqMemOrderViolation; 4237720Sgblack@eecs.umich.edu 4247720Sgblack@eecs.umich.edu /** Total number of squashed stores. */ 4252623SN/A Stats::Scalar<> lsqSquashedStores; 4267720Sgblack@eecs.umich.edu 4273577Sgblack@eecs.umich.edu /** Total number of software prefetches ignored due to invalid addresses. */ 4287720Sgblack@eecs.umich.edu Stats::Scalar<> invAddrSwpfs; 4295086Sgblack@eecs.umich.edu 4302623SN/A /** Ready loads blocked due to partial store-forwarding. */ 4312683Sktlim@umich.edu Stats::Scalar<> lsqBlockedLoads; 4322623SN/A 4332420SN/A /** Number of loads that were rescheduled. */ 4342SN/A Stats::Scalar<> lsqRescheduledLoads; 4352623SN/A 4362623SN/A /** Number of times the LSQ is blocked due to the cache. */ 4372SN/A Stats::Scalar<> lsqCacheBlocked; 4382SN/A 4392623SN/A public: 4402623SN/A /** Executes the load at the given index. */ 4412623SN/A template <class T> 4422623SN/A Fault read(Request *req, T &data, int load_idx); 4432SN/A 4445953Ssaidi@eecs.umich.edu /** Executes the store at the given index. */ 4457720Sgblack@eecs.umich.edu template <class T> 4465953Ssaidi@eecs.umich.edu Fault write(Request *req, T &data, int store_idx); 4475953Ssaidi@eecs.umich.edu 4487897Shestness@cs.utexas.edu /** Returns the index of the head load instruction. */ 4497897Shestness@cs.utexas.edu int getLoadHead() { return loadHead; } 4507897Shestness@cs.utexas.edu /** Returns the sequence number of the head load instruction. */ 4517897Shestness@cs.utexas.edu InstSeqNum getLoadHeadSeqNum() 4527897Shestness@cs.utexas.edu { 4537897Shestness@cs.utexas.edu if (loadQueue[loadHead]) { 4547897Shestness@cs.utexas.edu return loadQueue[loadHead]->seqNum; 4557897Shestness@cs.utexas.edu } else { 4567897Shestness@cs.utexas.edu return 0; 4577897Shestness@cs.utexas.edu } 4587897Shestness@cs.utexas.edu 4597897Shestness@cs.utexas.edu } 4607897Shestness@cs.utexas.edu 4617897Shestness@cs.utexas.edu /** Returns the index of the head store instruction. */ 4627897Shestness@cs.utexas.edu int getStoreHead() { return storeHead; } 4637897Shestness@cs.utexas.edu /** Returns the sequence number of the head store instruction. */ 4647897Shestness@cs.utexas.edu InstSeqNum getStoreHeadSeqNum() 4657897Shestness@cs.utexas.edu { 4667897Shestness@cs.utexas.edu if (storeQueue[storeHead].inst) { 4677897Shestness@cs.utexas.edu return storeQueue[storeHead].inst->seqNum; 4687897Shestness@cs.utexas.edu } else { 4697897Shestness@cs.utexas.edu return 0; 4707897Shestness@cs.utexas.edu } 4717897Shestness@cs.utexas.edu 4727897Shestness@cs.utexas.edu } 4737897Shestness@cs.utexas.edu 4747897Shestness@cs.utexas.edu /** Returns whether or not the LSQ unit is stalled. */ 4757897Shestness@cs.utexas.edu bool isStalled() { return stalled; } 4767897Shestness@cs.utexas.edu}; 4777897Shestness@cs.utexas.edu 4787897Shestness@cs.utexas.edutemplate <class Impl> 4797897Shestness@cs.utexas.edutemplate <class T> 4807897Shestness@cs.utexas.eduFault 4817720Sgblack@eecs.umich.eduLSQUnit<Impl>::read(Request *req, T &data, int load_idx) 4822644Sstever@eecs.umich.edu{ 4832644Sstever@eecs.umich.edu DynInstPtr load_inst = loadQueue[load_idx]; 4844046Sbinkertn@umich.edu 4854046Sbinkertn@umich.edu assert(load_inst); 4864046Sbinkertn@umich.edu 4872644Sstever@eecs.umich.edu assert(!load_inst->isExecuted()); 4882623SN/A 4892SN/A // Make sure this isn't an uncacheable access 4902SN/A // A bit of a hackish way to get uncached accesses to work only if they're 4912623SN/A // at the head of the LSQ and are ready to commit (at the head of the ROB 4922623SN/A // too). 4932623SN/A if (req->isUncacheable() && 4944377Sgblack@eecs.umich.edu (load_idx != loadHead || !load_inst->isAtCommit())) { 4954377Sgblack@eecs.umich.edu iewStage->rescheduleMemInst(load_inst); 4962090SN/A ++lsqRescheduledLoads; 4973905Ssaidi@eecs.umich.edu 4987678Sgblack@eecs.umich.edu // Must delete request now that it wasn't handed off to 4995120Sgblack@eecs.umich.edu // memory. This is quite ugly. @todo: Figure out the proper 5004377Sgblack@eecs.umich.edu // place to really handle request deletes. 5017720Sgblack@eecs.umich.edu delete req; 5027720Sgblack@eecs.umich.edu return TheISA::genMachineCheckFault(); 5037720Sgblack@eecs.umich.edu } 5047720Sgblack@eecs.umich.edu 5057720Sgblack@eecs.umich.edu // Check the SQ for any previous stores that might lead to forwarding 5067720Sgblack@eecs.umich.edu int store_idx = load_inst->sqIdx; 5073276Sgblack@eecs.umich.edu 5082SN/A int store_size = 0; 5092SN/A 5102SN/A DPRINTF(LSQUnit, "Read called, load idx: %i, store idx: %i, " 5115250Sksewell@umich.edu "storeHead: %i addr: %#x\n", 5125222Sksewell@umich.edu load_idx, store_idx, storeHead, req->getPaddr()); 5135222Sksewell@umich.edu 5145222Sksewell@umich.edu if (req->isLocked()) { 5155222Sksewell@umich.edu // Disable recording the result temporarily. Writing to misc 5165222Sksewell@umich.edu // regs normally updates the result, but this is not the 5175222Sksewell@umich.edu // desired behavior when handling store conditionals. 5185222Sksewell@umich.edu load_inst->recordResult = false; 5195222Sksewell@umich.edu TheISA::handleLockedRead(load_inst.get(), req); 5205222Sksewell@umich.edu load_inst->recordResult = true; 5215222Sksewell@umich.edu } 5225222Sksewell@umich.edu 5235222Sksewell@umich.edu while (store_idx != -1) { 5245222Sksewell@umich.edu // End once we've reached the top of the LSQ 5255222Sksewell@umich.edu if (store_idx == storeWBIdx) { 5265222Sksewell@umich.edu break; 5275222Sksewell@umich.edu } 5285222Sksewell@umich.edu 5295222Sksewell@umich.edu // Move the index to one younger 5305222Sksewell@umich.edu if (--store_idx < 0) 5315222Sksewell@umich.edu store_idx += SQEntries; 5325222Sksewell@umich.edu 5335222Sksewell@umich.edu assert(storeQueue[store_idx].inst); 5345222Sksewell@umich.edu 5355222Sksewell@umich.edu store_size = storeQueue[store_idx].size; 5365222Sksewell@umich.edu 5375222Sksewell@umich.edu if (store_size == 0) 5385222Sksewell@umich.edu continue; 5395222Sksewell@umich.edu else if (storeQueue[store_idx].inst->uncacheable()) 5405222Sksewell@umich.edu continue; 5415222Sksewell@umich.edu 5425222Sksewell@umich.edu assert(storeQueue[store_idx].inst->effAddrValid); 5435222Sksewell@umich.edu 5445250Sksewell@umich.edu // Check if the store data is within the lower and upper bounds of 545 // addresses that the request needs. 546 bool store_has_lower_limit = 547 req->getVaddr() >= storeQueue[store_idx].inst->effAddr; 548 bool store_has_upper_limit = 549 (req->getVaddr() + req->getSize()) <= 550 (storeQueue[store_idx].inst->effAddr + store_size); 551 bool lower_load_has_store_part = 552 req->getVaddr() < (storeQueue[store_idx].inst->effAddr + 553 store_size); 554 bool upper_load_has_store_part = 555 (req->getVaddr() + req->getSize()) > 556 storeQueue[store_idx].inst->effAddr; 557 558 // If the store's data has all of the data needed, we can forward. 559 if ((store_has_lower_limit && store_has_upper_limit)) { 560 // Get shift amount for offset into the store's data. 561 int shift_amt = req->getVaddr() & (store_size - 1); 562 563 memcpy(&data, storeQueue[store_idx].data + shift_amt, sizeof(T)); 564 565 assert(!load_inst->memData); 566 load_inst->memData = new uint8_t[64]; 567 568 memcpy(load_inst->memData, 569 storeQueue[store_idx].data + shift_amt, req->getSize()); 570 571 DPRINTF(LSQUnit, "Forwarding from store idx %i to load to " 572 "addr %#x, data %#x\n", 573 store_idx, req->getVaddr(), data); 574 575 PacketPtr data_pkt = new Packet(req, MemCmd::ReadReq, 576 Packet::Broadcast); 577 data_pkt->dataStatic(load_inst->memData); 578 579 WritebackEvent *wb = new WritebackEvent(load_inst, data_pkt, this); 580 581 // We'll say this has a 1 cycle load-store forwarding latency 582 // for now. 583 // @todo: Need to make this a parameter. 584 wb->schedule(curTick); 585 586 ++lsqForwLoads; 587 return NoFault; 588 } else if ((store_has_lower_limit && lower_load_has_store_part) || 589 (store_has_upper_limit && upper_load_has_store_part) || 590 (lower_load_has_store_part && upper_load_has_store_part)) { 591 // This is the partial store-load forwarding case where a store 592 // has only part of the load's data. 593 594 // If it's already been written back, then don't worry about 595 // stalling on it. 596 if (storeQueue[store_idx].completed) { 597 panic("Should not check one of these"); 598 continue; 599 } 600 601 // Must stall load and force it to retry, so long as it's the oldest 602 // load that needs to do so. 603 if (!stalled || 604 (stalled && 605 load_inst->seqNum < 606 loadQueue[stallingLoadIdx]->seqNum)) { 607 stalled = true; 608 stallingStoreIsn = storeQueue[store_idx].inst->seqNum; 609 stallingLoadIdx = load_idx; 610 } 611 612 // Tell IQ/mem dep unit that this instruction will need to be 613 // rescheduled eventually 614 iewStage->rescheduleMemInst(load_inst); 615 iewStage->decrWb(load_inst->seqNum); 616 load_inst->clearIssued(); 617 ++lsqRescheduledLoads; 618 619 // Do not generate a writeback event as this instruction is not 620 // complete. 621 DPRINTF(LSQUnit, "Load-store forwarding mis-match. " 622 "Store idx %i to load addr %#x\n", 623 store_idx, req->getVaddr()); 624 625 // Must delete request now that it wasn't handed off to 626 // memory. This is quite ugly. @todo: Figure out the 627 // proper place to really handle request deletes. 628 delete req; 629 630 return NoFault; 631 } 632 } 633 634 // If there's no forwarding case, then go access memory 635 DPRINTF(LSQUnit, "Doing memory access for inst [sn:%lli] PC %#x\n", 636 load_inst->seqNum, load_inst->readPC()); 637 638 assert(!load_inst->memData); 639 load_inst->memData = new uint8_t[64]; 640 641 ++usedPorts; 642 643 // if we the cache is not blocked, do cache access 644 if (!lsq->cacheBlocked()) { 645 PacketPtr data_pkt = 646 new Packet(req, MemCmd::ReadReq, Packet::Broadcast); 647 data_pkt->dataStatic(load_inst->memData); 648 649 LSQSenderState *state = new LSQSenderState; 650 state->isLoad = true; 651 state->idx = load_idx; 652 state->inst = load_inst; 653 data_pkt->senderState = state; 654 655 if (!dcachePort->sendTiming(data_pkt)) { 656 Packet::Result result = data_pkt->result; 657 658 // Delete state and data packet because a load retry 659 // initiates a pipeline restart; it does not retry. 660 delete state; 661 delete data_pkt->req; 662 delete data_pkt; 663 664 req = NULL; 665 666 if (result == Packet::BadAddress) { 667 return TheISA::genMachineCheckFault(); 668 } 669 670 // If the access didn't succeed, tell the LSQ by setting 671 // the retry thread id. 672 lsq->setRetryTid(lsqID); 673 } 674 } 675 676 // If the cache was blocked, or has become blocked due to the access, 677 // handle it. 678 if (lsq->cacheBlocked()) { 679 if (req) 680 delete req; 681 682 ++lsqCacheBlocked; 683 684 iewStage->decrWb(load_inst->seqNum); 685 // There's an older load that's already going to squash. 686 if (isLoadBlocked && blockedLoadSeqNum < load_inst->seqNum) 687 return NoFault; 688 689 // Record that the load was blocked due to memory. This 690 // load will squash all instructions after it, be 691 // refetched, and re-executed. 692 isLoadBlocked = true; 693 loadBlockedHandled = false; 694 blockedLoadSeqNum = load_inst->seqNum; 695 // No fault occurred, even though the interface is blocked. 696 return NoFault; 697 } 698 699 return NoFault; 700} 701 702template <class Impl> 703template <class T> 704Fault 705LSQUnit<Impl>::write(Request *req, T &data, int store_idx) 706{ 707 assert(storeQueue[store_idx].inst); 708 709 DPRINTF(LSQUnit, "Doing write to store idx %i, addr %#x data %#x" 710 " | storeHead:%i [sn:%i]\n", 711 store_idx, req->getPaddr(), data, storeHead, 712 storeQueue[store_idx].inst->seqNum); 713 714 storeQueue[store_idx].req = req; 715 storeQueue[store_idx].size = sizeof(T); 716 assert(sizeof(T) <= sizeof(storeQueue[store_idx].data)); 717 718 T gData = htog(data); 719 memcpy(storeQueue[store_idx].data, &gData, sizeof(T)); 720 721 // This function only writes the data to the store queue, so no fault 722 // can happen here. 723 return NoFault; 724} 725 726#endif // __CPU_O3_LSQ_UNIT_HH__ 727