lsq_unit.hh revision 4395
16313Sgblack@eecs.umich.edu/* 212529Sgiacomo.travaglini@arm.com * Copyright (c) 2004-2006 The Regents of The University of Michigan 37093Sgblack@eecs.umich.edu * All rights reserved. 47093Sgblack@eecs.umich.edu * 57093Sgblack@eecs.umich.edu * Redistribution and use in source and binary forms, with or without 67093Sgblack@eecs.umich.edu * modification, are permitted provided that the following conditions are 77093Sgblack@eecs.umich.edu * met: redistributions of source code must retain the above copyright 87093Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer; 97093Sgblack@eecs.umich.edu * redistributions in binary form must reproduce the above copyright 107093Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer in the 117093Sgblack@eecs.umich.edu * documentation and/or other materials provided with the distribution; 127093Sgblack@eecs.umich.edu * neither the name of the copyright holders nor the names of its 137093Sgblack@eecs.umich.edu * contributors may be used to endorse or promote products derived from 146313Sgblack@eecs.umich.edu * this software without specific prior written permission. 156313Sgblack@eecs.umich.edu * 166313Sgblack@eecs.umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 176313Sgblack@eecs.umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 186313Sgblack@eecs.umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 196313Sgblack@eecs.umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 206313Sgblack@eecs.umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 216313Sgblack@eecs.umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 226313Sgblack@eecs.umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 236313Sgblack@eecs.umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 246313Sgblack@eecs.umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 256313Sgblack@eecs.umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 266313Sgblack@eecs.umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 276313Sgblack@eecs.umich.edu * 286313Sgblack@eecs.umich.edu * Authors: Kevin Lim 296313Sgblack@eecs.umich.edu * Korey Sewell 306313Sgblack@eecs.umich.edu */ 316313Sgblack@eecs.umich.edu 326313Sgblack@eecs.umich.edu#ifndef __CPU_O3_LSQ_UNIT_HH__ 336313Sgblack@eecs.umich.edu#define __CPU_O3_LSQ_UNIT_HH__ 346313Sgblack@eecs.umich.edu 356313Sgblack@eecs.umich.edu#include <algorithm> 366313Sgblack@eecs.umich.edu#include <cstring> 376313Sgblack@eecs.umich.edu#include <map> 386313Sgblack@eecs.umich.edu#include <queue> 396313Sgblack@eecs.umich.edu 406313Sgblack@eecs.umich.edu#include "arch/faults.hh" 416313Sgblack@eecs.umich.edu#include "arch/locked_mem.hh" 426313Sgblack@eecs.umich.edu#include "config/full_system.hh" 436313Sgblack@eecs.umich.edu#include "base/hashmap.hh" 447404SAli.Saidi@ARM.com#include "cpu/inst_seq.hh" 456313Sgblack@eecs.umich.edu#include "mem/packet.hh" 4610461SAndreas.Sandberg@ARM.com#include "mem/port.hh" 4712479SCurtis.Dunham@arm.com 486333Sgblack@eecs.umich.edu/** 4910037SARM gem5 Developers * Class that implements the actual LQ and SQ for each specific 507404SAli.Saidi@ARM.com * thread. Both are circular queues; load entries are freed upon 516313Sgblack@eecs.umich.edu * committing, while store entries are freed once they writeback. The 5212109SRekai.GonzalezAlberquilla@arm.com * LSQUnit tracks if there are memory ordering violations, and also 538232Snate@binkert.org * detects partial load to store forwarding cases (a store only has 5412109SRekai.GonzalezAlberquilla@arm.com * part of a load's data) that requires the load to wait until the 559384SAndreas.Sandberg@arm.com * store writes back. In the former case it holds onto the instruction 5611165SRekai.GonzalezAlberquilla@arm.com * until the dependence unit looks at it, and in the latter it stalls 576313Sgblack@eecs.umich.edu * the LSQ until the store writes back. At that point the load is 589384SAndreas.Sandberg@arm.com * replayed. 5910461SAndreas.Sandberg@ARM.com */ 606333Sgblack@eecs.umich.edutemplate <class Impl> 616313Sgblack@eecs.umich.educlass LSQUnit { 626313Sgblack@eecs.umich.edu protected: 636313Sgblack@eecs.umich.edu typedef TheISA::IntReg IntReg; 646313Sgblack@eecs.umich.edu public: 656313Sgblack@eecs.umich.edu typedef typename Impl::Params Params; 669384SAndreas.Sandberg@arm.com typedef typename Impl::O3CPU O3CPU; 676313Sgblack@eecs.umich.edu typedef typename Impl::DynInstPtr DynInstPtr; 686313Sgblack@eecs.umich.edu typedef typename Impl::CPUPol::IEW IEW; 6910037SARM gem5 Developers typedef typename Impl::CPUPol::LSQ LSQ; 7010037SARM gem5 Developers typedef typename Impl::CPUPol::IssueStruct IssueStruct; 7110037SARM gem5 Developers 7211165SRekai.GonzalezAlberquilla@arm.com public: 7311165SRekai.GonzalezAlberquilla@arm.com /** Constructs an LSQ unit. init() must be called prior to use. */ 7412109SRekai.GonzalezAlberquilla@arm.com LSQUnit(); 7511165SRekai.GonzalezAlberquilla@arm.com 7610461SAndreas.Sandberg@ARM.com /** Initializes the LSQ unit with the specified number of entries. */ 7710461SAndreas.Sandberg@ARM.com void init(O3CPU *cpu_ptr, IEW *iew_ptr, Params *params, LSQ *lsq_ptr, 7810461SAndreas.Sandberg@ARM.com unsigned maxLQEntries, unsigned maxSQEntries, unsigned id); 7910461SAndreas.Sandberg@ARM.com 8010461SAndreas.Sandberg@ARM.com /** Returns the name of the LSQ unit. */ 8110461SAndreas.Sandberg@ARM.com std::string name() const; 8210844Sandreas.sandberg@arm.com 8310844Sandreas.sandberg@arm.com /** Registers statistics. */ 8410844Sandreas.sandberg@arm.com void regStats(); 8513531Sjairo.balart@metempsy.com 8613531Sjairo.balart@metempsy.com /** Sets the pointer to the dcache port. */ 8713531Sjairo.balart@metempsy.com void setDcachePort(Port *dcache_port); 8810037SARM gem5 Developers 8911771SCurtis.Dunham@arm.com /** Switches out LSQ unit. */ 9010037SARM gem5 Developers void switchOut(); 9110037SARM gem5 Developers 9210037SARM gem5 Developers /** Takes over from another CPU's thread. */ 9313173Sgiacomo.travaglini@arm.com void takeOverFrom(); 9410037SARM gem5 Developers 9513531Sjairo.balart@metempsy.com /** Returns if the LSQ is switched out. */ 9613114Sgiacomo.travaglini@arm.com bool isSwitchedOut() { return switchedOut; } 9710037SARM gem5 Developers 9812714Sgiacomo.travaglini@arm.com /** Ticks the LSQ unit, which in this case only resets the number of 9912714Sgiacomo.travaglini@arm.com * used cache ports. 10012714Sgiacomo.travaglini@arm.com * @todo: Move the number of used ports up to the LSQ level so it can 10112714Sgiacomo.travaglini@arm.com * be shared by all LSQ units. 10212714Sgiacomo.travaglini@arm.com */ 10312714Sgiacomo.travaglini@arm.com void tick() { usedPorts = 0; } 10412478SCurtis.Dunham@arm.com 10510037SARM gem5 Developers /** Inserts an instruction. */ 10612477SCurtis.Dunham@arm.com void insert(DynInstPtr &inst); 10712477SCurtis.Dunham@arm.com /** Inserts a load instruction. */ 10812478SCurtis.Dunham@arm.com void insertLoad(DynInstPtr &load_inst); 10912478SCurtis.Dunham@arm.com /** Inserts a store instruction. */ 11012478SCurtis.Dunham@arm.com void insertStore(DynInstPtr &store_inst); 11112478SCurtis.Dunham@arm.com 11212478SCurtis.Dunham@arm.com /** Executes a load instruction. */ 11312478SCurtis.Dunham@arm.com Fault executeLoad(DynInstPtr &inst); 11412478SCurtis.Dunham@arm.com 11512478SCurtis.Dunham@arm.com Fault executeLoad(int lq_idx) { panic("Not implemented"); return NoFault; } 11612478SCurtis.Dunham@arm.com /** Executes a store instruction. */ 11712478SCurtis.Dunham@arm.com Fault executeStore(DynInstPtr &inst); 11812478SCurtis.Dunham@arm.com 11912478SCurtis.Dunham@arm.com /** Commits the head load. */ 12012478SCurtis.Dunham@arm.com void commitLoad(); 12112478SCurtis.Dunham@arm.com /** Commits loads older than a specific sequence number. */ 12212478SCurtis.Dunham@arm.com void commitLoads(InstSeqNum &youngest_inst); 12312478SCurtis.Dunham@arm.com 12410037SARM gem5 Developers /** Commits stores older than a specific sequence number. */ 12510037SARM gem5 Developers void commitStores(InstSeqNum &youngest_inst); 12612477SCurtis.Dunham@arm.com 12712479SCurtis.Dunham@arm.com /** Writes back stores. */ 12812477SCurtis.Dunham@arm.com void writebackStores(); 12912477SCurtis.Dunham@arm.com 13012477SCurtis.Dunham@arm.com /** Completes the data access that has been returned from the 13112479SCurtis.Dunham@arm.com * memory system. */ 13212477SCurtis.Dunham@arm.com void completeDataAccess(PacketPtr pkt); 13312477SCurtis.Dunham@arm.com 13412477SCurtis.Dunham@arm.com /** Clears all the entries in the LQ. */ 13512477SCurtis.Dunham@arm.com void clearLQ(); 13612477SCurtis.Dunham@arm.com 13712477SCurtis.Dunham@arm.com /** Clears all the entries in the SQ. */ 13812477SCurtis.Dunham@arm.com void clearSQ(); 13912478SCurtis.Dunham@arm.com 14012478SCurtis.Dunham@arm.com /** Resizes the LQ to a given size. */ 14112478SCurtis.Dunham@arm.com void resizeLQ(unsigned size); 14212478SCurtis.Dunham@arm.com 14312478SCurtis.Dunham@arm.com /** Resizes the SQ to a given size. */ 14412478SCurtis.Dunham@arm.com void resizeSQ(unsigned size); 14512478SCurtis.Dunham@arm.com 14612478SCurtis.Dunham@arm.com /** Squashes all instructions younger than a specific sequence number. */ 14712478SCurtis.Dunham@arm.com void squash(const InstSeqNum &squashed_num); 14812478SCurtis.Dunham@arm.com 14912478SCurtis.Dunham@arm.com /** Returns if there is a memory ordering violation. Value is reset upon 15012478SCurtis.Dunham@arm.com * call to getMemDepViolator(). 15112478SCurtis.Dunham@arm.com */ 15212478SCurtis.Dunham@arm.com bool violation() { return memDepViolator; } 15312478SCurtis.Dunham@arm.com 15412478SCurtis.Dunham@arm.com /** Returns the memory ordering violator. */ 15512479SCurtis.Dunham@arm.com DynInstPtr getMemDepViolator(); 15612479SCurtis.Dunham@arm.com 15712479SCurtis.Dunham@arm.com /** Returns if a load became blocked due to the memory system. */ 15812479SCurtis.Dunham@arm.com bool loadBlocked() 15912479SCurtis.Dunham@arm.com { return isLoadBlocked; } 16012479SCurtis.Dunham@arm.com 16112479SCurtis.Dunham@arm.com /** Clears the signal that a load became blocked. */ 16212479SCurtis.Dunham@arm.com void clearLoadBlocked() 16312479SCurtis.Dunham@arm.com { isLoadBlocked = false; } 16412479SCurtis.Dunham@arm.com 16512479SCurtis.Dunham@arm.com /** Returns if the blocked load was handled. */ 16612479SCurtis.Dunham@arm.com bool isLoadBlockedHandled() 16712479SCurtis.Dunham@arm.com { return loadBlockedHandled; } 16812479SCurtis.Dunham@arm.com 16912479SCurtis.Dunham@arm.com /** Records the blocked load as being handled. */ 17012479SCurtis.Dunham@arm.com void setLoadBlockedHandled() 17112479SCurtis.Dunham@arm.com { loadBlockedHandled = true; } 17212479SCurtis.Dunham@arm.com 17312479SCurtis.Dunham@arm.com /** Returns the number of free entries (min of free LQ and SQ entries). */ 17412479SCurtis.Dunham@arm.com unsigned numFreeEntries(); 17512479SCurtis.Dunham@arm.com 17612479SCurtis.Dunham@arm.com /** Returns the number of loads ready to execute. */ 17712479SCurtis.Dunham@arm.com int numLoadsReady(); 17812479SCurtis.Dunham@arm.com 17912479SCurtis.Dunham@arm.com /** Returns the number of loads in the LQ. */ 18012479SCurtis.Dunham@arm.com int numLoads() { return loads; } 18112479SCurtis.Dunham@arm.com 18212479SCurtis.Dunham@arm.com /** Returns the number of stores in the SQ. */ 18312479SCurtis.Dunham@arm.com int numStores() { return stores; } 18412479SCurtis.Dunham@arm.com 18512479SCurtis.Dunham@arm.com /** Returns if either the LQ or SQ is full. */ 18612479SCurtis.Dunham@arm.com bool isFull() { return lqFull() || sqFull(); } 18712479SCurtis.Dunham@arm.com 18812479SCurtis.Dunham@arm.com /** Returns if the LQ is full. */ 18912479SCurtis.Dunham@arm.com bool lqFull() { return loads >= (LQEntries - 1); } 19012479SCurtis.Dunham@arm.com 19112479SCurtis.Dunham@arm.com /** Returns if the SQ is full. */ 19212479SCurtis.Dunham@arm.com bool sqFull() { return stores >= (SQEntries - 1); } 19312479SCurtis.Dunham@arm.com 19412479SCurtis.Dunham@arm.com /** Returns the number of instructions in the LSQ. */ 19512479SCurtis.Dunham@arm.com unsigned getCount() { return loads + stores; } 19612479SCurtis.Dunham@arm.com 19712479SCurtis.Dunham@arm.com /** Returns if there are any stores to writeback. */ 19812479SCurtis.Dunham@arm.com bool hasStoresToWB() { return storesToWB; } 19912479SCurtis.Dunham@arm.com 20012479SCurtis.Dunham@arm.com /** Returns the number of stores to writeback. */ 20112479SCurtis.Dunham@arm.com int numStoresToWB() { return storesToWB; } 20212479SCurtis.Dunham@arm.com 20312479SCurtis.Dunham@arm.com /** Returns if the LSQ unit will writeback on this cycle. */ 20412479SCurtis.Dunham@arm.com bool willWB() { return storeQueue[storeWBIdx].canWB && 20512479SCurtis.Dunham@arm.com !storeQueue[storeWBIdx].completed && 20612479SCurtis.Dunham@arm.com !isStoreBlocked; } 20712479SCurtis.Dunham@arm.com 20812479SCurtis.Dunham@arm.com /** Handles doing the retry. */ 20912479SCurtis.Dunham@arm.com void recvRetry(); 21012479SCurtis.Dunham@arm.com 21112479SCurtis.Dunham@arm.com private: 21212479SCurtis.Dunham@arm.com /** Writes back the instruction, sending it to IEW. */ 21312668Sgiacomo.travaglini@arm.com void writeback(DynInstPtr &inst, PacketPtr pkt); 21412668Sgiacomo.travaglini@arm.com 21512668Sgiacomo.travaglini@arm.com /** Handles completing the send of a store to memory. */ 21612668Sgiacomo.travaglini@arm.com void storePostSend(PacketPtr pkt); 21712668Sgiacomo.travaglini@arm.com 21812479SCurtis.Dunham@arm.com /** Completes the store at the specified index. */ 21912479SCurtis.Dunham@arm.com void completeStore(int store_idx); 22012479SCurtis.Dunham@arm.com 22112479SCurtis.Dunham@arm.com /** Increments the given store index (circular queue). */ 22212479SCurtis.Dunham@arm.com inline void incrStIdx(int &store_idx); 22312479SCurtis.Dunham@arm.com /** Decrements the given store index (circular queue). */ 22412479SCurtis.Dunham@arm.com inline void decrStIdx(int &store_idx); 22512479SCurtis.Dunham@arm.com /** Increments the given load index (circular queue). */ 22612479SCurtis.Dunham@arm.com inline void incrLdIdx(int &load_idx); 22712479SCurtis.Dunham@arm.com /** Decrements the given load index (circular queue). */ 22812479SCurtis.Dunham@arm.com inline void decrLdIdx(int &load_idx); 22912479SCurtis.Dunham@arm.com 23012479SCurtis.Dunham@arm.com public: 23112668Sgiacomo.travaglini@arm.com /** Debugging function to dump instructions in the LSQ. */ 23212668Sgiacomo.travaglini@arm.com void dumpInsts(); 23312668Sgiacomo.travaglini@arm.com 23412668Sgiacomo.travaglini@arm.com private: 23512668Sgiacomo.travaglini@arm.com /** Pointer to the CPU. */ 23613395Sgiacomo.travaglini@arm.com O3CPU *cpu; 23713395Sgiacomo.travaglini@arm.com 23813395Sgiacomo.travaglini@arm.com /** Pointer to the IEW stage. */ 23913395Sgiacomo.travaglini@arm.com IEW *iewStage; 24013395Sgiacomo.travaglini@arm.com 24112479SCurtis.Dunham@arm.com /** Pointer to the LSQ. */ 24212479SCurtis.Dunham@arm.com LSQ *lsq; 24312479SCurtis.Dunham@arm.com 24412479SCurtis.Dunham@arm.com /** Pointer to the dcache port. Used only for sending. */ 24512479SCurtis.Dunham@arm.com Port *dcachePort; 24612479SCurtis.Dunham@arm.com 24712479SCurtis.Dunham@arm.com /** Derived class to hold any sender state the LSQ needs. */ 24812479SCurtis.Dunham@arm.com class LSQSenderState : public Packet::SenderState 24912479SCurtis.Dunham@arm.com { 25012479SCurtis.Dunham@arm.com public: 25112479SCurtis.Dunham@arm.com /** Default constructor. */ 25212479SCurtis.Dunham@arm.com LSQSenderState() 25312479SCurtis.Dunham@arm.com : noWB(false) 25412479SCurtis.Dunham@arm.com { } 25512479SCurtis.Dunham@arm.com 25612479SCurtis.Dunham@arm.com /** Instruction who initiated the access to memory. */ 25712479SCurtis.Dunham@arm.com DynInstPtr inst; 25812479SCurtis.Dunham@arm.com /** Whether or not it is a load. */ 25912479SCurtis.Dunham@arm.com bool isLoad; 26012479SCurtis.Dunham@arm.com /** The LQ/SQ index of the instruction. */ 26112479SCurtis.Dunham@arm.com int idx; 26212479SCurtis.Dunham@arm.com /** Whether or not the instruction will need to writeback. */ 26312479SCurtis.Dunham@arm.com bool noWB; 26412479SCurtis.Dunham@arm.com }; 26512479SCurtis.Dunham@arm.com 26612479SCurtis.Dunham@arm.com /** Writeback event, specifically for when stores forward data to loads. */ 26712479SCurtis.Dunham@arm.com class WritebackEvent : public Event { 26812479SCurtis.Dunham@arm.com public: 26912479SCurtis.Dunham@arm.com /** Constructs a writeback event. */ 27012479SCurtis.Dunham@arm.com WritebackEvent(DynInstPtr &_inst, PacketPtr pkt, LSQUnit *lsq_ptr); 27112479SCurtis.Dunham@arm.com 27212479SCurtis.Dunham@arm.com /** Processes the writeback event. */ 27312479SCurtis.Dunham@arm.com void process(); 27412479SCurtis.Dunham@arm.com 27512479SCurtis.Dunham@arm.com /** Returns the description of this event. */ 27612479SCurtis.Dunham@arm.com const char *description(); 27712479SCurtis.Dunham@arm.com 27812479SCurtis.Dunham@arm.com private: 27912479SCurtis.Dunham@arm.com /** Instruction whose results are being written back. */ 28012479SCurtis.Dunham@arm.com DynInstPtr inst; 28112479SCurtis.Dunham@arm.com 28212479SCurtis.Dunham@arm.com /** The packet that would have been sent to memory. */ 28312479SCurtis.Dunham@arm.com PacketPtr pkt; 28412479SCurtis.Dunham@arm.com 28512479SCurtis.Dunham@arm.com /** The pointer to the LSQ unit that issued the store. */ 28612479SCurtis.Dunham@arm.com LSQUnit<Impl> *lsqPtr; 28712479SCurtis.Dunham@arm.com }; 28812479SCurtis.Dunham@arm.com 28912479SCurtis.Dunham@arm.com public: 29012479SCurtis.Dunham@arm.com struct SQEntry { 29112479SCurtis.Dunham@arm.com /** Constructs an empty store queue entry. */ 29212479SCurtis.Dunham@arm.com SQEntry() 29312479SCurtis.Dunham@arm.com : inst(NULL), req(NULL), size(0), 29412479SCurtis.Dunham@arm.com canWB(0), committed(0), completed(0) 29512479SCurtis.Dunham@arm.com { 29612479SCurtis.Dunham@arm.com std::memset(data, 0, sizeof(data)); 29712479SCurtis.Dunham@arm.com } 29812479SCurtis.Dunham@arm.com 29912479SCurtis.Dunham@arm.com /** Constructs a store queue entry for a given instruction. */ 30012479SCurtis.Dunham@arm.com SQEntry(DynInstPtr &_inst) 30112479SCurtis.Dunham@arm.com : inst(_inst), req(NULL), size(0), 30212479SCurtis.Dunham@arm.com canWB(0), committed(0), completed(0) 30312479SCurtis.Dunham@arm.com { 30412479SCurtis.Dunham@arm.com std::memset(data, 0, sizeof(data)); 30512479SCurtis.Dunham@arm.com } 30612479SCurtis.Dunham@arm.com 30712479SCurtis.Dunham@arm.com /** The store instruction. */ 30812479SCurtis.Dunham@arm.com DynInstPtr inst; 30912479SCurtis.Dunham@arm.com /** The request for the store. */ 31012479SCurtis.Dunham@arm.com RequestPtr req; 31112479SCurtis.Dunham@arm.com /** The size of the store. */ 31212479SCurtis.Dunham@arm.com int size; 31312479SCurtis.Dunham@arm.com /** The store data. */ 31412479SCurtis.Dunham@arm.com char data[sizeof(IntReg)]; 31512479SCurtis.Dunham@arm.com /** Whether or not the store can writeback. */ 31612479SCurtis.Dunham@arm.com bool canWB; 31712479SCurtis.Dunham@arm.com /** Whether or not the store is committed. */ 31812479SCurtis.Dunham@arm.com bool committed; 31912479SCurtis.Dunham@arm.com /** Whether or not the store is completed. */ 32012479SCurtis.Dunham@arm.com bool completed; 32112479SCurtis.Dunham@arm.com }; 32212479SCurtis.Dunham@arm.com 32312479SCurtis.Dunham@arm.com private: 32412479SCurtis.Dunham@arm.com /** The LSQUnit thread id. */ 32512479SCurtis.Dunham@arm.com unsigned lsqID; 32612479SCurtis.Dunham@arm.com 32712479SCurtis.Dunham@arm.com /** The store queue. */ 32812479SCurtis.Dunham@arm.com std::vector<SQEntry> storeQueue; 32912479SCurtis.Dunham@arm.com 33012479SCurtis.Dunham@arm.com /** The load queue. */ 33112479SCurtis.Dunham@arm.com std::vector<DynInstPtr> loadQueue; 33212479SCurtis.Dunham@arm.com 33312479SCurtis.Dunham@arm.com /** The number of LQ entries, plus a sentinel entry (circular queue). 33412479SCurtis.Dunham@arm.com * @todo: Consider having var that records the true number of LQ entries. 33512479SCurtis.Dunham@arm.com */ 33612479SCurtis.Dunham@arm.com unsigned LQEntries; 33712479SCurtis.Dunham@arm.com /** The number of SQ entries, plus a sentinel entry (circular queue). 33812479SCurtis.Dunham@arm.com * @todo: Consider having var that records the true number of SQ entries. 33912479SCurtis.Dunham@arm.com */ 34012479SCurtis.Dunham@arm.com unsigned SQEntries; 34112479SCurtis.Dunham@arm.com 34212479SCurtis.Dunham@arm.com /** The number of load instructions in the LQ. */ 34312479SCurtis.Dunham@arm.com int loads; 34412479SCurtis.Dunham@arm.com /** The number of store instructions in the SQ. */ 34512479SCurtis.Dunham@arm.com int stores; 34612479SCurtis.Dunham@arm.com /** The number of store instructions in the SQ waiting to writeback. */ 34712479SCurtis.Dunham@arm.com int storesToWB; 34812479SCurtis.Dunham@arm.com 34912479SCurtis.Dunham@arm.com /** The index of the head instruction in the LQ. */ 35012479SCurtis.Dunham@arm.com int loadHead; 35112479SCurtis.Dunham@arm.com /** The index of the tail instruction in the LQ. */ 35212479SCurtis.Dunham@arm.com int loadTail; 35312479SCurtis.Dunham@arm.com 35412479SCurtis.Dunham@arm.com /** The index of the head instruction in the SQ. */ 35512479SCurtis.Dunham@arm.com int storeHead; 35610037SARM gem5 Developers /** The index of the first instruction that may be ready to be 35710037SARM gem5 Developers * written back, and has not yet been written back. 35812477SCurtis.Dunham@arm.com */ 35912479SCurtis.Dunham@arm.com int storeWBIdx; 36012479SCurtis.Dunham@arm.com /** The index of the tail instruction in the SQ. */ 36112477SCurtis.Dunham@arm.com int storeTail; 36210037SARM gem5 Developers 36312477SCurtis.Dunham@arm.com /// @todo Consider moving to a more advanced model with write vs read ports 36410037SARM gem5 Developers /** The number of cache ports available each cycle. */ 3656333Sgblack@eecs.umich.edu int cachePorts; 3666718Sgblack@eecs.umich.edu 3676718Sgblack@eecs.umich.edu /** The number of used cache ports in this cycle. */ 3686718Sgblack@eecs.umich.edu int usedPorts; 3696718Sgblack@eecs.umich.edu 3706718Sgblack@eecs.umich.edu /** Is the LSQ switched out. */ 37110037SARM gem5 Developers bool switchedOut; 37210037SARM gem5 Developers 37310037SARM gem5 Developers //list<InstSeqNum> mshrSeqNums; 37410037SARM gem5 Developers 37510037SARM gem5 Developers /** Wire to read information from the issue stage time queue. */ 37610037SARM gem5 Developers typename TimeBuffer<IssueStruct>::wire fromIssue; 37710037SARM gem5 Developers 37810037SARM gem5 Developers /** Whether or not the LSQ is stalled. */ 37910037SARM gem5 Developers bool stalled; 38010037SARM gem5 Developers /** The store that causes the stall due to partial store to load 38110037SARM gem5 Developers * forwarding. 38210037SARM gem5 Developers */ 38310037SARM gem5 Developers InstSeqNum stallingStoreIsn; 38410037SARM gem5 Developers /** The index of the above store. */ 38510037SARM gem5 Developers int stallingLoadIdx; 38610037SARM gem5 Developers 38710037SARM gem5 Developers /** The packet that needs to be retried. */ 38810037SARM gem5 Developers PacketPtr retryPkt; 38910037SARM gem5 Developers 39010037SARM gem5 Developers /** Whehter or not a store is blocked due to the memory system. */ 39110037SARM gem5 Developers bool isStoreBlocked; 39210037SARM gem5 Developers 39310037SARM gem5 Developers /** Whether or not a load is blocked due to the memory system. */ 39410037SARM gem5 Developers bool isLoadBlocked; 39510037SARM gem5 Developers 39610037SARM gem5 Developers /** Has the blocked load been handled. */ 39710037SARM gem5 Developers bool loadBlockedHandled; 39810037SARM gem5 Developers 39910037SARM gem5 Developers /** The sequence number of the blocked load. */ 40010037SARM gem5 Developers InstSeqNum blockedLoadSeqNum; 40110037SARM gem5 Developers 40210037SARM gem5 Developers /** The oldest load that caused a memory ordering violation. */ 4036718Sgblack@eecs.umich.edu DynInstPtr memDepViolator; 4046718Sgblack@eecs.umich.edu 4056313Sgblack@eecs.umich.edu // Will also need how many read/write ports the Dcache has. Or keep track 40610844Sandreas.sandberg@arm.com // of that in stage that is one level up, and only call executeLoad/Store 40713531Sjairo.balart@metempsy.com // the appropriate number of times. 40810037SARM gem5 Developers /** Total number of loads forwaded from LSQ stores. */ 40910037SARM gem5 Developers Stats::Scalar<> lsqForwLoads; 41010037SARM gem5 Developers 41110037SARM gem5 Developers /** Total number of loads ignored due to invalid addresses. */ 41210037SARM gem5 Developers Stats::Scalar<> invAddrLoads; 41310037SARM gem5 Developers 41410037SARM gem5 Developers /** Total number of squashed loads. */ 41510037SARM gem5 Developers Stats::Scalar<> lsqSquashedLoads; 41610037SARM gem5 Developers 41710037SARM gem5 Developers /** Total number of responses from the memory system that are 41810037SARM gem5 Developers * ignored due to the instruction already being squashed. */ 41910037SARM gem5 Developers Stats::Scalar<> lsqIgnoredResponses; 42010037SARM gem5 Developers 4216313Sgblack@eecs.umich.edu /** Tota number of memory ordering violations. */ 4227427Sgblack@eecs.umich.edu Stats::Scalar<> lsqMemOrderViolation; 42313114Sgiacomo.travaglini@arm.com 42413114Sgiacomo.travaglini@arm.com /** Total number of squashed stores. */ 42513393Sgiacomo.travaglini@arm.com Stats::Scalar<> lsqSquashedStores; 42610037SARM gem5 Developers 42713114Sgiacomo.travaglini@arm.com /** Total number of software prefetches ignored due to invalid addresses. */ 42813114Sgiacomo.travaglini@arm.com Stats::Scalar<> invAddrSwpfs; 4296313Sgblack@eecs.umich.edu 43013114Sgiacomo.travaglini@arm.com /** Ready loads blocked due to partial store-forwarding. */ 43110035Sandreas.hansson@arm.com Stats::Scalar<> lsqBlockedLoads; 4327405SAli.Saidi@ARM.com 4337405SAli.Saidi@ARM.com /** Number of loads that were rescheduled. */ 4347405SAli.Saidi@ARM.com Stats::Scalar<> lsqRescheduledLoads; 4356313Sgblack@eecs.umich.edu 43612106SRekai.GonzalezAlberquilla@arm.com /** Number of times the LSQ is blocked due to the cache. */ 43712106SRekai.GonzalezAlberquilla@arm.com Stats::Scalar<> lsqCacheBlocked; 43812106SRekai.GonzalezAlberquilla@arm.com 43912106SRekai.GonzalezAlberquilla@arm.com public: 44012106SRekai.GonzalezAlberquilla@arm.com /** Executes the load at the given index. */ 44112106SRekai.GonzalezAlberquilla@arm.com template <class T> 44212106SRekai.GonzalezAlberquilla@arm.com Fault read(Request *req, T &data, int load_idx); 44312106SRekai.GonzalezAlberquilla@arm.com 44412109SRekai.GonzalezAlberquilla@arm.com /** Executes the store at the given index. */ 44512109SRekai.GonzalezAlberquilla@arm.com template <class T> 44612109SRekai.GonzalezAlberquilla@arm.com Fault write(Request *req, T &data, int store_idx); 44713545Sgiacomo.travaglini@arm.com 44813545Sgiacomo.travaglini@arm.com /** Returns the index of the head load instruction. */ 44912106SRekai.GonzalezAlberquilla@arm.com int getLoadHead() { return loadHead; } 45012106SRekai.GonzalezAlberquilla@arm.com /** Returns the sequence number of the head load instruction. */ 45112106SRekai.GonzalezAlberquilla@arm.com InstSeqNum getLoadHeadSeqNum() 45212106SRekai.GonzalezAlberquilla@arm.com { 45312106SRekai.GonzalezAlberquilla@arm.com if (loadQueue[loadHead]) { 45412106SRekai.GonzalezAlberquilla@arm.com return loadQueue[loadHead]->seqNum; 45512106SRekai.GonzalezAlberquilla@arm.com } else { 45612106SRekai.GonzalezAlberquilla@arm.com return 0; 4576313Sgblack@eecs.umich.edu } 45810035Sandreas.hansson@arm.com 4596313Sgblack@eecs.umich.edu } 4606718Sgblack@eecs.umich.edu 4616718Sgblack@eecs.umich.edu /** Returns the index of the head store instruction. */ 4626718Sgblack@eecs.umich.edu int getStoreHead() { return storeHead; } 4636726Sgblack@eecs.umich.edu /** Returns the sequence number of the head store instruction. */ 4646726Sgblack@eecs.umich.edu InstSeqNum getStoreHeadSeqNum() 46510037SARM gem5 Developers { 46610037SARM gem5 Developers if (storeQueue[storeHead].inst) { 46710037SARM gem5 Developers return storeQueue[storeHead].inst->seqNum; 46810037SARM gem5 Developers } else { 46910037SARM gem5 Developers return 0; 47010037SARM gem5 Developers } 47110037SARM gem5 Developers 47210037SARM gem5 Developers } 47310037SARM gem5 Developers 47411574SCurtis.Dunham@arm.com /** Returns whether or not the LSQ unit is stalled. */ 47511574SCurtis.Dunham@arm.com bool isStalled() { return stalled; } 47610037SARM gem5 Developers}; 47710037SARM gem5 Developers 47810037SARM gem5 Developerstemplate <class Impl> 47910037SARM gem5 Developerstemplate <class T> 48010037SARM gem5 DevelopersFault 48110037SARM gem5 DevelopersLSQUnit<Impl>::read(Request *req, T &data, int load_idx) 48213020Sshunhsingou@google.com{ 48310037SARM gem5 Developers DynInstPtr load_inst = loadQueue[load_idx]; 4846718Sgblack@eecs.umich.edu 48510037SARM gem5 Developers assert(load_inst); 4866718Sgblack@eecs.umich.edu 4876313Sgblack@eecs.umich.edu assert(!load_inst->isExecuted()); 4886313Sgblack@eecs.umich.edu 4896313Sgblack@eecs.umich.edu // Make sure this isn't an uncacheable access 49010035Sandreas.hansson@arm.com // A bit of a hackish way to get uncached accesses to work only if they're 4916313Sgblack@eecs.umich.edu // at the head of the LSQ and are ready to commit (at the head of the ROB 49210338SCurtis.Dunham@arm.com // too). 4936313Sgblack@eecs.umich.edu if (req->isUncacheable() && 4946313Sgblack@eecs.umich.edu (load_idx != loadHead || !load_inst->isAtCommit())) { 4956313Sgblack@eecs.umich.edu iewStage->rescheduleMemInst(load_inst); 4969920Syasuko.eckert@amd.com ++lsqRescheduledLoads; 49712109SRekai.GonzalezAlberquilla@arm.com 49812109SRekai.GonzalezAlberquilla@arm.com // Must delete request now that it wasn't handed off to 49912109SRekai.GonzalezAlberquilla@arm.com // memory. This is quite ugly. @todo: Figure out the proper 50012109SRekai.GonzalezAlberquilla@arm.com // place to really handle request deletes. 50112109SRekai.GonzalezAlberquilla@arm.com delete req; 50212109SRekai.GonzalezAlberquilla@arm.com return TheISA::genMachineCheckFault(); 50312109SRekai.GonzalezAlberquilla@arm.com } 50412109SRekai.GonzalezAlberquilla@arm.com 50512109SRekai.GonzalezAlberquilla@arm.com // Check the SQ for any previous stores that might lead to forwarding 50612109SRekai.GonzalezAlberquilla@arm.com int store_idx = load_inst->sqIdx; 50712109SRekai.GonzalezAlberquilla@arm.com 50812109SRekai.GonzalezAlberquilla@arm.com int store_size = 0; 50912109SRekai.GonzalezAlberquilla@arm.com 51012109SRekai.GonzalezAlberquilla@arm.com DPRINTF(LSQUnit, "Read called, load idx: %i, store idx: %i, " 51110035Sandreas.hansson@arm.com "storeHead: %i addr: %#x\n", 5129920Syasuko.eckert@amd.com load_idx, store_idx, storeHead, req->getPaddr()); 51310338SCurtis.Dunham@arm.com 5149920Syasuko.eckert@amd.com if (req->isLocked()) { 5159920Syasuko.eckert@amd.com // Disable recording the result temporarily. Writing to misc 5169920Syasuko.eckert@amd.com // regs normally updates the result, but this is not the 5177614Sminkyu.jeong@arm.com // desired behavior when handling store conditionals. 51810035Sandreas.hansson@arm.com load_inst->recordResult = false; 5197614Sminkyu.jeong@arm.com TheISA::handleLockedRead(load_inst.get(), req); 52010338SCurtis.Dunham@arm.com load_inst->recordResult = true; 52110037SARM gem5 Developers } 52210037SARM gem5 Developers 5237614Sminkyu.jeong@arm.com while (store_idx != -1) { 5247614Sminkyu.jeong@arm.com // End once we've reached the top of the LSQ 5257614Sminkyu.jeong@arm.com if (store_idx == storeWBIdx) { 52610037SARM gem5 Developers break; 52710037SARM gem5 Developers } 52810037SARM gem5 Developers 52910037SARM gem5 Developers // Move the index to one younger 53010037SARM gem5 Developers if (--store_idx < 0) 53110037SARM gem5 Developers store_idx += SQEntries; 53210037SARM gem5 Developers 53310037SARM gem5 Developers assert(storeQueue[store_idx].inst); 53410037SARM gem5 Developers 53510037SARM gem5 Developers store_size = storeQueue[store_idx].size; 53610037SARM gem5 Developers 53710037SARM gem5 Developers if (store_size == 0) 53810037SARM gem5 Developers continue; 53910037SARM gem5 Developers else if (storeQueue[store_idx].inst->uncacheable()) 54010037SARM gem5 Developers continue; 54110037SARM gem5 Developers 5427614Sminkyu.jeong@arm.com assert(storeQueue[store_idx].inst->effAddrValid); 5437614Sminkyu.jeong@arm.com 54410037SARM gem5 Developers // Check if the store data is within the lower and upper bounds of 5457614Sminkyu.jeong@arm.com // addresses that the request needs. 5467614Sminkyu.jeong@arm.com bool store_has_lower_limit = 54710037SARM gem5 Developers req->getVaddr() >= storeQueue[store_idx].inst->effAddr; 5487614Sminkyu.jeong@arm.com bool store_has_upper_limit = 5497614Sminkyu.jeong@arm.com (req->getVaddr() + req->getSize()) <= 55010037SARM gem5 Developers (storeQueue[store_idx].inst->effAddr + store_size); 5517614Sminkyu.jeong@arm.com bool lower_load_has_store_part = 5527614Sminkyu.jeong@arm.com req->getVaddr() < (storeQueue[store_idx].inst->effAddr + 55310037SARM gem5 Developers store_size); 5547614Sminkyu.jeong@arm.com bool upper_load_has_store_part = 5557614Sminkyu.jeong@arm.com (req->getVaddr() + req->getSize()) > 55610037SARM gem5 Developers storeQueue[store_idx].inst->effAddr; 5577614Sminkyu.jeong@arm.com 5587614Sminkyu.jeong@arm.com // If the store's data has all of the data needed, we can forward. 55910037SARM gem5 Developers if ((store_has_lower_limit && store_has_upper_limit)) { 56010037SARM gem5 Developers // Get shift amount for offset into the store's data. 56110037SARM gem5 Developers int shift_amt = req->getVaddr() & (store_size - 1); 56210037SARM gem5 Developers 5637614Sminkyu.jeong@arm.com memcpy(&data, storeQueue[store_idx].data + shift_amt, sizeof(T)); 5647614Sminkyu.jeong@arm.com 56510037SARM gem5 Developers assert(!load_inst->memData); 5667614Sminkyu.jeong@arm.com load_inst->memData = new uint8_t[64]; 5677614Sminkyu.jeong@arm.com 5687614Sminkyu.jeong@arm.com memcpy(load_inst->memData, 5697614Sminkyu.jeong@arm.com storeQueue[store_idx].data + shift_amt, req->getSize()); 57010037SARM gem5 Developers 5717614Sminkyu.jeong@arm.com DPRINTF(LSQUnit, "Forwarding from store idx %i to load to " 5727614Sminkyu.jeong@arm.com "addr %#x, data %#x\n", 57310037SARM gem5 Developers store_idx, req->getVaddr(), data); 57410037SARM gem5 Developers 57510037SARM gem5 Developers PacketPtr data_pkt = new Packet(req, MemCmd::ReadReq, 57610037SARM gem5 Developers Packet::Broadcast); 57710037SARM gem5 Developers data_pkt->dataStatic(load_inst->memData); 57810037SARM gem5 Developers 57910037SARM gem5 Developers WritebackEvent *wb = new WritebackEvent(load_inst, data_pkt, this); 58010037SARM gem5 Developers 58110037SARM gem5 Developers // We'll say this has a 1 cycle load-store forwarding latency 58210037SARM gem5 Developers // for now. 58310037SARM gem5 Developers // @todo: Need to make this a parameter. 58410037SARM gem5 Developers wb->schedule(curTick); 58510037SARM gem5 Developers 58610037SARM gem5 Developers ++lsqForwLoads; 58710037SARM gem5 Developers return NoFault; 58810037SARM gem5 Developers } else if ((store_has_lower_limit && lower_load_has_store_part) || 58910037SARM gem5 Developers (store_has_upper_limit && upper_load_has_store_part) || 59010037SARM gem5 Developers (lower_load_has_store_part && upper_load_has_store_part)) { 59110037SARM gem5 Developers // This is the partial store-load forwarding case where a store 59210037SARM gem5 Developers // has only part of the load's data. 59310037SARM gem5 Developers 59410037SARM gem5 Developers // If it's already been written back, then don't worry about 59510037SARM gem5 Developers // stalling on it. 59610037SARM gem5 Developers if (storeQueue[store_idx].completed) { 59710037SARM gem5 Developers panic("Should not check one of these"); 59810037SARM gem5 Developers continue; 59910037SARM gem5 Developers } 60010037SARM gem5 Developers 60110037SARM gem5 Developers // Must stall load and force it to retry, so long as it's the oldest 60210037SARM gem5 Developers // load that needs to do so. 60310037SARM gem5 Developers if (!stalled || 60410037SARM gem5 Developers (stalled && 60510037SARM gem5 Developers load_inst->seqNum < 60610037SARM gem5 Developers loadQueue[stallingLoadIdx]->seqNum)) { 60710037SARM gem5 Developers stalled = true; 60810037SARM gem5 Developers stallingStoreIsn = storeQueue[store_idx].inst->seqNum; 60910037SARM gem5 Developers stallingLoadIdx = load_idx; 61010037SARM gem5 Developers } 61110037SARM gem5 Developers 61210037SARM gem5 Developers // Tell IQ/mem dep unit that this instruction will need to be 61310037SARM gem5 Developers // rescheduled eventually 61410037SARM gem5 Developers iewStage->rescheduleMemInst(load_inst); 61510037SARM gem5 Developers iewStage->decrWb(load_inst->seqNum); 61610037SARM gem5 Developers load_inst->clearIssued(); 61710037SARM gem5 Developers ++lsqRescheduledLoads; 61810037SARM gem5 Developers 61910037SARM gem5 Developers // Do not generate a writeback event as this instruction is not 62010037SARM gem5 Developers // complete. 62110037SARM gem5 Developers DPRINTF(LSQUnit, "Load-store forwarding mis-match. " 62210037SARM gem5 Developers "Store idx %i to load addr %#x\n", 62311771SCurtis.Dunham@arm.com store_idx, req->getVaddr()); 62410037SARM gem5 Developers 62510037SARM gem5 Developers // Must delete request now that it wasn't handed off to 62610037SARM gem5 Developers // memory. This is quite ugly. @todo: Figure out the 62710037SARM gem5 Developers // proper place to really handle request deletes. 6287614Sminkyu.jeong@arm.com delete req; 62910037SARM gem5 Developers 6307614Sminkyu.jeong@arm.com return NoFault; 6317614Sminkyu.jeong@arm.com } 63211771SCurtis.Dunham@arm.com } 63311771SCurtis.Dunham@arm.com 63411771SCurtis.Dunham@arm.com // If there's no forwarding case, then go access memory 63511771SCurtis.Dunham@arm.com DPRINTF(LSQUnit, "Doing memory access for inst [sn:%lli] PC %#x\n", 63611771SCurtis.Dunham@arm.com load_inst->seqNum, load_inst->readPC()); 63711771SCurtis.Dunham@arm.com 63811771SCurtis.Dunham@arm.com assert(!load_inst->memData); 63911771SCurtis.Dunham@arm.com load_inst->memData = new uint8_t[64]; 64011771SCurtis.Dunham@arm.com 64111771SCurtis.Dunham@arm.com ++usedPorts; 64211771SCurtis.Dunham@arm.com 64311771SCurtis.Dunham@arm.com // if we the cache is not blocked, do cache access 64411771SCurtis.Dunham@arm.com if (!lsq->cacheBlocked()) { 64511771SCurtis.Dunham@arm.com PacketPtr data_pkt = 64611771SCurtis.Dunham@arm.com new Packet(req, MemCmd::ReadReq, Packet::Broadcast); 64711771SCurtis.Dunham@arm.com data_pkt->dataStatic(load_inst->memData); 64811771SCurtis.Dunham@arm.com 64911771SCurtis.Dunham@arm.com LSQSenderState *state = new LSQSenderState; 65011771SCurtis.Dunham@arm.com state->isLoad = true; 65111771SCurtis.Dunham@arm.com state->idx = load_idx; 65211771SCurtis.Dunham@arm.com state->inst = load_inst; 65310905Sandreas.sandberg@arm.com data_pkt->senderState = state; 6547733SAli.Saidi@ARM.com 6557733SAli.Saidi@ARM.com if (!dcachePort->sendTiming(data_pkt)) { 65612529Sgiacomo.travaglini@arm.com Packet::Result result = data_pkt->result; 65710037SARM gem5 Developers 65811771SCurtis.Dunham@arm.com // Delete state and data packet because a load retry 65910037SARM gem5 Developers // initiates a pipeline restart; it does not retry. 66010037SARM gem5 Developers delete state; 66110037SARM gem5 Developers delete data_pkt->req; 66210037SARM gem5 Developers delete data_pkt; 66313114Sgiacomo.travaglini@arm.com 6647733SAli.Saidi@ARM.com req = NULL; 66510905Sandreas.sandberg@arm.com 6667733SAli.Saidi@ARM.com if (result == Packet::BadAddress) { 6677733SAli.Saidi@ARM.com return TheISA::genMachineCheckFault(); 66812529Sgiacomo.travaglini@arm.com } 6697733SAli.Saidi@ARM.com 6707733SAli.Saidi@ARM.com // If the access didn't succeed, tell the LSQ by setting 67110037SARM gem5 Developers // the retry thread id. 67211771SCurtis.Dunham@arm.com lsq->setRetryTid(lsqID); 67310037SARM gem5 Developers } 67410037SARM gem5 Developers } 67510037SARM gem5 Developers 67610037SARM gem5 Developers // If the cache was blocked, or has become blocked due to the access, 67713114Sgiacomo.travaglini@arm.com // handle it. 6787733SAli.Saidi@ARM.com if (lsq->cacheBlocked()) { 6796313Sgblack@eecs.umich.edu if (req) 68012972Sandreas.sandberg@arm.com delete req; 6819461Snilay@cs.wisc.edu 68211165SRekai.GonzalezAlberquilla@arm.com ++lsqCacheBlocked; 68311165SRekai.GonzalezAlberquilla@arm.com 68412109SRekai.GonzalezAlberquilla@arm.com iewStage->decrWb(load_inst->seqNum); 68512109SRekai.GonzalezAlberquilla@arm.com // There's an older load that's already going to squash. 68612109SRekai.GonzalezAlberquilla@arm.com if (isLoadBlocked && blockedLoadSeqNum < load_inst->seqNum) 68712109SRekai.GonzalezAlberquilla@arm.com return NoFault; 68812109SRekai.GonzalezAlberquilla@arm.com 68912109SRekai.GonzalezAlberquilla@arm.com // Record that the load was blocked due to memory. This 6909553Sandreas.hansson@arm.com // load will squash all instructions after it, be 6919553Sandreas.hansson@arm.com // refetched, and re-executed. 6929553Sandreas.hansson@arm.com isLoadBlocked = true; 6939384SAndreas.Sandberg@arm.com loadBlockedHandled = false; 6947400SAli.Saidi@ARM.com blockedLoadSeqNum = load_inst->seqNum; 6959384SAndreas.Sandberg@arm.com // No fault occurred, even though the interface is blocked. 6969384SAndreas.Sandberg@arm.com return NoFault; 6979384SAndreas.Sandberg@arm.com } 6986313Sgblack@eecs.umich.edu 6996313Sgblack@eecs.umich.edu return NoFault; 7006313Sgblack@eecs.umich.edu} 70112109SRekai.GonzalezAlberquilla@arm.com 70212109SRekai.GonzalezAlberquilla@arm.comtemplate <class Impl> 70312109SRekai.GonzalezAlberquilla@arm.comtemplate <class T> 70412109SRekai.GonzalezAlberquilla@arm.comFault 70512109SRekai.GonzalezAlberquilla@arm.comLSQUnit<Impl>::write(Request *req, T &data, int store_idx) 70612109SRekai.GonzalezAlberquilla@arm.com{ 70712109SRekai.GonzalezAlberquilla@arm.com assert(storeQueue[store_idx].inst); 70812109SRekai.GonzalezAlberquilla@arm.com 70912109SRekai.GonzalezAlberquilla@arm.com DPRINTF(LSQUnit, "Doing write to store idx %i, addr %#x data %#x" 71012109SRekai.GonzalezAlberquilla@arm.com " | storeHead:%i [sn:%i]\n", 71112109SRekai.GonzalezAlberquilla@arm.com store_idx, req->getPaddr(), data, storeHead, 71212109SRekai.GonzalezAlberquilla@arm.com storeQueue[store_idx].inst->seqNum); 71312109SRekai.GonzalezAlberquilla@arm.com 7146313Sgblack@eecs.umich.edu 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