lsq.hh revision 13710:5ba1d8066ef0
17404SAli.Saidi@ARM.com/* 27404SAli.Saidi@ARM.com * Copyright (c) 2011-2012, 2014, 2018 ARM Limited 37404SAli.Saidi@ARM.com * Copyright (c) 2013 Advanced Micro Devices, Inc. 47404SAli.Saidi@ARM.com * All rights reserved 57404SAli.Saidi@ARM.com * 67404SAli.Saidi@ARM.com * The license below extends only to copyright in the software and shall 77404SAli.Saidi@ARM.com * not be construed as granting a license to any other intellectual 87404SAli.Saidi@ARM.com * property including but not limited to intellectual property relating 97404SAli.Saidi@ARM.com * to a hardware implementation of the functionality of the software 107404SAli.Saidi@ARM.com * licensed hereunder. You may use the software subject to the license 117404SAli.Saidi@ARM.com * terms below provided that you ensure that this notice is replicated 127404SAli.Saidi@ARM.com * unmodified and in its entirety in all distributions of the software, 137404SAli.Saidi@ARM.com * modified or unmodified, in source code or in binary form. 147404SAli.Saidi@ARM.com * 157404SAli.Saidi@ARM.com * Copyright (c) 2004-2006 The Regents of The University of Michigan 167404SAli.Saidi@ARM.com * All rights reserved. 177404SAli.Saidi@ARM.com * 187404SAli.Saidi@ARM.com * Redistribution and use in source and binary forms, with or without 197404SAli.Saidi@ARM.com * modification, are permitted provided that the following conditions are 207404SAli.Saidi@ARM.com * met: redistributions of source code must retain the above copyright 217404SAli.Saidi@ARM.com * notice, this list of conditions and the following disclaimer; 227404SAli.Saidi@ARM.com * redistributions in binary form must reproduce the above copyright 237404SAli.Saidi@ARM.com * notice, this list of conditions and the following disclaimer in the 247404SAli.Saidi@ARM.com * documentation and/or other materials provided with the distribution; 257404SAli.Saidi@ARM.com * neither the name of the copyright holders nor the names of its 267404SAli.Saidi@ARM.com * contributors may be used to endorse or promote products derived from 277404SAli.Saidi@ARM.com * this software without specific prior written permission. 287404SAli.Saidi@ARM.com * 297404SAli.Saidi@ARM.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 307404SAli.Saidi@ARM.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 317404SAli.Saidi@ARM.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 327404SAli.Saidi@ARM.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 337404SAli.Saidi@ARM.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 347404SAli.Saidi@ARM.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 357404SAli.Saidi@ARM.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 367404SAli.Saidi@ARM.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 377404SAli.Saidi@ARM.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 387404SAli.Saidi@ARM.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 397404SAli.Saidi@ARM.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 407404SAli.Saidi@ARM.com * 417404SAli.Saidi@ARM.com * Authors: Korey Sewell 427404SAli.Saidi@ARM.com */ 437578Sdam.sunwoo@arm.com 447578Sdam.sunwoo@arm.com#ifndef __CPU_O3_LSQ_HH__ 457404SAli.Saidi@ARM.com#define __CPU_O3_LSQ_HH__ 467404SAli.Saidi@ARM.com 478851Sandreas.hansson@arm.com#include <map> 487404SAli.Saidi@ARM.com#include <queue> 497404SAli.Saidi@ARM.com 507404SAli.Saidi@ARM.com#include "arch/generic/tlb.hh" 517404SAli.Saidi@ARM.com#include "cpu/inst_seq.hh" 527878Sgblack@eecs.umich.edu#include "cpu/o3/lsq_unit.hh" 537404SAli.Saidi@ARM.com#include "enums/SMTQueuePolicy.hh" 547404SAli.Saidi@ARM.com#include "mem/port.hh" 557404SAli.Saidi@ARM.com#include "sim/sim_object.hh" 567404SAli.Saidi@ARM.com 577404SAli.Saidi@ARM.comstruct DerivO3CPUParams; 587404SAli.Saidi@ARM.com 597404SAli.Saidi@ARM.comtemplate <class Impl> 607404SAli.Saidi@ARM.comclass LSQ 617404SAli.Saidi@ARM.com 627404SAli.Saidi@ARM.com{ 637694SAli.Saidi@ARM.com public: 647404SAli.Saidi@ARM.com typedef typename Impl::O3CPU O3CPU; 657404SAli.Saidi@ARM.com typedef typename Impl::DynInstPtr DynInstPtr; 667404SAli.Saidi@ARM.com typedef typename Impl::CPUPol::IEW IEW; 677404SAli.Saidi@ARM.com typedef typename Impl::CPUPol::LSQUnit LSQUnit; 687404SAli.Saidi@ARM.com 697404SAli.Saidi@ARM.com class LSQRequest; 707404SAli.Saidi@ARM.com /** Derived class to hold any sender state the LSQ needs. */ 717404SAli.Saidi@ARM.com class LSQSenderState : public Packet::SenderState 727404SAli.Saidi@ARM.com { 737436Sdam.sunwoo@arm.com protected: 747404SAli.Saidi@ARM.com /** The senderState needs to know the LSQRequest who owns it. */ 757404SAli.Saidi@ARM.com LSQRequest* _request; 767436Sdam.sunwoo@arm.com 777436Sdam.sunwoo@arm.com /** Default constructor. */ 787436Sdam.sunwoo@arm.com LSQSenderState(LSQRequest* request, bool isLoad_) 797436Sdam.sunwoo@arm.com : _request(request), mainPkt(nullptr), pendingPacket(nullptr), 807404SAli.Saidi@ARM.com outstanding(0), isLoad(isLoad_), needWB(isLoad_), isSplit(false), 817404SAli.Saidi@ARM.com pktToSend(false), deleted(false) 827404SAli.Saidi@ARM.com { } 837404SAli.Saidi@ARM.com public: 847404SAli.Saidi@ARM.com 857404SAli.Saidi@ARM.com /** Instruction which initiated the access to memory. */ 867404SAli.Saidi@ARM.com DynInstPtr inst; 877404SAli.Saidi@ARM.com /** The main packet from a split load, used during writeback. */ 887404SAli.Saidi@ARM.com PacketPtr mainPkt; 897404SAli.Saidi@ARM.com /** A second packet from a split store that needs sending. */ 907404SAli.Saidi@ARM.com PacketPtr pendingPacket; 917404SAli.Saidi@ARM.com /** Number of outstanding packets to complete. */ 927404SAli.Saidi@ARM.com uint8_t outstanding; 937404SAli.Saidi@ARM.com /** Whether or not it is a load. */ 947404SAli.Saidi@ARM.com bool isLoad; 957404SAli.Saidi@ARM.com /** Whether or not the instruction will need to writeback. */ 967946SGiacomo.Gabrielli@arm.com bool needWB; 977404SAli.Saidi@ARM.com /** Whether or not this access is split in two. */ 987694SAli.Saidi@ARM.com bool isSplit; 997694SAli.Saidi@ARM.com /** Whether or not there is a packet that needs sending. */ 1007694SAli.Saidi@ARM.com bool pktToSend; 1017694SAli.Saidi@ARM.com /** Has the request been deleted? 1027694SAli.Saidi@ARM.com * LSQ entries can be squashed before the response comes back. in that 1037946SGiacomo.Gabrielli@arm.com * case the SenderState knows. 1047694SAli.Saidi@ARM.com */ 1057694SAli.Saidi@ARM.com bool deleted; 1067404SAli.Saidi@ARM.com ContextID contextId() { return inst->contextId(); } 1077404SAli.Saidi@ARM.com 1087404SAli.Saidi@ARM.com /** Completes a packet and returns whether the access is finished. */ 1097404SAli.Saidi@ARM.com inline bool isComplete() { return outstanding == 0; } 1107404SAli.Saidi@ARM.com inline void deleteRequest() { deleted = true; } 1117404SAli.Saidi@ARM.com inline bool alive() { return !deleted; } 1127946SGiacomo.Gabrielli@arm.com LSQRequest* request() { return _request; } 1137404SAli.Saidi@ARM.com virtual void complete() = 0; 1147404SAli.Saidi@ARM.com void writebackDone() { _request->writebackDone(); } 1157404SAli.Saidi@ARM.com }; 1167404SAli.Saidi@ARM.com 1177404SAli.Saidi@ARM.com /** Memory operation metadata. 1187608SGene.Wu@arm.com * This class holds the information about a memory operation. It lives 1197404SAli.Saidi@ARM.com * from initiateAcc to resource deallocation at commit or squash. 1207404SAli.Saidi@ARM.com * LSQRequest objects are owned by the LQ/SQ Entry in the LSQUnit that 1217404SAli.Saidi@ARM.com * holds the operation. It is also used by the LSQSenderState. In addition, 1227404SAli.Saidi@ARM.com * the LSQRequest is a TranslationState, therefore, upon squash, there must 1237404SAli.Saidi@ARM.com * be a defined ownership transferal in case the LSQ resources are 1247608SGene.Wu@arm.com * deallocated before the TLB is done using the TranslationState. If that 1257404SAli.Saidi@ARM.com * happens, the LSQRequest will be self-owned, and responsible to detect 1267404SAli.Saidi@ARM.com * that its services are no longer required and self-destruct. 1277404SAli.Saidi@ARM.com * 1287404SAli.Saidi@ARM.com * Lifetime of a LSQRequest: 1297404SAli.Saidi@ARM.com * +--------------------+ 1307946SGiacomo.Gabrielli@arm.com * |LSQ creates and owns| 1317404SAli.Saidi@ARM.com * +--------------------+ 1327404SAli.Saidi@ARM.com * | 1337404SAli.Saidi@ARM.com * +--------------------+ 1347404SAli.Saidi@ARM.com * | Initate translation| 1357404SAli.Saidi@ARM.com * +--------------------+ 1367946SGiacomo.Gabrielli@arm.com * | 1377404SAli.Saidi@ARM.com * ___^___ 1387404SAli.Saidi@ARM.com * ___/ \___ 1397404SAli.Saidi@ARM.com * ______/ Squashed? \ 1407404SAli.Saidi@ARM.com * | \___ ___/ 1417404SAli.Saidi@ARM.com * | \___ ___/ 1427946SGiacomo.Gabrielli@arm.com * | v 1437404SAli.Saidi@ARM.com * | | 1447404SAli.Saidi@ARM.com * | +--------------------+ 1457436Sdam.sunwoo@arm.com * | | Translation done | 1467436Sdam.sunwoo@arm.com * | +--------------------+ 1477436Sdam.sunwoo@arm.com * | | 1487436Sdam.sunwoo@arm.com * | +--------------------+ 1497436Sdam.sunwoo@arm.com * | | Send packet |<------+ 1507404SAli.Saidi@ARM.com * | +--------------------+ | 1517404SAli.Saidi@ARM.com * | | | 1527946SGiacomo.Gabrielli@arm.com * | ___^___ | 1537404SAli.Saidi@ARM.com * | ___/ \___ | 1547404SAli.Saidi@ARM.com * | ____/ Squashed? \ | 1557436Sdam.sunwoo@arm.com * | | \___ ___/ | 1567436Sdam.sunwoo@arm.com * | | \___ ___/ | 1577436Sdam.sunwoo@arm.com * | | v | 1587436Sdam.sunwoo@arm.com * | | | | 1597436Sdam.sunwoo@arm.com * | | ___^___ | 1607436Sdam.sunwoo@arm.com * | | ___/ \___ | 1617436Sdam.sunwoo@arm.com * | | / Done? \__________| 1627436Sdam.sunwoo@arm.com * | | \___ ___/ 1637436Sdam.sunwoo@arm.com * | | \___ ___/ 1647436Sdam.sunwoo@arm.com * | | v 1657436Sdam.sunwoo@arm.com * | | | 1667436Sdam.sunwoo@arm.com * | | +--------------------+ 1677436Sdam.sunwoo@arm.com * | | | Manage stuff | 1687436Sdam.sunwoo@arm.com * | | | Free resources | 1697436Sdam.sunwoo@arm.com * | | +--------------------+ 1707436Sdam.sunwoo@arm.com * | | 1717436Sdam.sunwoo@arm.com * | | +--------------------+ 1727436Sdam.sunwoo@arm.com * | | | senderState owns | 1737436Sdam.sunwoo@arm.com * | +->| onRecvTimingResp | 1747436Sdam.sunwoo@arm.com * | | free resources | 1757404SAli.Saidi@ARM.com * | +--------------------+ 1767404SAli.Saidi@ARM.com * | 1777404SAli.Saidi@ARM.com * | +----------------------+ 1787404SAli.Saidi@ARM.com * | | self owned (Trans) | 1797404SAli.Saidi@ARM.com * +-->| on TranslationFinish | 1807436Sdam.sunwoo@arm.com * | free resources | 1817404SAli.Saidi@ARM.com * +----------------------+ 1827404SAli.Saidi@ARM.com * 1837436Sdam.sunwoo@arm.com * 1847436Sdam.sunwoo@arm.com */ 1857436Sdam.sunwoo@arm.com class LSQRequest : public BaseTLB::Translation 1867436Sdam.sunwoo@arm.com { 1877404SAli.Saidi@ARM.com protected: 1887404SAli.Saidi@ARM.com typedef uint32_t FlagsStorage; 1897404SAli.Saidi@ARM.com typedef ::Flags<FlagsStorage> FlagsType; 1907946SGiacomo.Gabrielli@arm.com 1917404SAli.Saidi@ARM.com enum Flag : FlagsStorage 1927404SAli.Saidi@ARM.com { 1937404SAli.Saidi@ARM.com IsLoad = 0x00000001, 1947404SAli.Saidi@ARM.com /** True if this is a store/atomic that writes registers (SC). */ 1957404SAli.Saidi@ARM.com WbStore = 0x00000002, 1967404SAli.Saidi@ARM.com Delayed = 0x00000004, 1977404SAli.Saidi@ARM.com IsSplit = 0x00000008, 1987404SAli.Saidi@ARM.com /** True if any translation has been sent to TLB. */ 1997404SAli.Saidi@ARM.com TranslationStarted = 0x00000010, 2007404SAli.Saidi@ARM.com /** True if there are un-replied outbound translations.. */ 2017404SAli.Saidi@ARM.com TranslationFinished = 0x00000020, 2027404SAli.Saidi@ARM.com Sent = 0x00000040, 2037404SAli.Saidi@ARM.com Retry = 0x00000080, 2047404SAli.Saidi@ARM.com Complete = 0x00000100, 2057404SAli.Saidi@ARM.com /** Ownership tracking flags. */ 2067404SAli.Saidi@ARM.com /** Translation squashed. */ 2077404SAli.Saidi@ARM.com TranslationSquashed = 0x00000200, 2087404SAli.Saidi@ARM.com /** Request discarded */ 2097404SAli.Saidi@ARM.com Discarded = 0x00000400, 2107404SAli.Saidi@ARM.com /** LSQ resources freed. */ 2117404SAli.Saidi@ARM.com LSQEntryFreed = 0x00000800, 2127404SAli.Saidi@ARM.com /** Store written back. */ 2137404SAli.Saidi@ARM.com WritebackScheduled = 0x00001000, 2147404SAli.Saidi@ARM.com WritebackDone = 0x00002000, 2157404SAli.Saidi@ARM.com /** True if this is an atomic request */ 2167404SAli.Saidi@ARM.com IsAtomic = 0x00004000 2177404SAli.Saidi@ARM.com }; 2187404SAli.Saidi@ARM.com FlagsType flags; 2197404SAli.Saidi@ARM.com 2207404SAli.Saidi@ARM.com enum class State 2217946SGiacomo.Gabrielli@arm.com { 2227946SGiacomo.Gabrielli@arm.com NotIssued, 2237404SAli.Saidi@ARM.com Translation, 2247404SAli.Saidi@ARM.com Request, 2257404SAli.Saidi@ARM.com Complete, 2267404SAli.Saidi@ARM.com Squashed, 2277404SAli.Saidi@ARM.com Fault, 2287404SAli.Saidi@ARM.com }; 2297404SAli.Saidi@ARM.com State _state; 2307404SAli.Saidi@ARM.com LSQSenderState* _senderState; 2317694SAli.Saidi@ARM.com void setState(const State& newState) { _state = newState; } 2327694SAli.Saidi@ARM.com 2337694SAli.Saidi@ARM.com uint32_t numTranslatedFragments; 2347694SAli.Saidi@ARM.com uint32_t numInTranslationFragments; 2357694SAli.Saidi@ARM.com 2367694SAli.Saidi@ARM.com /** LQ/SQ entry idx. */ 2377694SAli.Saidi@ARM.com uint32_t _entryIdx; 2387694SAli.Saidi@ARM.com 2397694SAli.Saidi@ARM.com void markDelayed() override { flags.set(Flag::Delayed); } 2407436Sdam.sunwoo@arm.com bool isDelayed() { return flags.isSet(Flag::Delayed); } 2417436Sdam.sunwoo@arm.com 2427436Sdam.sunwoo@arm.com public: 2437436Sdam.sunwoo@arm.com LSQUnit& _port; 2447436Sdam.sunwoo@arm.com const DynInstPtr _inst; 2457436Sdam.sunwoo@arm.com uint32_t _taskId; 2467436Sdam.sunwoo@arm.com PacketDataPtr _data; 2477436Sdam.sunwoo@arm.com std::vector<PacketPtr> _packets; 2487436Sdam.sunwoo@arm.com std::vector<RequestPtr> _requests; 2497436Sdam.sunwoo@arm.com std::vector<Fault> _fault; 2507436Sdam.sunwoo@arm.com uint64_t* _res; 2517436Sdam.sunwoo@arm.com const Addr _addr; 2527436Sdam.sunwoo@arm.com const uint32_t _size; 2537436Sdam.sunwoo@arm.com const Request::Flags _flags; 2547436Sdam.sunwoo@arm.com uint32_t _numOutstandingPackets; 2557436Sdam.sunwoo@arm.com AtomicOpFunctor *_amo_op; 2567436Sdam.sunwoo@arm.com protected: 2577436Sdam.sunwoo@arm.com LSQUnit* lsqUnit() { return &_port; } 2587436Sdam.sunwoo@arm.com LSQRequest(LSQUnit* port, const DynInstPtr& inst, bool isLoad) : 2597436Sdam.sunwoo@arm.com _state(State::NotIssued), _senderState(nullptr), 2607436Sdam.sunwoo@arm.com _port(*port), _inst(inst), _data(nullptr), 2617404SAli.Saidi@ARM.com _res(nullptr), _addr(0), _size(0), _flags(0), 2627404SAli.Saidi@ARM.com _numOutstandingPackets(0), _amo_op(nullptr) 2637439Sdam.sunwoo@arm.com { 2647439Sdam.sunwoo@arm.com flags.set(Flag::IsLoad, isLoad); 2657439Sdam.sunwoo@arm.com flags.set(Flag::WbStore, 2667439Sdam.sunwoo@arm.com _inst->isStoreConditional() || _inst->isAtomic()); 2677439Sdam.sunwoo@arm.com flags.set(Flag::IsAtomic, _inst->isAtomic()); 2687439Sdam.sunwoo@arm.com install(); 2697439Sdam.sunwoo@arm.com } 2707439Sdam.sunwoo@arm.com LSQRequest(LSQUnit* port, const DynInstPtr& inst, bool isLoad, 2717439Sdam.sunwoo@arm.com const Addr& addr, const uint32_t& size, 2727439Sdam.sunwoo@arm.com const Request::Flags& flags_, 2737439Sdam.sunwoo@arm.com PacketDataPtr data = nullptr, uint64_t* res = nullptr, 2747439Sdam.sunwoo@arm.com AtomicOpFunctor* amo_op = nullptr) 2757439Sdam.sunwoo@arm.com : _state(State::NotIssued), _senderState(nullptr), 2767439Sdam.sunwoo@arm.com numTranslatedFragments(0), 2777439Sdam.sunwoo@arm.com numInTranslationFragments(0), 2787439Sdam.sunwoo@arm.com _port(*port), _inst(inst), _data(data), 2797439Sdam.sunwoo@arm.com _res(res), _addr(addr), _size(size), 2807439Sdam.sunwoo@arm.com _flags(flags_), 2817439Sdam.sunwoo@arm.com _numOutstandingPackets(0), 2827439Sdam.sunwoo@arm.com _amo_op(amo_op) 2837439Sdam.sunwoo@arm.com { 2847439Sdam.sunwoo@arm.com flags.set(Flag::IsLoad, isLoad); 2857439Sdam.sunwoo@arm.com flags.set(Flag::WbStore, 2867439Sdam.sunwoo@arm.com _inst->isStoreConditional() || _inst->isAtomic()); 2877439Sdam.sunwoo@arm.com flags.set(Flag::IsAtomic, _inst->isAtomic()); 2887439Sdam.sunwoo@arm.com install(); 2897439Sdam.sunwoo@arm.com } 2907439Sdam.sunwoo@arm.com 2917439Sdam.sunwoo@arm.com bool 2927439Sdam.sunwoo@arm.com isLoad() const 2937439Sdam.sunwoo@arm.com { 2947439Sdam.sunwoo@arm.com return flags.isSet(Flag::IsLoad); 2957439Sdam.sunwoo@arm.com } 2967439Sdam.sunwoo@arm.com 2977439Sdam.sunwoo@arm.com bool 2988733Sgeoffrey.blake@arm.com isAtomic() const 2998733Sgeoffrey.blake@arm.com { 3008733Sgeoffrey.blake@arm.com return flags.isSet(Flag::IsAtomic); 3017439Sdam.sunwoo@arm.com } 3027439Sdam.sunwoo@arm.com 3037439Sdam.sunwoo@arm.com /** Install the request in the LQ/SQ. */ 3047439Sdam.sunwoo@arm.com void install() 3057439Sdam.sunwoo@arm.com { 3067439Sdam.sunwoo@arm.com if (isLoad()) { 3077439Sdam.sunwoo@arm.com _port.loadQueue[_inst->lqIdx].setRequest(this); 3087439Sdam.sunwoo@arm.com } else { 3097439Sdam.sunwoo@arm.com // Store, StoreConditional, and Atomic requests are pushed 3107439Sdam.sunwoo@arm.com // to this storeQueue 3117439Sdam.sunwoo@arm.com _port.storeQueue[_inst->sqIdx].setRequest(this); 3127439Sdam.sunwoo@arm.com } 3137439Sdam.sunwoo@arm.com } 3147439Sdam.sunwoo@arm.com virtual bool 3157439Sdam.sunwoo@arm.com squashed() const override 3167439Sdam.sunwoo@arm.com { 3177439Sdam.sunwoo@arm.com return _inst->isSquashed(); 3187439Sdam.sunwoo@arm.com } 3197653Sgene.wu@arm.com 3207653Sgene.wu@arm.com /** 3217653Sgene.wu@arm.com * Test if the LSQRequest has been released, i.e. self-owned. 3227653Sgene.wu@arm.com * An LSQRequest manages itself when the resources on the LSQ are freed 3237653Sgene.wu@arm.com * but the translation is still going on and the LSQEntry was freed. 3247653Sgene.wu@arm.com */ 3257439Sdam.sunwoo@arm.com bool 3267728SAli.Saidi@ARM.com isReleased() 3277728SAli.Saidi@ARM.com { 3288902Sandreas.hansson@arm.com return flags.isSet(Flag::LSQEntryFreed) || 3297728SAli.Saidi@ARM.com flags.isSet(Flag::Discarded); 3307728SAli.Saidi@ARM.com } 3317404SAli.Saidi@ARM.com 3328851Sandreas.hansson@arm.com /** Release the LSQRequest. 3337404SAli.Saidi@ARM.com * Notify the sender state that the request it points to is not valid 3347404SAli.Saidi@ARM.com * anymore. Understand if the request is orphan (self-managed) and if 3357404SAli.Saidi@ARM.com * so, mark it as freed, else destroy it, as this means 3367404SAli.Saidi@ARM.com * the end of its life cycle. 3377404SAli.Saidi@ARM.com * An LSQRequest is orphan when its resources are released 3387404SAli.Saidi@ARM.com * but there is any in-flight translation request to the TLB or access 3397404SAli.Saidi@ARM.com * request to the memory. 3407439Sdam.sunwoo@arm.com */ 3417437Sdam.sunwoo@arm.com void release(Flag reason) 3427728SAli.Saidi@ARM.com { 3437728SAli.Saidi@ARM.com assert(reason == Flag::LSQEntryFreed || reason == Flag::Discarded); 3447728SAli.Saidi@ARM.com if (!isAnyOutstandingRequest()) { 3458832SAli.Saidi@ARM.com delete this; 3468832SAli.Saidi@ARM.com } else { 3478832SAli.Saidi@ARM.com if (_senderState) { 3487404SAli.Saidi@ARM.com _senderState->deleteRequest(); 3497404SAli.Saidi@ARM.com } 3507404SAli.Saidi@ARM.com flags.set(reason); 3517404SAli.Saidi@ARM.com } 3527404SAli.Saidi@ARM.com } 3537404SAli.Saidi@ARM.com 3547404SAli.Saidi@ARM.com /** Destructor. 3557404SAli.Saidi@ARM.com * The LSQRequest owns the request. If the packet has already been 3567404SAli.Saidi@ARM.com * sent, the sender state will be deleted upon receiving the reply. 3577404SAli.Saidi@ARM.com */ 3587404SAli.Saidi@ARM.com virtual ~LSQRequest() 3597733SAli.Saidi@ARM.com { 3607748SAli.Saidi@ARM.com assert(!isAnyOutstandingRequest()); 3617404SAli.Saidi@ARM.com _inst->savedReq = nullptr; 3627404SAli.Saidi@ARM.com if (_senderState) 3637404SAli.Saidi@ARM.com delete _senderState; 3648733Sgeoffrey.blake@arm.com 3657404SAli.Saidi@ARM.com for (auto r: _packets) 3667404SAli.Saidi@ARM.com delete r; 3677439Sdam.sunwoo@arm.com }; 3687439Sdam.sunwoo@arm.com 3697404SAli.Saidi@ARM.com 3707404SAli.Saidi@ARM.com public: 3717404SAli.Saidi@ARM.com /** Convenience getters/setters. */ 3727404SAli.Saidi@ARM.com /** @{ */ 3737437Sdam.sunwoo@arm.com /** Set up Context numbers. */ 3747437Sdam.sunwoo@arm.com void 3757404SAli.Saidi@ARM.com setContext(const ContextID& context_id) 3767404SAli.Saidi@ARM.com { 3777437Sdam.sunwoo@arm.com request()->setContext(context_id); 3787437Sdam.sunwoo@arm.com } 3797404SAli.Saidi@ARM.com 3807728SAli.Saidi@ARM.com const DynInstPtr& 3817728SAli.Saidi@ARM.com instruction() 3827728SAli.Saidi@ARM.com { 3837404SAli.Saidi@ARM.com return _inst; 3847728SAli.Saidi@ARM.com } 3857404SAli.Saidi@ARM.com 3867404SAli.Saidi@ARM.com /** Set up virtual request. 3877404SAli.Saidi@ARM.com * For a previously allocated Request objects. 3887404SAli.Saidi@ARM.com */ 3897404SAli.Saidi@ARM.com void 3907404SAli.Saidi@ARM.com setVirt(int asid, Addr vaddr, unsigned size, Request::Flags flags_, 3917404SAli.Saidi@ARM.com MasterID mid, Addr pc) 392 { 393 request()->setVirt(asid, vaddr, size, flags_, mid, pc); 394 } 395 396 void 397 taskId(const uint32_t& v) 398 { 399 _taskId = v; 400 for (auto& r: _requests) 401 r->taskId(v); 402 } 403 404 uint32_t taskId() const { return _taskId; } 405 RequestPtr request(int idx = 0) { return _requests.at(idx); } 406 407 const RequestPtr 408 request(int idx = 0) const 409 { 410 return _requests.at(idx); 411 } 412 413 Addr getVaddr(int idx = 0) const { return request(idx)->getVaddr(); } 414 virtual void initiateTranslation() = 0; 415 416 PacketPtr packet(int idx = 0) { return _packets.at(idx); } 417 418 virtual PacketPtr 419 mainPacket() 420 { 421 assert (_packets.size() == 1); 422 return packet(); 423 } 424 425 virtual RequestPtr 426 mainRequest() 427 { 428 assert (_requests.size() == 1); 429 return request(); 430 } 431 432 void 433 senderState(LSQSenderState* st) 434 { 435 _senderState = st; 436 for (auto& pkt: _packets) { 437 if (pkt) 438 pkt->senderState = st; 439 } 440 } 441 442 const LSQSenderState* 443 senderState() const 444 { 445 return _senderState; 446 } 447 448 /** 449 * Mark senderState as discarded. This will cause to discard response 450 * packets from the cache. 451 */ 452 void 453 discardSenderState() 454 { 455 assert(_senderState); 456 _senderState->deleteRequest(); 457 } 458 459 /** 460 * Test if there is any in-flight translation or mem access request 461 */ 462 bool 463 isAnyOutstandingRequest() 464 { 465 return numInTranslationFragments > 0 || 466 _numOutstandingPackets > 0 || 467 (flags.isSet(Flag::WritebackScheduled) && 468 !flags.isSet(Flag::WritebackDone)); 469 } 470 471 bool 472 isSplit() const 473 { 474 return flags.isSet(Flag::IsSplit); 475 } 476 /** @} */ 477 virtual bool recvTimingResp(PacketPtr pkt) = 0; 478 virtual void sendPacketToCache() = 0; 479 virtual void buildPackets() = 0; 480 481 /** 482 * Memory mapped IPR accesses 483 */ 484 virtual void handleIprWrite(ThreadContext *thread, PacketPtr pkt) = 0; 485 virtual Cycles handleIprRead(ThreadContext *thread, PacketPtr pkt) = 0; 486 487 /** 488 * Test if the request accesses a particular cache line. 489 */ 490 virtual bool isCacheBlockHit(Addr blockAddr, Addr cacheBlockMask) = 0; 491 492 /** Update the status to reflect that a packet was sent. */ 493 void 494 packetSent() 495 { 496 flags.set(Flag::Sent); 497 } 498 /** Update the status to reflect that a packet was not sent. 499 * When a packet fails to be sent, we mark the request as needing a 500 * retry. Note that Retry flag is sticky. 501 */ 502 void 503 packetNotSent() 504 { 505 flags.set(Flag::Retry); 506 flags.clear(Flag::Sent); 507 } 508 509 void sendFragmentToTranslation(int i); 510 bool 511 isComplete() 512 { 513 return flags.isSet(Flag::Complete); 514 } 515 516 bool 517 isInTranslation() 518 { 519 return _state == State::Translation; 520 } 521 522 bool 523 isTranslationComplete() 524 { 525 return flags.isSet(Flag::TranslationStarted) && 526 !isInTranslation(); 527 } 528 529 bool 530 isTranslationBlocked() 531 { 532 return _state == State::Translation && 533 flags.isSet(Flag::TranslationStarted) && 534 !flags.isSet(Flag::TranslationFinished); 535 } 536 537 bool 538 isSent() 539 { 540 return flags.isSet(Flag::Sent); 541 } 542 543 /** 544 * The LSQ entry is cleared 545 */ 546 void 547 freeLSQEntry() 548 { 549 release(Flag::LSQEntryFreed); 550 } 551 552 /** 553 * The request is discarded (e.g. partial store-load forwarding) 554 */ 555 void 556 discard() 557 { 558 release(Flag::Discarded); 559 } 560 561 void 562 packetReplied() 563 { 564 assert(_numOutstandingPackets > 0); 565 _numOutstandingPackets--; 566 if (_numOutstandingPackets == 0 && isReleased()) 567 delete this; 568 } 569 570 void 571 writebackScheduled() 572 { 573 assert(!flags.isSet(Flag::WritebackScheduled)); 574 flags.set(Flag::WritebackScheduled); 575 } 576 577 void 578 writebackDone() 579 { 580 flags.set(Flag::WritebackDone); 581 /* If the lsq resources are already free */ 582 if (isReleased()) { 583 delete this; 584 } 585 } 586 587 void 588 squashTranslation() 589 { 590 assert(numInTranslationFragments == 0); 591 flags.set(Flag::TranslationSquashed); 592 /* If we are on our own, self-destruct. */ 593 if (isReleased()) { 594 delete this; 595 } 596 } 597 598 void 599 complete() 600 { 601 flags.set(Flag::Complete); 602 } 603 }; 604 605 class SingleDataRequest : public LSQRequest 606 { 607 protected: 608 /* Given that we are inside templates, children need explicit 609 * declaration of the names in the parent class. */ 610 using Flag = typename LSQRequest::Flag; 611 using State = typename LSQRequest::State; 612 using LSQRequest::_fault; 613 using LSQRequest::_inst; 614 using LSQRequest::_packets; 615 using LSQRequest::_port; 616 using LSQRequest::_res; 617 using LSQRequest::_senderState; 618 using LSQRequest::_state; 619 using LSQRequest::flags; 620 using LSQRequest::isLoad; 621 using LSQRequest::isTranslationComplete; 622 using LSQRequest::lsqUnit; 623 using LSQRequest::request; 624 using LSQRequest::sendFragmentToTranslation; 625 using LSQRequest::setState; 626 using LSQRequest::numInTranslationFragments; 627 using LSQRequest::numTranslatedFragments; 628 using LSQRequest::_numOutstandingPackets; 629 using LSQRequest::_amo_op; 630 public: 631 SingleDataRequest(LSQUnit* port, const DynInstPtr& inst, bool isLoad, 632 const Addr& addr, const uint32_t& size, 633 const Request::Flags& flags_, 634 PacketDataPtr data = nullptr, 635 uint64_t* res = nullptr, 636 AtomicOpFunctor* amo_op = nullptr) : 637 LSQRequest(port, inst, isLoad, addr, size, flags_, data, res, 638 amo_op) 639 { 640 LSQRequest::_requests.push_back( 641 std::make_shared<Request>(inst->getASID(), addr, size, 642 flags_, inst->masterId(), inst->instAddr(), 643 inst->contextId(), amo_op)); 644 LSQRequest::_requests.back()->setReqInstSeqNum(inst->seqNum); 645 } 646 inline virtual ~SingleDataRequest() {} 647 virtual void initiateTranslation(); 648 virtual void finish(const Fault &fault, const RequestPtr &req, 649 ThreadContext* tc, BaseTLB::Mode mode); 650 virtual bool recvTimingResp(PacketPtr pkt); 651 virtual void sendPacketToCache(); 652 virtual void buildPackets(); 653 virtual void handleIprWrite(ThreadContext *thread, PacketPtr pkt); 654 virtual Cycles handleIprRead(ThreadContext *thread, PacketPtr pkt); 655 virtual bool isCacheBlockHit(Addr blockAddr, Addr cacheBlockMask); 656 }; 657 658 class SplitDataRequest : public LSQRequest 659 { 660 protected: 661 /* Given that we are inside templates, children need explicit 662 * declaration of the names in the parent class. */ 663 using Flag = typename LSQRequest::Flag; 664 using State = typename LSQRequest::State; 665 using LSQRequest::_addr; 666 using LSQRequest::_data; 667 using LSQRequest::_fault; 668 using LSQRequest::_flags; 669 using LSQRequest::_inst; 670 using LSQRequest::_packets; 671 using LSQRequest::_port; 672 using LSQRequest::_requests; 673 using LSQRequest::_res; 674 using LSQRequest::_senderState; 675 using LSQRequest::_size; 676 using LSQRequest::_state; 677 using LSQRequest::_taskId; 678 using LSQRequest::flags; 679 using LSQRequest::isLoad; 680 using LSQRequest::isTranslationComplete; 681 using LSQRequest::lsqUnit; 682 using LSQRequest::numInTranslationFragments; 683 using LSQRequest::numTranslatedFragments; 684 using LSQRequest::request; 685 using LSQRequest::sendFragmentToTranslation; 686 using LSQRequest::setState; 687 using LSQRequest::_numOutstandingPackets; 688 689 uint32_t numFragments; 690 uint32_t numReceivedPackets; 691 RequestPtr mainReq; 692 PacketPtr _mainPacket; 693 694 695 public: 696 SplitDataRequest(LSQUnit* port, const DynInstPtr& inst, bool isLoad, 697 const Addr& addr, const uint32_t& size, 698 const Request::Flags & flags_, 699 PacketDataPtr data = nullptr, 700 uint64_t* res = nullptr) : 701 LSQRequest(port, inst, isLoad, addr, size, flags_, data, res), 702 numFragments(0), 703 numReceivedPackets(0), 704 mainReq(nullptr), 705 _mainPacket(nullptr) 706 { 707 flags.set(Flag::IsSplit); 708 } 709 virtual ~SplitDataRequest() 710 { 711 if (mainReq) { 712 mainReq = nullptr; 713 } 714 if (_mainPacket) { 715 delete _mainPacket; 716 _mainPacket = nullptr; 717 } 718 } 719 virtual void finish(const Fault &fault, const RequestPtr &req, 720 ThreadContext* tc, BaseTLB::Mode mode); 721 virtual bool recvTimingResp(PacketPtr pkt); 722 virtual void initiateTranslation(); 723 virtual void sendPacketToCache(); 724 virtual void buildPackets(); 725 726 virtual void handleIprWrite(ThreadContext *thread, PacketPtr pkt); 727 virtual Cycles handleIprRead(ThreadContext *thread, PacketPtr pkt); 728 virtual bool isCacheBlockHit(Addr blockAddr, Addr cacheBlockMask); 729 730 virtual RequestPtr mainRequest(); 731 virtual PacketPtr mainPacket(); 732 }; 733 734 /** Constructs an LSQ with the given parameters. */ 735 LSQ(O3CPU *cpu_ptr, IEW *iew_ptr, DerivO3CPUParams *params); 736 ~LSQ() { } 737 738 /** Returns the name of the LSQ. */ 739 std::string name() const; 740 741 /** Registers statistics of each LSQ unit. */ 742 void regStats(); 743 744 /** Sets the pointer to the list of active threads. */ 745 void setActiveThreads(std::list<ThreadID> *at_ptr); 746 747 /** Perform sanity checks after a drain. */ 748 void drainSanityCheck() const; 749 /** Has the LSQ drained? */ 750 bool isDrained() const; 751 /** Takes over execution from another CPU's thread. */ 752 void takeOverFrom(); 753 754 /** Number of entries needed for the given amount of threads.*/ 755 int entryAmount(ThreadID num_threads); 756 757 /** Ticks the LSQ. */ 758 void tick(); 759 760 /** Inserts a load into the LSQ. */ 761 void insertLoad(const DynInstPtr &load_inst); 762 /** Inserts a store into the LSQ. */ 763 void insertStore(const DynInstPtr &store_inst); 764 765 /** Executes a load. */ 766 Fault executeLoad(const DynInstPtr &inst); 767 768 /** Executes a store. */ 769 Fault executeStore(const DynInstPtr &inst); 770 771 /** 772 * Commits loads up until the given sequence number for a specific thread. 773 */ 774 void commitLoads(InstSeqNum &youngest_inst, ThreadID tid) 775 { thread.at(tid).commitLoads(youngest_inst); } 776 777 /** 778 * Commits stores up until the given sequence number for a specific thread. 779 */ 780 void commitStores(InstSeqNum &youngest_inst, ThreadID tid) 781 { thread.at(tid).commitStores(youngest_inst); } 782 783 /** 784 * Attempts to write back stores until all cache ports are used or the 785 * interface becomes blocked. 786 */ 787 void writebackStores(); 788 /** Same as above, but only for one thread. */ 789 void writebackStores(ThreadID tid); 790 791 /** 792 * Squash instructions from a thread until the specified sequence number. 793 */ 794 void 795 squash(const InstSeqNum &squashed_num, ThreadID tid) 796 { 797 thread.at(tid).squash(squashed_num); 798 } 799 800 /** Returns whether or not there was a memory ordering violation. */ 801 bool violation(); 802 /** 803 * Returns whether or not there was a memory ordering violation for a 804 * specific thread. 805 */ 806 bool violation(ThreadID tid) { return thread.at(tid).violation(); } 807 808 /** Gets the instruction that caused the memory ordering violation. */ 809 DynInstPtr 810 getMemDepViolator(ThreadID tid) 811 { 812 return thread.at(tid).getMemDepViolator(); 813 } 814 815 /** Returns the head index of the load queue for a specific thread. */ 816 int getLoadHead(ThreadID tid) { return thread.at(tid).getLoadHead(); } 817 818 /** Returns the sequence number of the head of the load queue. */ 819 InstSeqNum 820 getLoadHeadSeqNum(ThreadID tid) 821 { 822 return thread.at(tid).getLoadHeadSeqNum(); 823 } 824 825 /** Returns the head index of the store queue. */ 826 int getStoreHead(ThreadID tid) { return thread.at(tid).getStoreHead(); } 827 828 /** Returns the sequence number of the head of the store queue. */ 829 InstSeqNum 830 getStoreHeadSeqNum(ThreadID tid) 831 { 832 return thread.at(tid).getStoreHeadSeqNum(); 833 } 834 835 /** Returns the number of instructions in all of the queues. */ 836 int getCount(); 837 /** Returns the number of instructions in the queues of one thread. */ 838 int getCount(ThreadID tid) { return thread.at(tid).getCount(); } 839 840 /** Returns the total number of loads in the load queue. */ 841 int numLoads(); 842 /** Returns the total number of loads for a single thread. */ 843 int numLoads(ThreadID tid) { return thread.at(tid).numLoads(); } 844 845 /** Returns the total number of stores in the store queue. */ 846 int numStores(); 847 /** Returns the total number of stores for a single thread. */ 848 int numStores(ThreadID tid) { return thread.at(tid).numStores(); } 849 850 /** Returns the number of free load entries. */ 851 unsigned numFreeLoadEntries(); 852 853 /** Returns the number of free store entries. */ 854 unsigned numFreeStoreEntries(); 855 856 /** Returns the number of free entries for a specific thread. */ 857 unsigned numFreeEntries(ThreadID tid); 858 859 /** Returns the number of free entries in the LQ for a specific thread. */ 860 unsigned numFreeLoadEntries(ThreadID tid); 861 862 /** Returns the number of free entries in the SQ for a specific thread. */ 863 unsigned numFreeStoreEntries(ThreadID tid); 864 865 /** Returns if the LSQ is full (either LQ or SQ is full). */ 866 bool isFull(); 867 /** 868 * Returns if the LSQ is full for a specific thread (either LQ or SQ is 869 * full). 870 */ 871 bool isFull(ThreadID tid); 872 873 /** Returns if the LSQ is empty (both LQ and SQ are empty). */ 874 bool isEmpty() const; 875 /** Returns if all of the LQs are empty. */ 876 bool lqEmpty() const; 877 /** Returns if all of the SQs are empty. */ 878 bool sqEmpty() const; 879 880 /** Returns if any of the LQs are full. */ 881 bool lqFull(); 882 /** Returns if the LQ of a given thread is full. */ 883 bool lqFull(ThreadID tid); 884 885 /** Returns if any of the SQs are full. */ 886 bool sqFull(); 887 /** Returns if the SQ of a given thread is full. */ 888 bool sqFull(ThreadID tid); 889 890 /** 891 * Returns if the LSQ is stalled due to a memory operation that must be 892 * replayed. 893 */ 894 bool isStalled(); 895 /** 896 * Returns if the LSQ of a specific thread is stalled due to a memory 897 * operation that must be replayed. 898 */ 899 bool isStalled(ThreadID tid); 900 901 /** Returns whether or not there are any stores to write back to memory. */ 902 bool hasStoresToWB(); 903 904 /** Returns whether or not a specific thread has any stores to write back 905 * to memory. 906 */ 907 bool hasStoresToWB(ThreadID tid) { return thread.at(tid).hasStoresToWB(); } 908 909 /** Returns the number of stores a specific thread has to write back. */ 910 int numStoresToWB(ThreadID tid) { return thread.at(tid).numStoresToWB(); } 911 912 /** Returns if the LSQ will write back to memory this cycle. */ 913 bool willWB(); 914 /** Returns if the LSQ of a specific thread will write back to memory this 915 * cycle. 916 */ 917 bool willWB(ThreadID tid) { return thread.at(tid).willWB(); } 918 919 /** Debugging function to print out all instructions. */ 920 void dumpInsts() const; 921 /** Debugging function to print out instructions from a specific thread. */ 922 void dumpInsts(ThreadID tid) const { thread.at(tid).dumpInsts(); } 923 924 /** Executes a read operation, using the load specified at the load 925 * index. 926 */ 927 Fault read(LSQRequest* req, int load_idx); 928 929 /** Executes a store operation, using the store specified at the store 930 * index. 931 */ 932 Fault write(LSQRequest* req, uint8_t *data, int store_idx); 933 934 /** 935 * Retry the previous send that failed. 936 */ 937 void recvReqRetry(); 938 939 void completeDataAccess(PacketPtr pkt); 940 /** 941 * Handles writing back and completing the load or store that has 942 * returned from memory. 943 * 944 * @param pkt Response packet from the memory sub-system 945 */ 946 bool recvTimingResp(PacketPtr pkt); 947 948 void recvTimingSnoopReq(PacketPtr pkt); 949 950 Fault pushRequest(const DynInstPtr& inst, bool isLoad, uint8_t *data, 951 unsigned int size, Addr addr, Request::Flags flags, 952 uint64_t *res, AtomicOpFunctor *amo_op); 953 954 /** The CPU pointer. */ 955 O3CPU *cpu; 956 957 /** The IEW stage pointer. */ 958 IEW *iewStage; 959 960 /** Is D-cache blocked? */ 961 bool cacheBlocked() const; 962 /** Set D-cache blocked status */ 963 void cacheBlocked(bool v); 964 /** Is any store port available to use? */ 965 bool cachePortAvailable(bool is_load) const; 966 /** Another store port is in use */ 967 void cachePortBusy(bool is_load); 968 969 protected: 970 /** D-cache is blocked */ 971 bool _cacheBlocked; 972 /** The number of cache ports available each cycle (stores only). */ 973 int cacheStorePorts; 974 /** The number of used cache ports in this cycle by stores. */ 975 int usedStorePorts; 976 /** The number of cache ports available each cycle (loads only). */ 977 int cacheLoadPorts; 978 /** The number of used cache ports in this cycle by loads. */ 979 int usedLoadPorts; 980 981 982 /** The LSQ policy for SMT mode. */ 983 SMTQueuePolicy lsqPolicy; 984 985 /** Auxiliary function to calculate per-thread max LSQ allocation limit. 986 * Depending on a policy, number of entries and possibly number of threads 987 * and threshold, this function calculates how many resources each thread 988 * can occupy at most. 989 */ 990 static uint32_t 991 maxLSQAllocation(SMTQueuePolicy pol, uint32_t entries, 992 uint32_t numThreads, uint32_t SMTThreshold) 993 { 994 if (pol == SMTQueuePolicy::Dynamic) { 995 return entries; 996 } else if (pol == SMTQueuePolicy::Partitioned) { 997 //@todo:make work if part_amt doesnt divide evenly. 998 return entries / numThreads; 999 } else if (pol == SMTQueuePolicy::Threshold) { 1000 //Divide up by threshold amount 1001 //@todo: Should threads check the max and the total 1002 //amount of the LSQ 1003 return SMTThreshold; 1004 } 1005 return 0; 1006 } 1007 1008 /** List of Active Threads in System. */ 1009 std::list<ThreadID> *activeThreads; 1010 1011 /** Total Size of LQ Entries. */ 1012 unsigned LQEntries; 1013 /** Total Size of SQ Entries. */ 1014 unsigned SQEntries; 1015 1016 /** Max LQ Size - Used to Enforce Sharing Policies. */ 1017 unsigned maxLQEntries; 1018 1019 /** Max SQ Size - Used to Enforce Sharing Policies. */ 1020 unsigned maxSQEntries; 1021 1022 /** The LSQ units for individual threads. */ 1023 std::vector<LSQUnit> thread; 1024 1025 /** Number of Threads. */ 1026 ThreadID numThreads; 1027}; 1028 1029template <class Impl> 1030Fault 1031LSQ<Impl>::read(LSQRequest* req, int load_idx) 1032{ 1033 ThreadID tid = cpu->contextToThread(req->request()->contextId()); 1034 1035 return thread.at(tid).read(req, load_idx); 1036} 1037 1038template <class Impl> 1039Fault 1040LSQ<Impl>::write(LSQRequest* req, uint8_t *data, int store_idx) 1041{ 1042 ThreadID tid = cpu->contextToThread(req->request()->contextId()); 1043 1044 return thread.at(tid).write(req, data, store_idx); 1045} 1046 1047#endif // __CPU_O3_LSQ_HH__ 1048