lsq_unit.hh revision 2307
11689SN/A/* 212109SRekai.GonzalezAlberquilla@arm.com * Copyright (c) 2004-2005 The Regents of The University of Michigan 39919Ssteve.reinhardt@amd.com * All rights reserved. 48707Sandreas.hansson@arm.com * 58707Sandreas.hansson@arm.com * Redistribution and use in source and binary forms, with or without 68707Sandreas.hansson@arm.com * modification, are permitted provided that the following conditions are 78707Sandreas.hansson@arm.com * met: redistributions of source code must retain the above copyright 88707Sandreas.hansson@arm.com * notice, this list of conditions and the following disclaimer; 98707Sandreas.hansson@arm.com * redistributions in binary form must reproduce the above copyright 108707Sandreas.hansson@arm.com * notice, this list of conditions and the following disclaimer in the 118707Sandreas.hansson@arm.com * documentation and/or other materials provided with the distribution; 128707Sandreas.hansson@arm.com * neither the name of the copyright holders nor the names of its 138707Sandreas.hansson@arm.com * contributors may be used to endorse or promote products derived from 148707Sandreas.hansson@arm.com * this software without specific prior written permission. 151689SN/A * 167897Shestness@cs.utexas.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 171689SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 181689SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 191689SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 201689SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 211689SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 221689SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 231689SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 241689SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 251689SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 261689SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 271689SN/A */ 281689SN/A 291689SN/A#ifndef __CPU_O3_LSQ_UNIT_HH__ 301689SN/A#define __CPU_O3_LSQ_UNIT_HH__ 311689SN/A 321689SN/A#include <map> 331689SN/A#include <queue> 341689SN/A#include <algorithm> 351689SN/A 361689SN/A#include "config/full_system.hh" 371689SN/A#include "base/hashmap.hh" 381689SN/A#include "cpu/inst_seq.hh" 391689SN/A#include "mem/mem_interface.hh" 401689SN/A//#include "mem/page_table.hh" 412665Ssaidi@eecs.umich.edu#include "sim/debug.hh" 422665Ssaidi@eecs.umich.edu#include "sim/sim_object.hh" 432756Sksewell@umich.edu#include "arch/faults.hh" 447897Shestness@cs.utexas.edu 451689SN/A/** 461689SN/A * Class that implements the actual LQ and SQ for each specific thread. 472325SN/A * Both are circular queues; load entries are freed upon committing, while 482325SN/A * store entries are freed once they writeback. The LSQUnit tracks if there 491060SN/A * are memory ordering violations, and also detects partial load to store 501060SN/A * forwarding cases (a store only has part of a load's data) that requires 511060SN/A * the load to wait until the store writes back. In the former case it 522292SN/A * holds onto the instruction until the dependence unit looks at it, and 532292SN/A * in the latter it stalls the LSQ until the store writes back. At that 541681SN/A * point the load is replayed. 551060SN/A */ 5612109SRekai.GonzalezAlberquilla@arm.comtemplate <class Impl> 572980Sgblack@eecs.umich.educlass LSQUnit { 581060SN/A protected: 596658Snate@binkert.org typedef TheISA::IntReg IntReg; 601717SN/A public: 611717SN/A typedef typename Impl::Params Params; 622292SN/A typedef typename Impl::FullCPU FullCPU; 632292SN/A typedef typename Impl::DynInstPtr DynInstPtr; 648229Snate@binkert.org typedef typename Impl::CPUPol::IEW IEW; 658229Snate@binkert.org typedef typename Impl::CPUPol::IssueStruct IssueStruct; 668229Snate@binkert.org 678229Snate@binkert.org private: 682817Sksewell@umich.edu class StoreCompletionEvent : public Event { 698229Snate@binkert.org public: 701060SN/A /** Constructs a store completion event. */ 711060SN/A StoreCompletionEvent(int store_idx, Event *wb_event, LSQUnit *lsq_ptr); 722316SN/A 732316SN/A /** Processes the store completion event. */ 742680Sktlim@umich.edu void process(); 752817Sksewell@umich.edu 762817Sksewell@umich.edu /** Returns the description of this event. */ 772843Sktlim@umich.edu const char *description(); 782843Sktlim@umich.edu 792669Sktlim@umich.edu private: 801060SN/A /** The store index of the store being written back. */ 811060SN/A int storeIdx; 828737Skoansin.tan@gmail.com /** The writeback event for the store. Needed for store 835529Snate@binkert.org * conditionals. 842733Sktlim@umich.edu */ 851060SN/A Event *wbEvent; 861060SN/A /** The pointer to the LSQ unit that issued the store. */ 871060SN/A LSQUnit<Impl> *lsqPtr; 885529Snate@binkert.org }; 892292SN/A 902292SN/A friend class StoreCompletionEvent; 911060SN/A 921060SN/A public: 932348SN/A /** Constructs an LSQ unit. init() must be called prior to use. */ 942348SN/A LSQUnit(); 952348SN/A 962348SN/A /** Initializes the LSQ unit with the specified number of entries. */ 972348SN/A void init(Params *params, unsigned maxLQEntries, 981060SN/A unsigned maxSQEntries, unsigned id); 992733Sktlim@umich.edu 1001060SN/A /** Returns the name of the LSQ unit. */ 1011060SN/A std::string name() const; 1022325SN/A 1031060SN/A /** Sets the CPU pointer. */ 1041061SN/A void setCPU(FullCPU *cpu_ptr) 1054329Sktlim@umich.edu { cpu = cpu_ptr; } 1061060SN/A 10712109SRekai.GonzalezAlberquilla@arm.com /** Sets the IEW stage pointer. */ 10812109SRekai.GonzalezAlberquilla@arm.com void setIEW(IEW *iew_ptr) 10912109SRekai.GonzalezAlberquilla@arm.com { iewStage = iew_ptr; } 1105595Sgblack@eecs.umich.edu 1112292SN/A /** Sets the page table pointer. */ 1122292SN/A// void setPageTable(PageTable *pt_ptr); 1132292SN/A 1142292SN/A void switchOut(); 1152817Sksewell@umich.edu 1162829Sksewell@umich.edu void takeOverFrom(); 1171060SN/A 1181060SN/A bool isSwitchedOut() { return switchedOut; } 1191060SN/A 1201060SN/A /** Ticks the LSQ unit, which in this case only resets the number of 1211060SN/A * used cache ports. 1222307SN/A * @todo: Move the number of used ports up to the LSQ level so it can 1232307SN/A * be shared by all LSQ units. 1241060SN/A */ 1251060SN/A void tick() { usedPorts = 0; } 1266022Sgblack@eecs.umich.edu 1276022Sgblack@eecs.umich.edu /** Inserts an instruction. */ 1283781Sgblack@eecs.umich.edu void insert(DynInstPtr &inst); 1292292SN/A /** Inserts a load instruction. */ 1301060SN/A void insertLoad(DynInstPtr &load_inst); 1311060SN/A /** Inserts a store instruction. */ 1321060SN/A void insertStore(DynInstPtr &store_inst); 1338707Sandreas.hansson@arm.com 1348707Sandreas.hansson@arm.com /** Executes a load instruction. */ 1358707Sandreas.hansson@arm.com Fault executeLoad(DynInstPtr &inst); 1368707Sandreas.hansson@arm.com 1379608Sandreas.hansson@arm.com Fault executeLoad(int lq_idx); 1388707Sandreas.hansson@arm.com /** Executes a store instruction. */ 1398707Sandreas.hansson@arm.com Fault executeStore(DynInstPtr &inst); 1408707Sandreas.hansson@arm.com 1418707Sandreas.hansson@arm.com /** Commits the head load. */ 1428707Sandreas.hansson@arm.com void commitLoad(); 1438707Sandreas.hansson@arm.com /** Commits a specific load, given by the sequence number. */ 1448707Sandreas.hansson@arm.com void commitLoad(InstSeqNum &inst); 1458707Sandreas.hansson@arm.com /** Commits loads older than a specific sequence number. */ 1469608Sandreas.hansson@arm.com void commitLoads(InstSeqNum &youngest_inst); 1478707Sandreas.hansson@arm.com 1488707Sandreas.hansson@arm.com /** Commits stores older than a specific sequence number. */ 1498707Sandreas.hansson@arm.com void commitStores(InstSeqNum &youngest_inst); 1508707Sandreas.hansson@arm.com 1518707Sandreas.hansson@arm.com /** Writes back stores. */ 1528707Sandreas.hansson@arm.com void writebackStores(); 1538975Sandreas.hansson@arm.com 1548707Sandreas.hansson@arm.com // @todo: Include stats in the LSQ unit. 1558707Sandreas.hansson@arm.com //void regStats(); 15610713Sandreas.hansson@arm.com 1578707Sandreas.hansson@arm.com /** Clears all the entries in the LQ. */ 1588707Sandreas.hansson@arm.com void clearLQ(); 1598707Sandreas.hansson@arm.com 1608707Sandreas.hansson@arm.com /** Clears all the entries in the SQ. */ 1618707Sandreas.hansson@arm.com void clearSQ(); 1629608Sandreas.hansson@arm.com 1638707Sandreas.hansson@arm.com /** Resizes the LQ to a given size. */ 1648707Sandreas.hansson@arm.com void resizeLQ(unsigned size); 1658707Sandreas.hansson@arm.com 1668707Sandreas.hansson@arm.com /** Resizes the SQ to a given size. */ 1678707Sandreas.hansson@arm.com void resizeSQ(unsigned size); 16810529Smorr@cs.wisc.edu 1698707Sandreas.hansson@arm.com /** Squashes all instructions younger than a specific sequence number. */ 1708707Sandreas.hansson@arm.com void squash(const InstSeqNum &squashed_num); 1718707Sandreas.hansson@arm.com 1728707Sandreas.hansson@arm.com /** Returns if there is a memory ordering violation. Value is reset upon 17310529Smorr@cs.wisc.edu * call to getMemDepViolator(). 17410529Smorr@cs.wisc.edu */ 1758707Sandreas.hansson@arm.com bool violation() { return memDepViolator; } 1768707Sandreas.hansson@arm.com 1778707Sandreas.hansson@arm.com /** Returns the memory ordering violator. */ 1788707Sandreas.hansson@arm.com DynInstPtr getMemDepViolator(); 1798707Sandreas.hansson@arm.com 1808707Sandreas.hansson@arm.com /** Returns if a load became blocked due to the memory system. It clears 1818707Sandreas.hansson@arm.com * the bool's value upon this being called. 1828975Sandreas.hansson@arm.com */ 1838975Sandreas.hansson@arm.com bool loadBlocked() 1848707Sandreas.hansson@arm.com { return isLoadBlocked; } 1859608Sandreas.hansson@arm.com 1869608Sandreas.hansson@arm.com void clearLoadBlocked() 1879608Sandreas.hansson@arm.com { isLoadBlocked = false; } 1889608Sandreas.hansson@arm.com 1899608Sandreas.hansson@arm.com bool isLoadBlockedHandled() 1908707Sandreas.hansson@arm.com { return loadBlockedHandled; } 19110713Sandreas.hansson@arm.com 1928707Sandreas.hansson@arm.com void setLoadBlockedHandled() 1938707Sandreas.hansson@arm.com { loadBlockedHandled = true; } 1948707Sandreas.hansson@arm.com 1958707Sandreas.hansson@arm.com /** Returns the number of free entries (min of free LQ and SQ entries). */ 1968707Sandreas.hansson@arm.com unsigned numFreeEntries(); 1978711Sandreas.hansson@arm.com 1988707Sandreas.hansson@arm.com /** Returns the number of loads ready to execute. */ 1998922Swilliam.wang@arm.com int numLoadsReady(); 2008707Sandreas.hansson@arm.com 2018707Sandreas.hansson@arm.com /** Returns the number of loads in the LQ. */ 2022292SN/A int numLoads() { return loads; } 20312127Sspwilson2@wisc.edu 2041060SN/A /** Returns the number of stores in the SQ. */ 2052292SN/A int numStores() { return stores; } 2069180Sandreas.hansson@arm.com 2071060SN/A /** Returns if either the LQ or SQ is full. */ 2081060SN/A bool isFull() { return lqFull() || sqFull(); } 2099179Sandreas.hansson@arm.com 2101060SN/A /** Returns if the LQ is full. */ 2119179Sandreas.hansson@arm.com bool lqFull() { return loads >= (LQEntries - 1); } 2121060SN/A 2131060SN/A /** Returns if the SQ is full. */ 2142292SN/A bool sqFull() { return stores >= (SQEntries - 1); } 2151060SN/A 2161060SN/A /** Debugging function to dump instructions in the LSQ. */ 2171060SN/A void dumpInsts(); 2181060SN/A 2191060SN/A /** Returns the number of instructions in the LSQ. */ 2201060SN/A unsigned getCount() { return loads + stores; } 2219444SAndreas.Sandberg@ARM.com 22210913Sandreas.sandberg@arm.com /** Returns if there are any stores to writeback. */ 2239444SAndreas.Sandberg@ARM.com bool hasStoresToWB() { return storesToWB; } 2249444SAndreas.Sandberg@ARM.com 2259444SAndreas.Sandberg@ARM.com /** Returns the number of stores to writeback. */ 2269444SAndreas.Sandberg@ARM.com int numStoresToWB() { return storesToWB; } 2279444SAndreas.Sandberg@ARM.com 2289444SAndreas.Sandberg@ARM.com /** Returns if the LSQ unit will writeback on this cycle. */ 2299444SAndreas.Sandberg@ARM.com bool willWB() { return storeQueue[storeWBIdx].canWB && 2309444SAndreas.Sandberg@ARM.com !storeQueue[storeWBIdx].completed && 2319444SAndreas.Sandberg@ARM.com !dcacheInterface->isBlocked(); } 2329444SAndreas.Sandberg@ARM.com 2339444SAndreas.Sandberg@ARM.com private: 2349444SAndreas.Sandberg@ARM.com /** Completes the store at the specified index. */ 2359444SAndreas.Sandberg@ARM.com void completeStore(int store_idx); 2369444SAndreas.Sandberg@ARM.com 2379444SAndreas.Sandberg@ARM.com /** Increments the given store index (circular queue). */ 2389444SAndreas.Sandberg@ARM.com inline void incrStIdx(int &store_idx); 2399444SAndreas.Sandberg@ARM.com /** Decrements the given store index (circular queue). */ 2409444SAndreas.Sandberg@ARM.com inline void decrStIdx(int &store_idx); 2419444SAndreas.Sandberg@ARM.com /** Increments the given load index (circular queue). */ 2429444SAndreas.Sandberg@ARM.com inline void incrLdIdx(int &load_idx); 2439444SAndreas.Sandberg@ARM.com /** Decrements the given load index (circular queue). */ 2449444SAndreas.Sandberg@ARM.com inline void decrLdIdx(int &load_idx); 2459444SAndreas.Sandberg@ARM.com 2469444SAndreas.Sandberg@ARM.com private: 2479444SAndreas.Sandberg@ARM.com /** Pointer to the CPU. */ 2481060SN/A FullCPU *cpu; 2492292SN/A 2505595Sgblack@eecs.umich.edu /** Pointer to the IEW stage. */ 2512292SN/A IEW *iewStage; 2521755SN/A 2531060SN/A /** Pointer to the D-cache. */ 2542292SN/A MemInterface *dcacheInterface; 25511169Sandreas.hansson@arm.com 2561684SN/A /** Pointer to the page table. */ 25710023Smatt.horsnell@ARM.com// PageTable *pTable; 25810023Smatt.horsnell@ARM.com 25910023Smatt.horsnell@ARM.com public: 26010023Smatt.horsnell@ARM.com struct SQEntry { 26111169Sandreas.hansson@arm.com /** Constructs an empty store queue entry. */ 26210023Smatt.horsnell@ARM.com SQEntry() 2635358Sgblack@eecs.umich.edu : inst(NULL), req(NULL), size(0), data(0), 2645358Sgblack@eecs.umich.edu canWB(0), committed(0), completed(0) 2655358Sgblack@eecs.umich.edu { } 2665358Sgblack@eecs.umich.edu 2675358Sgblack@eecs.umich.edu /** Constructs a store queue entry for a given instruction. */ 2685358Sgblack@eecs.umich.edu SQEntry(DynInstPtr &_inst) 2695358Sgblack@eecs.umich.edu : inst(_inst), req(NULL), size(0), data(0), 2705358Sgblack@eecs.umich.edu canWB(0), committed(0), completed(0) 2715358Sgblack@eecs.umich.edu { } 2725358Sgblack@eecs.umich.edu 2735358Sgblack@eecs.umich.edu /** The store instruction. */ 2745358Sgblack@eecs.umich.edu DynInstPtr inst; 2755358Sgblack@eecs.umich.edu /** The memory request for the store. */ 2765358Sgblack@eecs.umich.edu MemReqPtr req; 2775358Sgblack@eecs.umich.edu /** The size of the store. */ 2785358Sgblack@eecs.umich.edu int size; 2792292SN/A /** The store data. */ 2802292SN/A IntReg data; 2812292SN/A /** Whether or not the store can writeback. */ 2821684SN/A bool canWB; 2831684SN/A /** Whether or not the store is committed. */ 2842292SN/A bool committed; 28511169Sandreas.hansson@arm.com /** Whether or not the store is completed. */ 2861060SN/A bool completed; 28711169Sandreas.hansson@arm.com }; 2889427SAndreas.Sandberg@ARM.com/* 2892834Sksewell@umich.edu enum Status { 2902834Sksewell@umich.edu Running, 2912834Sksewell@umich.edu Idle, 2922834Sksewell@umich.edu DcacheMissStall, 2932829Sksewell@umich.edu DcacheMissSwitch 2946221Snate@binkert.org }; 2952875Sksewell@umich.edu*/ 2962875Sksewell@umich.edu private: 2976221Snate@binkert.org /** The LSQUnit thread id. */ 2982829Sksewell@umich.edu unsigned lsqID; 2992292SN/A 3006221Snate@binkert.org /** The status of the LSQ unit. */ 3011060SN/A// Status _status; 3022292SN/A 3036221Snate@binkert.org /** The store queue. */ 3042292SN/A std::vector<SQEntry> storeQueue; 3052292SN/A 30611169Sandreas.hansson@arm.com /** The load queue. */ 3078834Satgutier@umich.edu std::vector<DynInstPtr> loadQueue; 3088834Satgutier@umich.edu 30911169Sandreas.hansson@arm.com // Consider making these 16 bits 3102292SN/A /** The number of LQ entries. */ 3112292SN/A unsigned LQEntries; 31211169Sandreas.hansson@arm.com /** The number of SQ entries. */ 3132292SN/A unsigned SQEntries; 3142292SN/A 31511169Sandreas.hansson@arm.com /** The number of load instructions in the LQ. */ 3162292SN/A int loads; 3172292SN/A /** The number of store instructions in the SQ (excludes those waiting to 3182292SN/A * writeback). 3192292SN/A */ 32011169Sandreas.hansson@arm.com int stores; 3212292SN/A /** The number of store instructions in the SQ waiting to writeback. */ 3222292SN/A int storesToWB; 3232292SN/A 3242292SN/A /** The index of the head instruction in the LQ. */ 3259444SAndreas.Sandberg@ARM.com int loadHead; 32610913Sandreas.sandberg@arm.com /** The index of the tail instruction in the LQ. */ 3279444SAndreas.Sandberg@ARM.com int loadTail; 32811168Sandreas.hansson@arm.com 32911168Sandreas.hansson@arm.com /** The index of the head instruction in the SQ. */ 3302864Sktlim@umich.edu int storeHead; 3312864Sktlim@umich.edu /** The index of the first instruction that is ready to be written back, 3325595Sgblack@eecs.umich.edu * and has not yet been written back. 3335595Sgblack@eecs.umich.edu */ 3342292SN/A int storeWBIdx; 33511877Sbrandon.potter@amd.com /** The index of the tail instruction in the SQ. */ 3362292SN/A int storeTail; 3372843Sktlim@umich.edu 3382843Sktlim@umich.edu /// @todo Consider moving to a more advanced model with write vs read ports 33911168Sandreas.hansson@arm.com /** The number of cache ports available each cycle. */ 3402843Sktlim@umich.edu int cachePorts; 3412843Sktlim@umich.edu 34211168Sandreas.hansson@arm.com /** The number of used cache ports in this cycle. */ 3432292SN/A int usedPorts; 3449444SAndreas.Sandberg@ARM.com 3459444SAndreas.Sandberg@ARM.com bool switchedOut; 3469444SAndreas.Sandberg@ARM.com 3479444SAndreas.Sandberg@ARM.com //list<InstSeqNum> mshrSeqNums; 3489444SAndreas.Sandberg@ARM.com 3499444SAndreas.Sandberg@ARM.com //Stats::Scalar<> dcacheStallCycles; 3509444SAndreas.Sandberg@ARM.com Counter lastDcacheStall; 3519444SAndreas.Sandberg@ARM.com 3522843Sktlim@umich.edu /** Wire to read information from the issue stage time queue. */ 3532843Sktlim@umich.edu typename TimeBuffer<IssueStruct>::wire fromIssue; 35411169Sandreas.hansson@arm.com 3552316SN/A // Make these per thread? 3562348SN/A /** Whether or not the LSQ is stalled. */ 35711169Sandreas.hansson@arm.com bool stalled; 3581060SN/A /** The store that causes the stall due to partial store to load 35911169Sandreas.hansson@arm.com * forwarding. 3609523SAndreas.Sandberg@ARM.com */ 3611060SN/A InstSeqNum stallingStoreIsn; 3622316SN/A /** The index of the above store. */ 3632316SN/A int stallingLoadIdx; 3641060SN/A 3655595Sgblack@eecs.umich.edu /** Whether or not a load is blocked due to the memory system. It is 36610417Sandreas.hansson@arm.com * cleared when this value is checked via loadBlocked(). 3675595Sgblack@eecs.umich.edu */ 3685702Ssaidi@eecs.umich.edu bool isLoadBlocked; 3696221Snate@binkert.org 3705702Ssaidi@eecs.umich.edu bool loadBlockedHandled; 3716221Snate@binkert.org 3725702Ssaidi@eecs.umich.edu InstSeqNum blockedLoadSeqNum; 3735595Sgblack@eecs.umich.edu 3745595Sgblack@eecs.umich.edu /** The oldest faulting load instruction. */ 3755595Sgblack@eecs.umich.edu DynInstPtr loadFaultInst; 3765595Sgblack@eecs.umich.edu /** The oldest faulting store instruction. */ 37710379Sandreas.hansson@arm.com DynInstPtr storeFaultInst; 3785595Sgblack@eecs.umich.edu 3795595Sgblack@eecs.umich.edu /** The oldest load that caused a memory ordering violation. */ 3805595Sgblack@eecs.umich.edu DynInstPtr memDepViolator; 3815595Sgblack@eecs.umich.edu 3822348SN/A // Will also need how many read/write ports the Dcache has. Or keep track 3835595Sgblack@eecs.umich.edu // of that in stage that is one level up, and only call executeLoad/Store 3845595Sgblack@eecs.umich.edu // the appropriate number of times. 38510698Sandreas.hansson@arm.com/* 3865595Sgblack@eecs.umich.edu // total number of loads forwaded from LSQ stores 3875595Sgblack@eecs.umich.edu Stats::Vector<> lsq_forw_loads; 3885595Sgblack@eecs.umich.edu 3895595Sgblack@eecs.umich.edu // total number of loads ignored due to invalid addresses 3906221Snate@binkert.org Stats::Vector<> inv_addr_loads; 3915595Sgblack@eecs.umich.edu 3925595Sgblack@eecs.umich.edu // total number of software prefetches ignored due to invalid addresses 3936221Snate@binkert.org Stats::Vector<> inv_addr_swpfs; 3946221Snate@binkert.org 3955595Sgblack@eecs.umich.edu // total non-speculative bogus addresses seen (debug var) 3965595Sgblack@eecs.umich.edu Counter sim_invalid_addrs; 3975595Sgblack@eecs.umich.edu Stats::Vector<> fu_busy; //cumulative fu busy 3985595Sgblack@eecs.umich.edu 3995595Sgblack@eecs.umich.edu // ready loads blocked due to memory disambiguation 4006221Snate@binkert.org Stats::Vector<> lsq_blocked_loads; 4015595Sgblack@eecs.umich.edu 40212105Snathanael.premillieu@arm.com Stats::Scalar<> lsqInversion; 4031060SN/A*/ 40412105Snathanael.premillieu@arm.com public: 4051060SN/A /** Executes the load at the given index. */ 40612105Snathanael.premillieu@arm.com template <class T> 4072455SN/A Fault read(MemReqPtr &req, T &data, int load_idx); 40812109SRekai.GonzalezAlberquilla@arm.com 40912109SRekai.GonzalezAlberquilla@arm.com /** Executes the store at the given index. */ 41012109SRekai.GonzalezAlberquilla@arm.com template <class T> 41112109SRekai.GonzalezAlberquilla@arm.com Fault write(MemReqPtr &req, T &data, int store_idx); 41212109SRekai.GonzalezAlberquilla@arm.com 41312109SRekai.GonzalezAlberquilla@arm.com /** Returns the index of the head load instruction. */ 41412109SRekai.GonzalezAlberquilla@arm.com int getLoadHead() { return loadHead; } 41512109SRekai.GonzalezAlberquilla@arm.com /** Returns the sequence number of the head load instruction. */ 41612109SRekai.GonzalezAlberquilla@arm.com InstSeqNum getLoadHeadSeqNum() 41712109SRekai.GonzalezAlberquilla@arm.com { 41812109SRekai.GonzalezAlberquilla@arm.com if (loadQueue[loadHead]) { 41912109SRekai.GonzalezAlberquilla@arm.com return loadQueue[loadHead]->seqNum; 42012109SRekai.GonzalezAlberquilla@arm.com } else { 42112109SRekai.GonzalezAlberquilla@arm.com return 0; 42212109SRekai.GonzalezAlberquilla@arm.com } 42312109SRekai.GonzalezAlberquilla@arm.com 42412109SRekai.GonzalezAlberquilla@arm.com } 42512109SRekai.GonzalezAlberquilla@arm.com 42612109SRekai.GonzalezAlberquilla@arm.com /** Returns the index of the head store instruction. */ 42712109SRekai.GonzalezAlberquilla@arm.com int getStoreHead() { return storeHead; } 42812109SRekai.GonzalezAlberquilla@arm.com /** Returns the sequence number of the head store instruction. */ 42912109SRekai.GonzalezAlberquilla@arm.com InstSeqNum getStoreHeadSeqNum() 43012109SRekai.GonzalezAlberquilla@arm.com { 43112109SRekai.GonzalezAlberquilla@arm.com if (storeQueue[storeHead].inst) { 43212109SRekai.GonzalezAlberquilla@arm.com return storeQueue[storeHead].inst->seqNum; 43312109SRekai.GonzalezAlberquilla@arm.com } else { 43412109SRekai.GonzalezAlberquilla@arm.com return 0; 43512109SRekai.GonzalezAlberquilla@arm.com } 43612109SRekai.GonzalezAlberquilla@arm.com 43712109SRekai.GonzalezAlberquilla@arm.com } 43812109SRekai.GonzalezAlberquilla@arm.com 43912109SRekai.GonzalezAlberquilla@arm.com /** Returns whether or not the LSQ unit is stalled. */ 44012109SRekai.GonzalezAlberquilla@arm.com bool isStalled() { return stalled; } 44112109SRekai.GonzalezAlberquilla@arm.com}; 44212109SRekai.GonzalezAlberquilla@arm.com 44312109SRekai.GonzalezAlberquilla@arm.comtemplate <class Impl> 44412109SRekai.GonzalezAlberquilla@arm.comtemplate <class T> 44512109SRekai.GonzalezAlberquilla@arm.comFault 44612109SRekai.GonzalezAlberquilla@arm.comLSQUnit<Impl>::read(MemReqPtr &req, T &data, int load_idx) 44712109SRekai.GonzalezAlberquilla@arm.com{ 44812105Snathanael.premillieu@arm.com //Depending on issue2execute delay a squashed load could 4499920Syasuko.eckert@amd.com //execute if it is found to be squashed in the same 45012105Snathanael.premillieu@arm.com //cycle it is scheduled to execute 4511060SN/A assert(loadQueue[load_idx]); 45212105Snathanael.premillieu@arm.com 4531060SN/A if (loadQueue[load_idx]->isExecuted()) { 45412105Snathanael.premillieu@arm.com panic("Should not reach this point with split ops!"); 4552455SN/A memcpy(&data,req->data,req->size); 45612109SRekai.GonzalezAlberquilla@arm.com 45712109SRekai.GonzalezAlberquilla@arm.com return NoFault; 45812109SRekai.GonzalezAlberquilla@arm.com } 45912109SRekai.GonzalezAlberquilla@arm.com 46012105Snathanael.premillieu@arm.com // Make sure this isn't an uncacheable access 4619920Syasuko.eckert@amd.com // A bit of a hackish way to get uncached accesses to work only if they're 4626221Snate@binkert.org // at the head of the LSQ and are ready to commit (at the head of the ROB 4631060SN/A // too). 4646314Sgblack@eecs.umich.edu // @todo: Fix uncached accesses. 4652292SN/A if (req->flags & UNCACHEABLE && 4666221Snate@binkert.org (load_idx != loadHead || !loadQueue[load_idx]->reachedCommit)) { 4672292SN/A iewStage->rescheduleMemInst(loadQueue[load_idx]); 46812109SRekai.GonzalezAlberquilla@arm.com return TheISA::genMachineCheckFault(); 46912109SRekai.GonzalezAlberquilla@arm.com } 47012109SRekai.GonzalezAlberquilla@arm.com 47112109SRekai.GonzalezAlberquilla@arm.com // Check the SQ for any previous stores that might lead to forwarding 47212109SRekai.GonzalezAlberquilla@arm.com int store_idx = loadQueue[load_idx]->sqIdx; 47312109SRekai.GonzalezAlberquilla@arm.com 47412109SRekai.GonzalezAlberquilla@arm.com int store_size = 0; 47512109SRekai.GonzalezAlberquilla@arm.com 47612109SRekai.GonzalezAlberquilla@arm.com DPRINTF(LSQUnit, "Read called, load idx: %i, store idx: %i, " 47712109SRekai.GonzalezAlberquilla@arm.com "storeHead: %i addr: %#x\n", 47812109SRekai.GonzalezAlberquilla@arm.com load_idx, store_idx, storeHead, req->paddr); 47912109SRekai.GonzalezAlberquilla@arm.com 48012109SRekai.GonzalezAlberquilla@arm.com#ifdef FULL_SYSTEM 48112109SRekai.GonzalezAlberquilla@arm.com if (req->flags & LOCKED) { 48212109SRekai.GonzalezAlberquilla@arm.com cpu->lockAddr = req->paddr; 48312109SRekai.GonzalezAlberquilla@arm.com cpu->lockFlag = true; 48412109SRekai.GonzalezAlberquilla@arm.com } 48512109SRekai.GonzalezAlberquilla@arm.com#endif 48612109SRekai.GonzalezAlberquilla@arm.com 48712109SRekai.GonzalezAlberquilla@arm.com while (store_idx != -1) { 48812109SRekai.GonzalezAlberquilla@arm.com // End once we've reached the top of the LSQ 48912109SRekai.GonzalezAlberquilla@arm.com if (store_idx == storeWBIdx) { 49012109SRekai.GonzalezAlberquilla@arm.com break; 49112109SRekai.GonzalezAlberquilla@arm.com } 49212109SRekai.GonzalezAlberquilla@arm.com 49312109SRekai.GonzalezAlberquilla@arm.com // Move the index to one younger 49412109SRekai.GonzalezAlberquilla@arm.com if (--store_idx < 0) 49512109SRekai.GonzalezAlberquilla@arm.com store_idx += SQEntries; 4969920Syasuko.eckert@amd.com 4979920Syasuko.eckert@amd.com assert(storeQueue[store_idx].inst); 4982348SN/A 4992348SN/A store_size = storeQueue[store_idx].size; 5002348SN/A 5012348SN/A if (store_size == 0) 5022348SN/A continue; 5036221Snate@binkert.org 5042292SN/A // Check if the store data is within the lower and upper bounds of 5056314Sgblack@eecs.umich.edu // addresses that the request needs. 5062292SN/A bool store_has_lower_limit = 5076221Snate@binkert.org req->vaddr >= storeQueue[store_idx].inst->effAddr; 5082292SN/A bool store_has_upper_limit = 50912109SRekai.GonzalezAlberquilla@arm.com (req->vaddr + req->size) <= (storeQueue[store_idx].inst->effAddr + 51012109SRekai.GonzalezAlberquilla@arm.com store_size); 51112109SRekai.GonzalezAlberquilla@arm.com bool lower_load_has_store_part = 51212109SRekai.GonzalezAlberquilla@arm.com req->vaddr < (storeQueue[store_idx].inst->effAddr + 51312109SRekai.GonzalezAlberquilla@arm.com store_size); 5149920Syasuko.eckert@amd.com bool upper_load_has_store_part = 5159920Syasuko.eckert@amd.com (req->vaddr + req->size) > storeQueue[store_idx].inst->effAddr; 5167720Sgblack@eecs.umich.edu 5177720Sgblack@eecs.umich.edu // If the store's data has all of the data needed, we can forward. 5187720Sgblack@eecs.umich.edu if (store_has_lower_limit && store_has_upper_limit) { 5197720Sgblack@eecs.umich.edu 5207720Sgblack@eecs.umich.edu int shift_amt = req->vaddr & (store_size - 1); 5217720Sgblack@eecs.umich.edu // Assumes byte addressing 5222348SN/A shift_amt = shift_amt << 3; 5237720Sgblack@eecs.umich.edu 5242292SN/A // Cast this to type T? 5254636Sgblack@eecs.umich.edu data = storeQueue[store_idx].data >> shift_amt; 5267720Sgblack@eecs.umich.edu 5274636Sgblack@eecs.umich.edu req->cmd = Read; 5282348SN/A assert(!req->completionEvent); 5297720Sgblack@eecs.umich.edu req->completionEvent = NULL; 5302756Sksewell@umich.edu req->time = curTick; 5315595Sgblack@eecs.umich.edu assert(!req->data); 5325595Sgblack@eecs.umich.edu req->data = new uint8_t[64]; 5335595Sgblack@eecs.umich.edu 5345595Sgblack@eecs.umich.edu memcpy(req->data, &data, req->size); 5356221Snate@binkert.org 5365595Sgblack@eecs.umich.edu DPRINTF(LSQUnit, "Forwarding from store idx %i to load to " 5371060SN/A "addr %#x, data %#x\n", 5381060SN/A store_idx, req->vaddr, *(req->data)); 5391060SN/A 5402292SN/A typename IEW::LdWritebackEvent *wb = 5411060SN/A new typename IEW::LdWritebackEvent(loadQueue[load_idx], 5421060SN/A iewStage); 5438834Satgutier@umich.edu 5441060SN/A // We'll say this has a 1 cycle load-store forwarding latency 5452325SN/A // for now. 5462325SN/A // @todo: Need to make this a parameter. 5471060SN/A wb->schedule(curTick); 5481061SN/A 5491060SN/A // Should keep track of stat for forwarded data 5502935Sksewell@umich.edu return NoFault; 5512935Sksewell@umich.edu } else if ((store_has_lower_limit && lower_load_has_store_part) || 5526221Snate@binkert.org (store_has_upper_limit && upper_load_has_store_part) || 5531060SN/A (lower_load_has_store_part && upper_load_has_store_part)) { 5541062SN/A // This is the partial store-load forwarding case where a store 5556221Snate@binkert.org // has only part of the load's data. 5562292SN/A 5572348SN/A // If it's already been written back, then don't worry about 5586221Snate@binkert.org // stalling on it. 5592292SN/A if (storeQueue[store_idx].completed) { 5602348SN/A continue; 5612292SN/A } 5621062SN/A 5632348SN/A // Must stall load and force it to retry, so long as it's the oldest 5641060SN/A // load that needs to do so. 5651060SN/A if (!stalled || 5661060SN/A (stalled && 5675737Scws3k@cs.virginia.edu loadQueue[load_idx]->seqNum < 5685737Scws3k@cs.virginia.edu loadQueue[stallingLoadIdx]->seqNum)) { 5695737Scws3k@cs.virginia.edu stalled = true; 5705737Scws3k@cs.virginia.edu stallingStoreIsn = storeQueue[store_idx].inst->seqNum; 5715737Scws3k@cs.virginia.edu stallingLoadIdx = load_idx; 5721060SN/A } 5732292SN/A 5741060SN/A // Tell IQ/mem dep unit that this instruction will need to be 5752292SN/A // rescheduled eventually 5762292SN/A iewStage->rescheduleMemInst(loadQueue[load_idx]); 5772292SN/A 5782292SN/A // Do not generate a writeback event as this instruction is not 5792292SN/A // complete. 5802325SN/A 5812348SN/A DPRINTF(LSQUnit, "Load-store forwarding mis-match. " 5822348SN/A "Store idx %i to load addr %#x\n", 5832348SN/A store_idx, req->vaddr); 5842292SN/A 5852325SN/A return NoFault; 5862292SN/A } 5872325SN/A } 5882325SN/A 5892292SN/A 5902292SN/A // If there's no forwarding case, then go access memory 5912292SN/A DynInstPtr inst = loadQueue[load_idx]; 5921060SN/A 5931060SN/A DPRINTF(LSQUnit, "Doing functional access for inst PC %#x\n", 5941060SN/A loadQueue[load_idx]->readPC()); 5951060SN/A assert(!req->data); 5961060SN/A req->cmd = Read; 5971060SN/A req->completionEvent = NULL; 5981060SN/A req->time = curTick; 5991060SN/A req->data = new uint8_t[64]; 6001060SN/A Fault fault = cpu->read(req, data); 6011060SN/A memcpy(req->data, &data, sizeof(T)); 6021060SN/A 6031060SN/A ++usedPorts; 6041060SN/A 6051060SN/A // if we have a cache, do cache access too 6061060SN/A if (fault == NoFault && dcacheInterface) { 6071060SN/A if (dcacheInterface->isBlocked()) { 60812109SRekai.GonzalezAlberquilla@arm.com // There's an older load that's already going to squash. 60912109SRekai.GonzalezAlberquilla@arm.com if (isLoadBlocked && blockedLoadSeqNum < inst->seqNum) 61012109SRekai.GonzalezAlberquilla@arm.com return NoFault; 6111060SN/A 6129919Ssteve.reinhardt@amd.com isLoadBlocked = true; 6131060SN/A loadBlockedHandled = false; 6141060SN/A blockedLoadSeqNum = inst->seqNum; 6151060SN/A // No fault occurred, even though the interface is blocked. 6161060SN/A return NoFault; 6171060SN/A } 6182292SN/A DPRINTF(LSQUnit, "Doing timing access for inst PC %#x\n", 6192292SN/A loadQueue[load_idx]->readPC()); 6202292SN/A/* 6212292SN/A Addr debug_addr = ULL(0xfffffc0000be81a8); 6221060SN/A if (req->vaddr == debug_addr) { 6231060SN/A debug_break(); 6241060SN/A } 6251060SN/A*/ 6262292SN/A assert(!req->completionEvent); 6276221Snate@binkert.org req->completionEvent = 6282292SN/A new typename IEW::LdWritebackEvent(loadQueue[load_idx], iewStage); 6292292SN/A MemAccessResult result = dcacheInterface->access(req); 6302292SN/A 6312292SN/A assert(dcacheInterface->doEvents()); 6329384SAndreas.Sandberg@arm.com 6336313Sgblack@eecs.umich.edu // Ugly hack to get an event scheduled *only* if the access is 6348707Sandreas.hansson@arm.com // a miss. We really should add first-class support for this 6358707Sandreas.hansson@arm.com // at some point. 6368707Sandreas.hansson@arm.com if (result != MA_HIT) { 6378707Sandreas.hansson@arm.com DPRINTF(LSQUnit, "LSQUnit: D-cache miss!\n"); 6388707Sandreas.hansson@arm.com DPRINTF(Activity, "Activity: ld accessing mem miss [sn:%lli]\n", 6398707Sandreas.hansson@arm.com inst->seqNum); 6401060SN/A 6412292SN/A lastDcacheStall = curTick; 6422292SN/A 6432292SN/A// _status = DcacheMissStall; 6442292SN/A 6452292SN/A } else { 6462292SN/A DPRINTF(Activity, "Activity: ld accessing mem hit [sn:%lli]\n", 6472292SN/A inst->seqNum); 6482292SN/A 6492292SN/A DPRINTF(LSQUnit, "LSQUnit: D-cache hit!\n"); 6502292SN/A } 6512292SN/A } 6522292SN/A#if 0 6531060SN/A // if we have a cache, do cache access too 6541060SN/A if (dcacheInterface) { 6551060SN/A if (dcacheInterface->isBlocked()) { 6561061SN/A isLoadBlocked = true; 6571060SN/A // No fault occurred, even though the interface is blocked. 6581061SN/A return NoFault; 6591060SN/A } 6601061SN/A 6611060SN/A DPRINTF(LSQUnit, "LSQUnit: D-cache: PC:%#x reading from paddr:%#x " 6621061SN/A "vaddr:%#x flags:%i\n", 6631060SN/A inst->readPC(), req->paddr, req->vaddr, req->flags); 6641061SN/A 6651060SN/A // Setup MemReq pointer 6661060SN/A req->cmd = Read; 6671060SN/A req->completionEvent = NULL; 6681060SN/A req->time = curTick; 6691060SN/A assert(!req->data); 6701060SN/A req->data = new uint8_t[64]; 6711060SN/A 6721060SN/A assert(!req->completionEvent); 6731060SN/A req->completionEvent = 6741060SN/A new typename IEW::LdWritebackEvent(loadQueue[load_idx], iewStage); 6751060SN/A 6761060SN/A // Do Cache Access 6771060SN/A MemAccessResult result = dcacheInterface->access(req); 6781060SN/A 6791060SN/A // Ugly hack to get an event scheduled *only* if the access is 6801060SN/A // a miss. We really should add first-class support for this 6812348SN/A // at some point. 6822348SN/A // @todo: Probably should support having no events 6832348SN/A if (result != MA_HIT) { 6842348SN/A DPRINTF(LSQUnit, "LSQUnit: D-cache miss!\n"); 6852348SN/A DPRINTF(Activity, "Activity: ld accessing mem miss [sn:%lli]\n", 6862325SN/A inst->seqNum); 6871060SN/A 6882348SN/A lastDcacheStall = curTick; 6892348SN/A 6902325SN/A _status = DcacheMissStall; 6912292SN/A 6922348SN/A } else { 6932325SN/A DPRINTF(Activity, "Activity: ld accessing mem hit [sn:%lli]\n", 6942325SN/A inst->seqNum); 6952292SN/A 6962348SN/A DPRINTF(LSQUnit, "LSQUnit: D-cache hit!\n"); 6972325SN/A } 6982325SN/A } else { 6992292SN/A fatal("Must use D-cache with new memory system"); 7002292SN/A } 7012292SN/A#endif 7022260SN/A 70311168Sandreas.hansson@arm.com return fault; 7045807Snate@binkert.org} 7052292SN/A 7066221Snate@binkert.orgtemplate <class Impl> 7072292SN/Atemplate <class T> 7082292SN/AFault 7092680Sktlim@umich.eduLSQUnit<Impl>::write(MemReqPtr &req, T &data, int store_idx) 7106221Snate@binkert.org{ 7116221Snate@binkert.org assert(storeQueue[store_idx].inst); 7121681SN/A 7132680Sktlim@umich.edu DPRINTF(LSQUnit, "Doing write to store idx %i, addr %#x data %#x" 7142190SN/A " | storeHead:%i [sn:%i]\n", 7152190SN/A store_idx, req->paddr, data, storeHead, 7162292SN/A storeQueue[store_idx].inst->seqNum); 7173093Sksewell@umich.edu/* 7181060SN/A if (req->flags & LOCKED) { 7192348SN/A if (req->flags & UNCACHEABLE) { 7202348SN/A req->result = 2; 7212348SN/A } else { 7222348SN/A req->result = 1; 7238733Sgeoffrey.blake@arm.com } 7242316SN/A } 7252292SN/A*/ 7261060SN/A storeQueue[store_idx].req = req; 7271060SN/A storeQueue[store_idx].size = sizeof(T); 7282348SN/A storeQueue[store_idx].data = data; 7292292SN/A/* 7302260SN/A Addr debug_addr = ULL(0xfffffc0000be81a8); 7312292SN/A if (req->vaddr == debug_addr) { 7322292SN/A debug_break(); 7332292SN/A } 7342292SN/A*/ 7359180Sandreas.hansson@arm.com // This function only writes the data to the store queue, so no fault 7362292SN/A // can happen here. 7372829Sksewell@umich.edu return NoFault; 7382829Sksewell@umich.edu} 7392829Sksewell@umich.edu 7402292SN/A#endif // __CPU_O3_LSQ_UNIT_HH__ 7416221Snate@binkert.org