lsq_unit_impl.hh revision 2669:f2b336e89d2a
111308Santhony.gutierrez@amd.com/* 211308Santhony.gutierrez@amd.com * Copyright (c) 2004-2005 The Regents of The University of Michigan 311308Santhony.gutierrez@amd.com * All rights reserved. 411308Santhony.gutierrez@amd.com * 511308Santhony.gutierrez@amd.com * Redistribution and use in source and binary forms, with or without 611308Santhony.gutierrez@amd.com * modification, are permitted provided that the following conditions are 711308Santhony.gutierrez@amd.com * met: redistributions of source code must retain the above copyright 811308Santhony.gutierrez@amd.com * notice, this list of conditions and the following disclaimer; 911308Santhony.gutierrez@amd.com * redistributions in binary form must reproduce the above copyright 1011308Santhony.gutierrez@amd.com * notice, this list of conditions and the following disclaimer in the 1111308Santhony.gutierrez@amd.com * documentation and/or other materials provided with the distribution; 1211308Santhony.gutierrez@amd.com * neither the name of the copyright holders nor the names of its 1311308Santhony.gutierrez@amd.com * contributors may be used to endorse or promote products derived from 1411308Santhony.gutierrez@amd.com * this software without specific prior written permission. 1511308Santhony.gutierrez@amd.com * 1611308Santhony.gutierrez@amd.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 1712697Santhony.gutierrez@amd.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 1812697Santhony.gutierrez@amd.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 1912697Santhony.gutierrez@amd.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 2011308Santhony.gutierrez@amd.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 2111308Santhony.gutierrez@amd.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 2211308Santhony.gutierrez@amd.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2311308Santhony.gutierrez@amd.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2411308Santhony.gutierrez@amd.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2511308Santhony.gutierrez@amd.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 2611308Santhony.gutierrez@amd.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2711308Santhony.gutierrez@amd.com */ 2811308Santhony.gutierrez@amd.com 2911308Santhony.gutierrez@amd.com#include "cpu/checker/cpu.hh" 3011308Santhony.gutierrez@amd.com#include "cpu/o3/lsq_unit.hh" 3111308Santhony.gutierrez@amd.com#include "base/str.hh" 3211308Santhony.gutierrez@amd.com#include "mem/request.hh" 3312697Santhony.gutierrez@amd.com 3411308Santhony.gutierrez@amd.comtemplate<class Impl> 3511308Santhony.gutierrez@amd.comvoid 3611308Santhony.gutierrez@amd.comLSQUnit<Impl>::completeDataAccess(PacketPtr pkt) 3711308Santhony.gutierrez@amd.com{ 3811308Santhony.gutierrez@amd.com/* 3911308Santhony.gutierrez@amd.com DPRINTF(IEW, "Load writeback event [sn:%lli]\n", inst->seqNum); 4011308Santhony.gutierrez@amd.com DPRINTF(Activity, "Activity: Ld Writeback event [sn:%lli]\n", inst->seqNum); 4111308Santhony.gutierrez@amd.com 4211308Santhony.gutierrez@amd.com //iewStage->ldstQueue.removeMSHR(inst->threadNumber,inst->seqNum); 4311308Santhony.gutierrez@amd.com 4411308Santhony.gutierrez@amd.com if (iewStage->isSwitchedOut()) { 4511308Santhony.gutierrez@amd.com inst = NULL; 4611308Santhony.gutierrez@amd.com return; 4711308Santhony.gutierrez@amd.com } else if (inst->isSquashed()) { 4811308Santhony.gutierrez@amd.com iewStage->wakeCPU(); 4911308Santhony.gutierrez@amd.com inst = NULL; 5012334Sgabeblack@google.com return; 5111308Santhony.gutierrez@amd.com } 5211308Santhony.gutierrez@amd.com 5311308Santhony.gutierrez@amd.com iewStage->wakeCPU(); 5411308Santhony.gutierrez@amd.com 5511308Santhony.gutierrez@amd.com if (!inst->isExecuted()) { 5611308Santhony.gutierrez@amd.com inst->setExecuted(); 5711308Santhony.gutierrez@amd.com 5811308Santhony.gutierrez@amd.com // Complete access to copy data to proper place. 5911308Santhony.gutierrez@amd.com inst->completeAcc(); 6011308Santhony.gutierrez@amd.com } 6111308Santhony.gutierrez@amd.com 6211308Santhony.gutierrez@amd.com // Need to insert instruction into queue to commit 6311308Santhony.gutierrez@amd.com iewStage->instToCommit(inst); 6411308Santhony.gutierrez@amd.com 6511308Santhony.gutierrez@amd.com iewStage->activityThisCycle(); 6611308Santhony.gutierrez@amd.com 6711308Santhony.gutierrez@amd.com inst = NULL; 6811308Santhony.gutierrez@amd.com*/ 6911308Santhony.gutierrez@amd.com} 7012717Sbrandon.potter@amd.com 7111308Santhony.gutierrez@amd.comtemplate<class Impl> 7211308Santhony.gutierrez@amd.comvoid 7311308Santhony.gutierrez@amd.comLSQUnit<Impl>::completeStoreDataAccess(DynInstPtr &inst) 7411308Santhony.gutierrez@amd.com{ 7511308Santhony.gutierrez@amd.com/* 7611308Santhony.gutierrez@amd.com DPRINTF(LSQ, "Cache miss complete for store idx:%i\n", storeIdx); 7711308Santhony.gutierrez@amd.com DPRINTF(Activity, "Activity: st writeback event idx:%i\n", storeIdx); 7811308Santhony.gutierrez@amd.com 7911308Santhony.gutierrez@amd.com //lsqPtr->removeMSHR(lsqPtr->storeQueue[storeIdx].inst->seqNum); 8011308Santhony.gutierrez@amd.com 8111308Santhony.gutierrez@amd.com if (lsqPtr->isSwitchedOut()) 8211308Santhony.gutierrez@amd.com return; 8311308Santhony.gutierrez@amd.com 8411308Santhony.gutierrez@amd.com lsqPtr->cpu->wakeCPU(); 8511308Santhony.gutierrez@amd.com 8611308Santhony.gutierrez@amd.com if (wb) 8711308Santhony.gutierrez@amd.com lsqPtr->completeDataAccess(storeIdx); 8811308Santhony.gutierrez@amd.com lsqPtr->completeStore(storeIdx); 8911308Santhony.gutierrez@amd.com*/ 9011308Santhony.gutierrez@amd.com} 9111308Santhony.gutierrez@amd.com 9211308Santhony.gutierrez@amd.comtemplate <class Impl> 9311308Santhony.gutierrez@amd.comTick 9411308Santhony.gutierrez@amd.comLSQUnit<Impl>::DcachePort::recvAtomic(PacketPtr pkt) 9511308Santhony.gutierrez@amd.com{ 9611308Santhony.gutierrez@amd.com panic("O3CPU model does not work with atomic mode!"); 9711308Santhony.gutierrez@amd.com return curTick; 9811308Santhony.gutierrez@amd.com} 9911308Santhony.gutierrez@amd.com 10011308Santhony.gutierrez@amd.comtemplate <class Impl> 10111308Santhony.gutierrez@amd.comvoid 10211308Santhony.gutierrez@amd.comLSQUnit<Impl>::DcachePort::recvFunctional(PacketPtr pkt) 10311308Santhony.gutierrez@amd.com{ 10411308Santhony.gutierrez@amd.com panic("O3CPU doesn't expect recvFunctional callback!"); 10511308Santhony.gutierrez@amd.com} 10611308Santhony.gutierrez@amd.com 10711308Santhony.gutierrez@amd.comtemplate <class Impl> 10811308Santhony.gutierrez@amd.comvoid 10911308Santhony.gutierrez@amd.comLSQUnit<Impl>::DcachePort::recvStatusChange(Status status) 11011308Santhony.gutierrez@amd.com{ 11111308Santhony.gutierrez@amd.com if (status == RangeChange) 11211308Santhony.gutierrez@amd.com return; 11311308Santhony.gutierrez@amd.com 11411308Santhony.gutierrez@amd.com panic("O3CPU doesn't expect recvStatusChange callback!"); 11511308Santhony.gutierrez@amd.com} 11612749Sgiacomo.travaglini@arm.com 11712749Sgiacomo.travaglini@arm.comtemplate <class Impl> 11811308Santhony.gutierrez@amd.combool 11911308Santhony.gutierrez@amd.comLSQUnit<Impl>::DcachePort::recvTiming(PacketPtr pkt) 12011308Santhony.gutierrez@amd.com{ 12112717Sbrandon.potter@amd.com lsq->completeDataAccess(pkt); 12211308Santhony.gutierrez@amd.com return true; 12311308Santhony.gutierrez@amd.com} 12411308Santhony.gutierrez@amd.com 12511308Santhony.gutierrez@amd.comtemplate <class Impl> 12611308Santhony.gutierrez@amd.comvoid 12711308Santhony.gutierrez@amd.comLSQUnit<Impl>::DcachePort::recvRetry() 12811308Santhony.gutierrez@amd.com{ 12911308Santhony.gutierrez@amd.com panic("Retry unsupported for now!"); 13011308Santhony.gutierrez@amd.com // we shouldn't get a retry unless we have a packet that we're 13111308Santhony.gutierrez@amd.com // waiting to transmit 13211308Santhony.gutierrez@amd.com/* 13311308Santhony.gutierrez@amd.com assert(cpu->dcache_pkt != NULL); 13411308Santhony.gutierrez@amd.com assert(cpu->_status == DcacheRetry); 13511308Santhony.gutierrez@amd.com PacketPtr tmp = cpu->dcache_pkt; 13611308Santhony.gutierrez@amd.com if (sendTiming(tmp)) { 13711308Santhony.gutierrez@amd.com cpu->_status = DcacheWaitResponse; 13811308Santhony.gutierrez@amd.com cpu->dcache_pkt = NULL; 13911308Santhony.gutierrez@amd.com } 14011308Santhony.gutierrez@amd.com*/ 14111308Santhony.gutierrez@amd.com} 14211308Santhony.gutierrez@amd.com 14311308Santhony.gutierrez@amd.comtemplate <class Impl> 14411308Santhony.gutierrez@amd.comLSQUnit<Impl>::LSQUnit() 14511308Santhony.gutierrez@amd.com : loads(0), stores(0), storesToWB(0), stalled(false), isLoadBlocked(false), 14611308Santhony.gutierrez@amd.com loadBlockedHandled(false) 14711308Santhony.gutierrez@amd.com{ 14811308Santhony.gutierrez@amd.com} 14911308Santhony.gutierrez@amd.com 15011308Santhony.gutierrez@amd.comtemplate<class Impl> 15111308Santhony.gutierrez@amd.comvoid 15211308Santhony.gutierrez@amd.comLSQUnit<Impl>::init(Params *params, unsigned maxLQEntries, 15311308Santhony.gutierrez@amd.com unsigned maxSQEntries, unsigned id) 15411308Santhony.gutierrez@amd.com{ 15511308Santhony.gutierrez@amd.com DPRINTF(LSQUnit, "Creating LSQUnit%i object.\n",id); 15611308Santhony.gutierrez@amd.com 15711308Santhony.gutierrez@amd.com switchedOut = false; 15811308Santhony.gutierrez@amd.com 15911308Santhony.gutierrez@amd.com lsqID = id; 16011308Santhony.gutierrez@amd.com 16111308Santhony.gutierrez@amd.com // Add 1 for the sentinel entry (they are circular queues). 16212717Sbrandon.potter@amd.com LQEntries = maxLQEntries + 1; 16311308Santhony.gutierrez@amd.com SQEntries = maxSQEntries + 1; 16411308Santhony.gutierrez@amd.com 16511308Santhony.gutierrez@amd.com loadQueue.resize(LQEntries); 16611308Santhony.gutierrez@amd.com storeQueue.resize(SQEntries); 16711308Santhony.gutierrez@amd.com 16811308Santhony.gutierrez@amd.com loadHead = loadTail = 0; 16911308Santhony.gutierrez@amd.com 17011308Santhony.gutierrez@amd.com storeHead = storeWBIdx = storeTail = 0; 17111308Santhony.gutierrez@amd.com 17211308Santhony.gutierrez@amd.com usedPorts = 0; 17311308Santhony.gutierrez@amd.com cachePorts = params->cachePorts; 17411308Santhony.gutierrez@amd.com 17511308Santhony.gutierrez@amd.com Port *mem_dport = params->mem->getPort(""); 17611308Santhony.gutierrez@amd.com dcachePort->setPeer(mem_dport); 17711308Santhony.gutierrez@amd.com mem_dport->setPeer(dcachePort); 17811308Santhony.gutierrez@amd.com 17911308Santhony.gutierrez@amd.com memDepViolator = NULL; 18012749Sgiacomo.travaglini@arm.com 18111308Santhony.gutierrez@amd.com blockedLoadSeqNum = 0; 18212749Sgiacomo.travaglini@arm.com} 18311308Santhony.gutierrez@amd.com 18411308Santhony.gutierrez@amd.comtemplate<class Impl> 18511308Santhony.gutierrez@amd.comvoid 18611308Santhony.gutierrez@amd.comLSQUnit<Impl>::setCPU(FullCPU *cpu_ptr) 18711308Santhony.gutierrez@amd.com{ 18811308Santhony.gutierrez@amd.com cpu = cpu_ptr; 18911308Santhony.gutierrez@amd.com dcachePort = new DcachePort(cpu, this); 19011308Santhony.gutierrez@amd.com} 19111308Santhony.gutierrez@amd.com 19211308Santhony.gutierrez@amd.comtemplate<class Impl> 19311308Santhony.gutierrez@amd.comstd::string 19411308Santhony.gutierrez@amd.comLSQUnit<Impl>::name() const 19511308Santhony.gutierrez@amd.com{ 19611308Santhony.gutierrez@amd.com if (Impl::MaxThreads == 1) { 19711308Santhony.gutierrez@amd.com return iewStage->name() + ".lsq"; 19811308Santhony.gutierrez@amd.com } else { 19911308Santhony.gutierrez@amd.com return iewStage->name() + ".lsq.thread." + to_string(lsqID); 20011308Santhony.gutierrez@amd.com } 20111308Santhony.gutierrez@amd.com} 20211308Santhony.gutierrez@amd.com 20311308Santhony.gutierrez@amd.comtemplate<class Impl> 20411308Santhony.gutierrez@amd.comvoid 20511308Santhony.gutierrez@amd.comLSQUnit<Impl>::clearLQ() 20611308Santhony.gutierrez@amd.com{ 20711308Santhony.gutierrez@amd.com loadQueue.clear(); 20811308Santhony.gutierrez@amd.com} 20911308Santhony.gutierrez@amd.com 21011308Santhony.gutierrez@amd.comtemplate<class Impl> 21111308Santhony.gutierrez@amd.comvoid 21211308Santhony.gutierrez@amd.comLSQUnit<Impl>::clearSQ() 21311308Santhony.gutierrez@amd.com{ 21411308Santhony.gutierrez@amd.com storeQueue.clear(); 21511308Santhony.gutierrez@amd.com} 21611308Santhony.gutierrez@amd.com 21711308Santhony.gutierrez@amd.com#if 0 21811308Santhony.gutierrez@amd.comtemplate<class Impl> 21911308Santhony.gutierrez@amd.comvoid 22011308Santhony.gutierrez@amd.comLSQUnit<Impl>::setPageTable(PageTable *pt_ptr) 22111308Santhony.gutierrez@amd.com{ 22211308Santhony.gutierrez@amd.com DPRINTF(LSQUnit, "Setting the page table pointer.\n"); 22311308Santhony.gutierrez@amd.com pTable = pt_ptr; 22411308Santhony.gutierrez@amd.com} 22512749Sgiacomo.travaglini@arm.com#endif 22612749Sgiacomo.travaglini@arm.com 22711308Santhony.gutierrez@amd.comtemplate<class Impl> 22812749Sgiacomo.travaglini@arm.comvoid 22911308Santhony.gutierrez@amd.comLSQUnit<Impl>::switchOut() 23011308Santhony.gutierrez@amd.com{ 23111308Santhony.gutierrez@amd.com switchedOut = true; 23211308Santhony.gutierrez@amd.com for (int i = 0; i < loadQueue.size(); ++i) 23311308Santhony.gutierrez@amd.com loadQueue[i] = NULL; 23411308Santhony.gutierrez@amd.com 23512717Sbrandon.potter@amd.com assert(storesToWB == 0); 23611308Santhony.gutierrez@amd.com} 23711308Santhony.gutierrez@amd.com 23811308Santhony.gutierrez@amd.comtemplate<class Impl> 23911308Santhony.gutierrez@amd.comvoid 24011308Santhony.gutierrez@amd.comLSQUnit<Impl>::takeOverFrom() 24111308Santhony.gutierrez@amd.com{ 24212749Sgiacomo.travaglini@arm.com switchedOut = false; 24312749Sgiacomo.travaglini@arm.com loads = stores = storesToWB = 0; 24411308Santhony.gutierrez@amd.com 24511308Santhony.gutierrez@amd.com loadHead = loadTail = 0; 24611308Santhony.gutierrez@amd.com 24711308Santhony.gutierrez@amd.com storeHead = storeWBIdx = storeTail = 0; 24811308Santhony.gutierrez@amd.com 24911308Santhony.gutierrez@amd.com usedPorts = 0; 25011308Santhony.gutierrez@amd.com 25112717Sbrandon.potter@amd.com memDepViolator = NULL; 25211308Santhony.gutierrez@amd.com 25312717Sbrandon.potter@amd.com blockedLoadSeqNum = 0; 25411308Santhony.gutierrez@amd.com 25511308Santhony.gutierrez@amd.com stalled = false; 25611308Santhony.gutierrez@amd.com isLoadBlocked = false; 25711308Santhony.gutierrez@amd.com loadBlockedHandled = false; 25811308Santhony.gutierrez@amd.com} 25911308Santhony.gutierrez@amd.com 26011308Santhony.gutierrez@amd.comtemplate<class Impl> 26111308Santhony.gutierrez@amd.comvoid 26211308Santhony.gutierrez@amd.comLSQUnit<Impl>::resizeLQ(unsigned size) 26311308Santhony.gutierrez@amd.com{ 26411308Santhony.gutierrez@amd.com unsigned size_plus_sentinel = size + 1; 26511308Santhony.gutierrez@amd.com assert(size_plus_sentinel >= LQEntries); 26611308Santhony.gutierrez@amd.com 26711308Santhony.gutierrez@amd.com if (size_plus_sentinel > LQEntries) { 26811308Santhony.gutierrez@amd.com while (size_plus_sentinel > loadQueue.size()) { 26911308Santhony.gutierrez@amd.com DynInstPtr dummy; 27011308Santhony.gutierrez@amd.com loadQueue.push_back(dummy); 27111308Santhony.gutierrez@amd.com LQEntries++; 27211308Santhony.gutierrez@amd.com } 27311308Santhony.gutierrez@amd.com } else { 27411308Santhony.gutierrez@amd.com LQEntries = size_plus_sentinel; 27513449Sgabeblack@google.com } 27611308Santhony.gutierrez@amd.com 27711308Santhony.gutierrez@amd.com} 27811308Santhony.gutierrez@amd.com 27911308Santhony.gutierrez@amd.comtemplate<class Impl> 28011308Santhony.gutierrez@amd.comvoid 28111308Santhony.gutierrez@amd.comLSQUnit<Impl>::resizeSQ(unsigned size) 28211308Santhony.gutierrez@amd.com{ 28311308Santhony.gutierrez@amd.com unsigned size_plus_sentinel = size + 1; 28411308Santhony.gutierrez@amd.com if (size_plus_sentinel > SQEntries) { 28511308Santhony.gutierrez@amd.com while (size_plus_sentinel > storeQueue.size()) { 28611308Santhony.gutierrez@amd.com SQEntry dummy; 28711308Santhony.gutierrez@amd.com storeQueue.push_back(dummy); 28811308Santhony.gutierrez@amd.com SQEntries++; 28911308Santhony.gutierrez@amd.com } 29011308Santhony.gutierrez@amd.com } else { 29111308Santhony.gutierrez@amd.com SQEntries = size_plus_sentinel; 29211308Santhony.gutierrez@amd.com } 29311308Santhony.gutierrez@amd.com} 29411308Santhony.gutierrez@amd.com 29511308Santhony.gutierrez@amd.comtemplate <class Impl> 29611308Santhony.gutierrez@amd.comvoid 29711308Santhony.gutierrez@amd.comLSQUnit<Impl>::insert(DynInstPtr &inst) 29811308Santhony.gutierrez@amd.com{ 29911308Santhony.gutierrez@amd.com assert(inst->isMemRef()); 30011308Santhony.gutierrez@amd.com 30111308Santhony.gutierrez@amd.com assert(inst->isLoad() || inst->isStore()); 30211308Santhony.gutierrez@amd.com 30311308Santhony.gutierrez@amd.com if (inst->isLoad()) { 30411308Santhony.gutierrez@amd.com insertLoad(inst); 30511308Santhony.gutierrez@amd.com } else { 30611308Santhony.gutierrez@amd.com insertStore(inst); 30711308Santhony.gutierrez@amd.com } 30811308Santhony.gutierrez@amd.com 30911308Santhony.gutierrez@amd.com inst->setInLSQ(); 31011308Santhony.gutierrez@amd.com} 31113784Sgabeblack@google.com 31213784Sgabeblack@google.comtemplate <class Impl> 31311308Santhony.gutierrez@amd.comvoid 31411308Santhony.gutierrez@amd.comLSQUnit<Impl>::insertLoad(DynInstPtr &load_inst) 31511308Santhony.gutierrez@amd.com{ 31611308Santhony.gutierrez@amd.com assert((loadTail + 1) % LQEntries != loadHead); 31711308Santhony.gutierrez@amd.com assert(loads < LQEntries); 31811308Santhony.gutierrez@amd.com 31911308Santhony.gutierrez@amd.com DPRINTF(LSQUnit, "Inserting load PC %#x, idx:%i [sn:%lli]\n", 32011308Santhony.gutierrez@amd.com load_inst->readPC(), loadTail, load_inst->seqNum); 32111308Santhony.gutierrez@amd.com 32211308Santhony.gutierrez@amd.com load_inst->lqIdx = loadTail; 32311308Santhony.gutierrez@amd.com 32411308Santhony.gutierrez@amd.com if (stores == 0) { 32511308Santhony.gutierrez@amd.com load_inst->sqIdx = -1; 32611308Santhony.gutierrez@amd.com } else { 32711308Santhony.gutierrez@amd.com load_inst->sqIdx = storeTail; 32811308Santhony.gutierrez@amd.com } 32911308Santhony.gutierrez@amd.com 33011308Santhony.gutierrez@amd.com loadQueue[loadTail] = load_inst; 33111308Santhony.gutierrez@amd.com 33211308Santhony.gutierrez@amd.com incrLdIdx(loadTail); 33311308Santhony.gutierrez@amd.com 33411308Santhony.gutierrez@amd.com ++loads; 33511308Santhony.gutierrez@amd.com} 33611308Santhony.gutierrez@amd.com 33711308Santhony.gutierrez@amd.comtemplate <class Impl> 33811308Santhony.gutierrez@amd.comvoid 33911308Santhony.gutierrez@amd.comLSQUnit<Impl>::insertStore(DynInstPtr &store_inst) 34011308Santhony.gutierrez@amd.com{ 34111308Santhony.gutierrez@amd.com // Make sure it is not full before inserting an instruction. 34212717Sbrandon.potter@amd.com assert((storeTail + 1) % SQEntries != storeHead); 34311308Santhony.gutierrez@amd.com assert(stores < SQEntries); 34411308Santhony.gutierrez@amd.com 34511308Santhony.gutierrez@amd.com DPRINTF(LSQUnit, "Inserting store PC %#x, idx:%i [sn:%lli]\n", 34611308Santhony.gutierrez@amd.com store_inst->readPC(), storeTail, store_inst->seqNum); 34711308Santhony.gutierrez@amd.com 34811308Santhony.gutierrez@amd.com store_inst->sqIdx = storeTail; 34911308Santhony.gutierrez@amd.com store_inst->lqIdx = loadTail; 35011308Santhony.gutierrez@amd.com 35111308Santhony.gutierrez@amd.com storeQueue[storeTail] = SQEntry(store_inst); 35211308Santhony.gutierrez@amd.com 35311308Santhony.gutierrez@amd.com incrStIdx(storeTail); 35411308Santhony.gutierrez@amd.com 35511308Santhony.gutierrez@amd.com ++stores; 35611308Santhony.gutierrez@amd.com} 35711308Santhony.gutierrez@amd.com 35811308Santhony.gutierrez@amd.comtemplate <class Impl> 35911308Santhony.gutierrez@amd.comtypename Impl::DynInstPtr 36011308Santhony.gutierrez@amd.comLSQUnit<Impl>::getMemDepViolator() 36111308Santhony.gutierrez@amd.com{ 36211308Santhony.gutierrez@amd.com DynInstPtr temp = memDepViolator; 36311308Santhony.gutierrez@amd.com 36411308Santhony.gutierrez@amd.com memDepViolator = NULL; 36511308Santhony.gutierrez@amd.com 36611308Santhony.gutierrez@amd.com return temp; 36711308Santhony.gutierrez@amd.com} 36811308Santhony.gutierrez@amd.com 36911308Santhony.gutierrez@amd.comtemplate <class Impl> 37011308Santhony.gutierrez@amd.comunsigned 37111308Santhony.gutierrez@amd.comLSQUnit<Impl>::numFreeEntries() 37211308Santhony.gutierrez@amd.com{ 37311308Santhony.gutierrez@amd.com unsigned free_lq_entries = LQEntries - loads; 37411308Santhony.gutierrez@amd.com unsigned free_sq_entries = SQEntries - stores; 37511308Santhony.gutierrez@amd.com 37611308Santhony.gutierrez@amd.com // Both the LQ and SQ entries have an extra dummy entry to differentiate 37711308Santhony.gutierrez@amd.com // empty/full conditions. Subtract 1 from the free entries. 37811308Santhony.gutierrez@amd.com if (free_lq_entries < free_sq_entries) { 37911308Santhony.gutierrez@amd.com return free_lq_entries - 1; 38011308Santhony.gutierrez@amd.com } else { 38111308Santhony.gutierrez@amd.com return free_sq_entries - 1; 38211308Santhony.gutierrez@amd.com } 38311308Santhony.gutierrez@amd.com} 38411308Santhony.gutierrez@amd.com 38511308Santhony.gutierrez@amd.comtemplate <class Impl> 38611308Santhony.gutierrez@amd.comint 38711308Santhony.gutierrez@amd.comLSQUnit<Impl>::numLoadsReady() 38811308Santhony.gutierrez@amd.com{ 38911308Santhony.gutierrez@amd.com int load_idx = loadHead; 39011308Santhony.gutierrez@amd.com int retval = 0; 39111308Santhony.gutierrez@amd.com 39211308Santhony.gutierrez@amd.com while (load_idx != loadTail) { 39311308Santhony.gutierrez@amd.com assert(loadQueue[load_idx]); 39411308Santhony.gutierrez@amd.com 39511308Santhony.gutierrez@amd.com if (loadQueue[load_idx]->readyToIssue()) { 39611308Santhony.gutierrez@amd.com ++retval; 39711308Santhony.gutierrez@amd.com } 39811308Santhony.gutierrez@amd.com } 39911308Santhony.gutierrez@amd.com 40011308Santhony.gutierrez@amd.com return retval; 40111308Santhony.gutierrez@amd.com} 40211308Santhony.gutierrez@amd.com 40311308Santhony.gutierrez@amd.comtemplate <class Impl> 40411308Santhony.gutierrez@amd.comFault 40511308Santhony.gutierrez@amd.comLSQUnit<Impl>::executeLoad(DynInstPtr &inst) 40611308Santhony.gutierrez@amd.com{ 40711308Santhony.gutierrez@amd.com // Execute a specific load. 40811308Santhony.gutierrez@amd.com Fault load_fault = NoFault; 40911308Santhony.gutierrez@amd.com 41011308Santhony.gutierrez@amd.com DPRINTF(LSQUnit, "Executing load PC %#x, [sn:%lli]\n", 41111308Santhony.gutierrez@amd.com inst->readPC(),inst->seqNum); 41211308Santhony.gutierrez@amd.com 41311308Santhony.gutierrez@amd.com load_fault = inst->initiateAcc(); 41411308Santhony.gutierrez@amd.com 41512085Sspwilson2@wisc.edu // If the instruction faulted, then we need to send it along to commit 41611308Santhony.gutierrez@amd.com // without the instruction completing. 41711308Santhony.gutierrez@amd.com if (load_fault != NoFault) { 41811308Santhony.gutierrez@amd.com // Send this instruction to commit, also make sure iew stage 41911308Santhony.gutierrez@amd.com // realizes there is activity. 42011308Santhony.gutierrez@amd.com iewStage->instToCommit(inst); 42111308Santhony.gutierrez@amd.com iewStage->activityThisCycle(); 42211308Santhony.gutierrez@amd.com } 42311308Santhony.gutierrez@amd.com 42411308Santhony.gutierrez@amd.com return load_fault; 42511308Santhony.gutierrez@amd.com} 42611308Santhony.gutierrez@amd.com 42711308Santhony.gutierrez@amd.comtemplate <class Impl> 42811308Santhony.gutierrez@amd.comFault 42911308Santhony.gutierrez@amd.comLSQUnit<Impl>::executeStore(DynInstPtr &store_inst) 43011308Santhony.gutierrez@amd.com{ 43111308Santhony.gutierrez@amd.com using namespace TheISA; 43211308Santhony.gutierrez@amd.com // Make sure that a store exists. 43311308Santhony.gutierrez@amd.com assert(stores != 0); 43411308Santhony.gutierrez@amd.com 43511308Santhony.gutierrez@amd.com int store_idx = store_inst->sqIdx; 43611308Santhony.gutierrez@amd.com 43711308Santhony.gutierrez@amd.com DPRINTF(LSQUnit, "Executing store PC %#x [sn:%lli]\n", 43811308Santhony.gutierrez@amd.com store_inst->readPC(), store_inst->seqNum); 43911308Santhony.gutierrez@amd.com 44011308Santhony.gutierrez@amd.com // Check the recently completed loads to see if any match this store's 44111308Santhony.gutierrez@amd.com // address. If so, then we have a memory ordering violation. 44211308Santhony.gutierrez@amd.com int load_idx = store_inst->lqIdx; 44311308Santhony.gutierrez@amd.com 44411308Santhony.gutierrez@amd.com Fault store_fault = store_inst->initiateAcc(); 44511308Santhony.gutierrez@amd.com// Fault store_fault = store_inst->execute(); 44611308Santhony.gutierrez@amd.com 44711308Santhony.gutierrez@amd.com if (storeQueue[store_idx].size == 0) { 44812085Sspwilson2@wisc.edu DPRINTF(LSQUnit,"Fault on Store PC %#x, [sn:%lli],Size = 0\n", 44911308Santhony.gutierrez@amd.com store_inst->readPC(),store_inst->seqNum); 45011308Santhony.gutierrez@amd.com 45111308Santhony.gutierrez@amd.com return store_fault; 45211308Santhony.gutierrez@amd.com } 453 454 assert(store_fault == NoFault); 455 456 if (store_inst->isStoreConditional()) { 457 // Store conditionals need to set themselves as able to 458 // writeback if we haven't had a fault by here. 459 storeQueue[store_idx].canWB = true; 460 461 ++storesToWB; 462 } 463 464 if (!memDepViolator) { 465 while (load_idx != loadTail) { 466 // Really only need to check loads that have actually executed 467 // It's safe to check all loads because effAddr is set to 468 // InvalAddr when the dyn inst is created. 469 470 // @todo: For now this is extra conservative, detecting a 471 // violation if the addresses match assuming all accesses 472 // are quad word accesses. 473 474 // @todo: Fix this, magic number being used here 475 if ((loadQueue[load_idx]->effAddr >> 8) == 476 (store_inst->effAddr >> 8)) { 477 // A load incorrectly passed this store. Squash and refetch. 478 // For now return a fault to show that it was unsuccessful. 479 memDepViolator = loadQueue[load_idx]; 480 481 return genMachineCheckFault(); 482 } 483 484 incrLdIdx(load_idx); 485 } 486 487 // If we've reached this point, there was no violation. 488 memDepViolator = NULL; 489 } 490 491 return store_fault; 492} 493 494template <class Impl> 495void 496LSQUnit<Impl>::commitLoad() 497{ 498 assert(loadQueue[loadHead]); 499 500 DPRINTF(LSQUnit, "Committing head load instruction, PC %#x\n", 501 loadQueue[loadHead]->readPC()); 502 503 504 loadQueue[loadHead] = NULL; 505 506 incrLdIdx(loadHead); 507 508 --loads; 509} 510 511template <class Impl> 512void 513LSQUnit<Impl>::commitLoads(InstSeqNum &youngest_inst) 514{ 515 assert(loads == 0 || loadQueue[loadHead]); 516 517 while (loads != 0 && loadQueue[loadHead]->seqNum <= youngest_inst) { 518 commitLoad(); 519 } 520} 521 522template <class Impl> 523void 524LSQUnit<Impl>::commitStores(InstSeqNum &youngest_inst) 525{ 526 assert(stores == 0 || storeQueue[storeHead].inst); 527 528 int store_idx = storeHead; 529 530 while (store_idx != storeTail) { 531 assert(storeQueue[store_idx].inst); 532 // Mark any stores that are now committed and have not yet 533 // been marked as able to write back. 534 if (!storeQueue[store_idx].canWB) { 535 if (storeQueue[store_idx].inst->seqNum > youngest_inst) { 536 break; 537 } 538 DPRINTF(LSQUnit, "Marking store as able to write back, PC " 539 "%#x [sn:%lli]\n", 540 storeQueue[store_idx].inst->readPC(), 541 storeQueue[store_idx].inst->seqNum); 542 543 storeQueue[store_idx].canWB = true; 544 545 ++storesToWB; 546 } 547 548 incrStIdx(store_idx); 549 } 550} 551 552template <class Impl> 553void 554LSQUnit<Impl>::writebackStores() 555{ 556 while (storesToWB > 0 && 557 storeWBIdx != storeTail && 558 storeQueue[storeWBIdx].inst && 559 storeQueue[storeWBIdx].canWB && 560 usedPorts < cachePorts) { 561 562 // Store didn't write any data so no need to write it back to 563 // memory. 564 if (storeQueue[storeWBIdx].size == 0) { 565 completeStore(storeWBIdx); 566 567 incrStIdx(storeWBIdx); 568 569 continue; 570 } 571/* 572 if (dcacheInterface && dcacheInterface->isBlocked()) { 573 DPRINTF(LSQUnit, "Unable to write back any more stores, cache" 574 " is blocked!\n"); 575 break; 576 } 577*/ 578 ++usedPorts; 579 580 if (storeQueue[storeWBIdx].inst->isDataPrefetch()) { 581 incrStIdx(storeWBIdx); 582 583 continue; 584 } 585 586 assert(storeQueue[storeWBIdx].req); 587 assert(!storeQueue[storeWBIdx].committed); 588 589 DynInstPtr inst = storeQueue[storeWBIdx].inst; 590 591 Request *req = storeQueue[storeWBIdx].req; 592 storeQueue[storeWBIdx].committed = true; 593 594 assert(!inst->memData); 595 inst->memData = new uint8_t[64]; 596 memcpy(inst->memData, (uint8_t *)&storeQueue[storeWBIdx].data, req->getSize()); 597 598 PacketPtr data_pkt = new Packet(req, Packet::WriteReq, Packet::Broadcast); 599 data_pkt->dataStatic(inst->memData); 600 601 DPRINTF(LSQUnit, "D-Cache: Writing back store idx:%i PC:%#x " 602 "to Addr:%#x, data:%#x [sn:%lli]\n", 603 storeWBIdx, storeQueue[storeWBIdx].inst->readPC(), 604 req->getPaddr(), *(inst->memData), 605 storeQueue[storeWBIdx].inst->seqNum); 606 607 if (!dcachePort->sendTiming(data_pkt)) { 608 // Need to handle becoming blocked on a store. 609 } else { 610 /* 611 StoreCompletionEvent *store_event = new 612 StoreCompletionEvent(storeWBIdx, NULL, this); 613 */ 614 if (isStalled() && 615 storeQueue[storeWBIdx].inst->seqNum == stallingStoreIsn) { 616 DPRINTF(LSQUnit, "Unstalling, stalling store [sn:%lli] " 617 "load idx:%i\n", 618 stallingStoreIsn, stallingLoadIdx); 619 stalled = false; 620 stallingStoreIsn = 0; 621 iewStage->replayMemInst(loadQueue[stallingLoadIdx]); 622 } 623/* 624 typename LdWritebackEvent *wb = NULL; 625 if (req->flags & LOCKED) { 626 // Stx_C should not generate a system port transaction 627 // if it misses in the cache, but that might be hard 628 // to accomplish without explicit cache support. 629 wb = new typename 630 LdWritebackEvent(storeQueue[storeWBIdx].inst, 631 iewStage); 632 store_event->wbEvent = wb; 633 } 634*/ 635 if (data_pkt->result != Packet::Success) { 636 DPRINTF(LSQUnit,"D-Cache Write Miss on idx:%i!\n", 637 storeWBIdx); 638 639 DPRINTF(Activity, "Active st accessing mem miss [sn:%lli]\n", 640 storeQueue[storeWBIdx].inst->seqNum); 641 642 //mshrSeqNums.push_back(storeQueue[storeWBIdx].inst->seqNum); 643 644 //DPRINTF(LSQUnit, "Added MSHR. count = %i\n",mshrSeqNums.size()); 645 646 // @todo: Increment stat here. 647 } else { 648 DPRINTF(LSQUnit,"D-Cache: Write Hit on idx:%i !\n", 649 storeWBIdx); 650 651 DPRINTF(Activity, "Active st accessing mem hit [sn:%lli]\n", 652 storeQueue[storeWBIdx].inst->seqNum); 653 } 654 655 incrStIdx(storeWBIdx); 656 } 657 } 658 659 // Not sure this should set it to 0. 660 usedPorts = 0; 661 662 assert(stores >= 0 && storesToWB >= 0); 663} 664 665/*template <class Impl> 666void 667LSQUnit<Impl>::removeMSHR(InstSeqNum seqNum) 668{ 669 list<InstSeqNum>::iterator mshr_it = find(mshrSeqNums.begin(), 670 mshrSeqNums.end(), 671 seqNum); 672 673 if (mshr_it != mshrSeqNums.end()) { 674 mshrSeqNums.erase(mshr_it); 675 DPRINTF(LSQUnit, "Removing MSHR. count = %i\n",mshrSeqNums.size()); 676 } 677}*/ 678 679template <class Impl> 680void 681LSQUnit<Impl>::squash(const InstSeqNum &squashed_num) 682{ 683 DPRINTF(LSQUnit, "Squashing until [sn:%lli]!" 684 "(Loads:%i Stores:%i)\n", squashed_num, loads, stores); 685 686 int load_idx = loadTail; 687 decrLdIdx(load_idx); 688 689 while (loads != 0 && loadQueue[load_idx]->seqNum > squashed_num) { 690 DPRINTF(LSQUnit,"Load Instruction PC %#x squashed, " 691 "[sn:%lli]\n", 692 loadQueue[load_idx]->readPC(), 693 loadQueue[load_idx]->seqNum); 694 695 if (isStalled() && load_idx == stallingLoadIdx) { 696 stalled = false; 697 stallingStoreIsn = 0; 698 stallingLoadIdx = 0; 699 } 700 701 // Clear the smart pointer to make sure it is decremented. 702 loadQueue[load_idx]->squashed = true; 703 loadQueue[load_idx] = NULL; 704 --loads; 705 706 // Inefficient! 707 loadTail = load_idx; 708 709 decrLdIdx(load_idx); 710 } 711 712 if (isLoadBlocked) { 713 if (squashed_num < blockedLoadSeqNum) { 714 isLoadBlocked = false; 715 loadBlockedHandled = false; 716 blockedLoadSeqNum = 0; 717 } 718 } 719 720 int store_idx = storeTail; 721 decrStIdx(store_idx); 722 723 while (stores != 0 && 724 storeQueue[store_idx].inst->seqNum > squashed_num) { 725 // Instructions marked as can WB are already committed. 726 if (storeQueue[store_idx].canWB) { 727 break; 728 } 729 730 DPRINTF(LSQUnit,"Store Instruction PC %#x squashed, " 731 "idx:%i [sn:%lli]\n", 732 storeQueue[store_idx].inst->readPC(), 733 store_idx, storeQueue[store_idx].inst->seqNum); 734 735 // I don't think this can happen. It should have been cleared 736 // by the stalling load. 737 if (isStalled() && 738 storeQueue[store_idx].inst->seqNum == stallingStoreIsn) { 739 panic("Is stalled should have been cleared by stalling load!\n"); 740 stalled = false; 741 stallingStoreIsn = 0; 742 } 743 744 // Clear the smart pointer to make sure it is decremented. 745 storeQueue[store_idx].inst->squashed = true; 746 storeQueue[store_idx].inst = NULL; 747 storeQueue[store_idx].canWB = 0; 748 749 storeQueue[store_idx].req = NULL; 750 --stores; 751 752 // Inefficient! 753 storeTail = store_idx; 754 755 decrStIdx(store_idx); 756 } 757} 758 759template <class Impl> 760void 761LSQUnit<Impl>::completeStore(int store_idx) 762{ 763 assert(storeQueue[store_idx].inst); 764 storeQueue[store_idx].completed = true; 765 --storesToWB; 766 // A bit conservative because a store completion may not free up entries, 767 // but hopefully avoids two store completions in one cycle from making 768 // the CPU tick twice. 769 cpu->activityThisCycle(); 770 771 if (store_idx == storeHead) { 772 do { 773 incrStIdx(storeHead); 774 775 --stores; 776 } while (storeQueue[storeHead].completed && 777 storeHead != storeTail); 778 779 iewStage->updateLSQNextCycle = true; 780 } 781 782 DPRINTF(LSQUnit, "Completing store [sn:%lli], idx:%i, store head " 783 "idx:%i\n", 784 storeQueue[store_idx].inst->seqNum, store_idx, storeHead); 785 786 if (isStalled() && 787 storeQueue[store_idx].inst->seqNum == stallingStoreIsn) { 788 DPRINTF(LSQUnit, "Unstalling, stalling store [sn:%lli] " 789 "load idx:%i\n", 790 stallingStoreIsn, stallingLoadIdx); 791 stalled = false; 792 stallingStoreIsn = 0; 793 iewStage->replayMemInst(loadQueue[stallingLoadIdx]); 794 } 795 796 storeQueue[store_idx].inst->setCompleted(); 797 798 // Tell the checker we've completed this instruction. Some stores 799 // may get reported twice to the checker, but the checker can 800 // handle that case. 801 if (cpu->checker) { 802 cpu->checker->tick(storeQueue[store_idx].inst); 803 } 804} 805 806template <class Impl> 807inline void 808LSQUnit<Impl>::incrStIdx(int &store_idx) 809{ 810 if (++store_idx >= SQEntries) 811 store_idx = 0; 812} 813 814template <class Impl> 815inline void 816LSQUnit<Impl>::decrStIdx(int &store_idx) 817{ 818 if (--store_idx < 0) 819 store_idx += SQEntries; 820} 821 822template <class Impl> 823inline void 824LSQUnit<Impl>::incrLdIdx(int &load_idx) 825{ 826 if (++load_idx >= LQEntries) 827 load_idx = 0; 828} 829 830template <class Impl> 831inline void 832LSQUnit<Impl>::decrLdIdx(int &load_idx) 833{ 834 if (--load_idx < 0) 835 load_idx += LQEntries; 836} 837 838template <class Impl> 839void 840LSQUnit<Impl>::dumpInsts() 841{ 842 cprintf("Load store queue: Dumping instructions.\n"); 843 cprintf("Load queue size: %i\n", loads); 844 cprintf("Load queue: "); 845 846 int load_idx = loadHead; 847 848 while (load_idx != loadTail && loadQueue[load_idx]) { 849 cprintf("%#x ", loadQueue[load_idx]->readPC()); 850 851 incrLdIdx(load_idx); 852 } 853 854 cprintf("Store queue size: %i\n", stores); 855 cprintf("Store queue: "); 856 857 int store_idx = storeHead; 858 859 while (store_idx != storeTail && storeQueue[store_idx].inst) { 860 cprintf("%#x ", storeQueue[store_idx].inst->readPC()); 861 862 incrStIdx(store_idx); 863 } 864 865 cprintf("\n"); 866} 867