lsq_unit_impl.hh revision 2361
16657Snate@binkert.org/* 26657Snate@binkert.org * Copyright (c) 2004-2005 The Regents of The University of Michigan 36657Snate@binkert.org * All rights reserved. 46657Snate@binkert.org * 56657Snate@binkert.org * Redistribution and use in source and binary forms, with or without 66657Snate@binkert.org * modification, are permitted provided that the following conditions are 76657Snate@binkert.org * met: redistributions of source code must retain the above copyright 86657Snate@binkert.org * notice, this list of conditions and the following disclaimer; 96657Snate@binkert.org * redistributions in binary form must reproduce the above copyright 106657Snate@binkert.org * notice, this list of conditions and the following disclaimer in the 116657Snate@binkert.org * documentation and/or other materials provided with the distribution; 126657Snate@binkert.org * neither the name of the copyright holders nor the names of its 136657Snate@binkert.org * contributors may be used to endorse or promote products derived from 146657Snate@binkert.org * this software without specific prior written permission. 156657Snate@binkert.org * 166657Snate@binkert.org * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 176657Snate@binkert.org * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 186657Snate@binkert.org * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 196657Snate@binkert.org * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 206657Snate@binkert.org * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 216657Snate@binkert.org * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 226657Snate@binkert.org * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 236657Snate@binkert.org * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 246657Snate@binkert.org * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 256657Snate@binkert.org * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 266657Snate@binkert.org * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 276657Snate@binkert.org */ 286999Snate@binkert.org 296657Snate@binkert.org#include "cpu/checker/cpu.hh" 306657Snate@binkert.org#include "cpu/o3/lsq_unit.hh" 316657Snate@binkert.org#include "base/str.hh" 329302Snilay@cs.wisc.edu 336657Snate@binkert.orgtemplate <class Impl> 346657Snate@binkert.orgLSQUnit<Impl>::StoreCompletionEvent::StoreCompletionEvent(int store_idx, 356657Snate@binkert.org Event *wb_event, 366657Snate@binkert.org LSQUnit<Impl> *lsq_ptr) 376657Snate@binkert.org : Event(&mainEventQueue), 386657Snate@binkert.org wbEvent(wb_event), 396657Snate@binkert.org storeIdx(store_idx), 406657Snate@binkert.org lsqPtr(lsq_ptr) 416657Snate@binkert.org{ 426657Snate@binkert.org this->setFlags(Event::AutoDelete); 436657Snate@binkert.org} 446657Snate@binkert.org 456657Snate@binkert.orgtemplate <class Impl> 466657Snate@binkert.orgvoid 476657Snate@binkert.orgLSQUnit<Impl>::StoreCompletionEvent::process() 486657Snate@binkert.org{ 496657Snate@binkert.org DPRINTF(LSQ, "Cache miss complete for store idx:%i\n", storeIdx); 506657Snate@binkert.org DPRINTF(Activity, "Activity: st writeback event idx:%i\n", storeIdx); 516657Snate@binkert.org 526657Snate@binkert.org //lsqPtr->removeMSHR(lsqPtr->storeQueue[storeIdx].inst->seqNum); 536657Snate@binkert.org 546657Snate@binkert.org if (lsqPtr->isSwitchedOut()) { 556882SBrad.Beckmann@amd.com if (wbEvent) 566657Snate@binkert.org delete wbEvent; 576657Snate@binkert.org 586657Snate@binkert.org return; 596657Snate@binkert.org } 606657Snate@binkert.org 616657Snate@binkert.org lsqPtr->cpu->wakeCPU(); 626657Snate@binkert.org if (wbEvent) { 636657Snate@binkert.org wbEvent->process(); 646657Snate@binkert.org delete wbEvent; 656657Snate@binkert.org } 666657Snate@binkert.org lsqPtr->completeStore(storeIdx); 676657Snate@binkert.org} 686657Snate@binkert.org 696657Snate@binkert.orgtemplate <class Impl> 706657Snate@binkert.orgconst char * 716657Snate@binkert.orgLSQUnit<Impl>::StoreCompletionEvent::description() 726657Snate@binkert.org{ 736657Snate@binkert.org return "LSQ store completion event"; 746657Snate@binkert.org} 756657Snate@binkert.org 766657Snate@binkert.orgtemplate <class Impl> 776657Snate@binkert.orgLSQUnit<Impl>::LSQUnit() 786657Snate@binkert.org : loads(0), stores(0), storesToWB(0), stalled(false), isLoadBlocked(false), 796657Snate@binkert.org loadBlockedHandled(false) 806657Snate@binkert.org{ 816657Snate@binkert.org} 826657Snate@binkert.org 836657Snate@binkert.orgtemplate<class Impl> 846657Snate@binkert.orgvoid 856657Snate@binkert.orgLSQUnit<Impl>::init(Params *params, unsigned maxLQEntries, 866657Snate@binkert.org unsigned maxSQEntries, unsigned id) 876657Snate@binkert.org 886657Snate@binkert.org{ 896657Snate@binkert.org DPRINTF(LSQUnit, "Creating LSQUnit%i object.\n",id); 906657Snate@binkert.org 916657Snate@binkert.org switchedOut = false; 926657Snate@binkert.org 936657Snate@binkert.org lsqID = id; 946657Snate@binkert.org 956657Snate@binkert.org // Add 1 for the sentinel entry (they are circular queues). 966657Snate@binkert.org LQEntries = maxLQEntries + 1; 976657Snate@binkert.org SQEntries = maxSQEntries + 1; 986657Snate@binkert.org 996657Snate@binkert.org loadQueue.resize(LQEntries); 1006657Snate@binkert.org storeQueue.resize(SQEntries); 1016657Snate@binkert.org 1026657Snate@binkert.org loadHead = loadTail = 0; 1036657Snate@binkert.org 1048086SBrad.Beckmann@amd.com storeHead = storeWBIdx = storeTail = 0; 1058086SBrad.Beckmann@amd.com 1068086SBrad.Beckmann@amd.com usedPorts = 0; 1076657Snate@binkert.org cachePorts = params->cachePorts; 1086657Snate@binkert.org 1096657Snate@binkert.org dcacheInterface = params->dcacheInterface; 1106657Snate@binkert.org 1119298Snilay@cs.wisc.edu memDepViolator = NULL; 1126657Snate@binkert.org 1136657Snate@binkert.org blockedLoadSeqNum = 0; 1146657Snate@binkert.org} 1156657Snate@binkert.org 1166657Snate@binkert.orgtemplate<class Impl> 1176657Snate@binkert.orgstd::string 1186657Snate@binkert.orgLSQUnit<Impl>::name() const 1196657Snate@binkert.org{ 1206657Snate@binkert.org if (Impl::MaxThreads == 1) { 1216657Snate@binkert.org return iewStage->name() + ".lsq"; 1226657Snate@binkert.org } else { 1236657Snate@binkert.org return iewStage->name() + ".lsq.thread." + to_string(lsqID); 1246657Snate@binkert.org } 1256657Snate@binkert.org} 1266657Snate@binkert.org 1276657Snate@binkert.orgtemplate<class Impl> 1286657Snate@binkert.orgvoid 1296657Snate@binkert.orgLSQUnit<Impl>::regStats() 1306657Snate@binkert.org{ 1316657Snate@binkert.org lsqForwLoads 1326657Snate@binkert.org .name(name() + ".forwLoads") 1336657Snate@binkert.org .desc("Number of loads that had data forwarded from stores"); 1346657Snate@binkert.org 1356657Snate@binkert.org invAddrLoads 1366657Snate@binkert.org .name(name() + ".invAddrLoads") 1376657Snate@binkert.org .desc("Number of loads ignored due to an invalid address"); 1386657Snate@binkert.org 1396657Snate@binkert.org lsqSquashedLoads 1406657Snate@binkert.org .name(name() + ".squashedLoads") 1416657Snate@binkert.org .desc("Number of loads squashed"); 1426657Snate@binkert.org 1436657Snate@binkert.org lsqIgnoredResponses 1446657Snate@binkert.org .name(name() + ".ignoredResponses") 1456657Snate@binkert.org .desc("Number of memory responses ignored because the instruction is squashed"); 1466657Snate@binkert.org 1476657Snate@binkert.org lsqMemOrderViolation 1489298Snilay@cs.wisc.edu .name(name() + ".memOrderViolation") 1496657Snate@binkert.org .desc("Number of memory ordering violations"); 1506657Snate@binkert.org 1516657Snate@binkert.org lsqSquashedStores 1526657Snate@binkert.org .name(name() + ".squashedStores") 1536657Snate@binkert.org .desc("Number of stores squashed"); 1546657Snate@binkert.org 1559302Snilay@cs.wisc.edu invAddrSwpfs 1569302Snilay@cs.wisc.edu .name(name() + ".invAddrSwpfs") 1579302Snilay@cs.wisc.edu .desc("Number of software prefetches ignored due to an invalid address"); 1586657Snate@binkert.org 1596657Snate@binkert.org lsqBlockedLoads 1606657Snate@binkert.org .name(name() + ".blockedLoads") 1616657Snate@binkert.org .desc("Number of blocked loads due to partial load-store forwarding"); 1626657Snate@binkert.org 1636657Snate@binkert.org lsqRescheduledLoads 1646657Snate@binkert.org .name(name() + ".rescheduledLoads") 1656657Snate@binkert.org .desc("Number of loads that were rescheduled"); 1666882SBrad.Beckmann@amd.com 1676882SBrad.Beckmann@amd.com lsqCacheBlocked 1686882SBrad.Beckmann@amd.com .name(name() + ".cacheBlocked") 1698086SBrad.Beckmann@amd.com .desc("Number of times an access to memory failed due to the cache being blocked"); 1708086SBrad.Beckmann@amd.com} 1718086SBrad.Beckmann@amd.com 1729298Snilay@cs.wisc.edutemplate<class Impl> 1736657Snate@binkert.orgvoid 1746657Snate@binkert.orgLSQUnit<Impl>::clearLQ() 1756657Snate@binkert.org{ 1766657Snate@binkert.org loadQueue.clear(); 1776657Snate@binkert.org} 1786657Snate@binkert.org 1796657Snate@binkert.orgtemplate<class Impl> 1809298Snilay@cs.wisc.eduvoid 1819298Snilay@cs.wisc.eduLSQUnit<Impl>::clearSQ() 1829298Snilay@cs.wisc.edu{ 1839298Snilay@cs.wisc.edu storeQueue.clear(); 1849298Snilay@cs.wisc.edu} 1859298Snilay@cs.wisc.edu 1869298Snilay@cs.wisc.edu#if 0 1879298Snilay@cs.wisc.edutemplate<class Impl> 1889298Snilay@cs.wisc.eduvoid 1899298Snilay@cs.wisc.eduLSQUnit<Impl>::setPageTable(PageTable *pt_ptr) 1909298Snilay@cs.wisc.edu{ 1919298Snilay@cs.wisc.edu DPRINTF(LSQUnit, "Setting the page table pointer.\n"); 1926657Snate@binkert.org pTable = pt_ptr; 1936657Snate@binkert.org} 1946657Snate@binkert.org#endif 1956657Snate@binkert.org 1966657Snate@binkert.orgtemplate<class Impl> 1976657Snate@binkert.orgvoid 1986657Snate@binkert.orgLSQUnit<Impl>::switchOut() 1996657Snate@binkert.org{ 2006657Snate@binkert.org switchedOut = true; 2016657Snate@binkert.org for (int i = 0; i < loadQueue.size(); ++i) 2026657Snate@binkert.org loadQueue[i] = NULL; 2039219Spower.jg@gmail.com 2046657Snate@binkert.org assert(storesToWB == 0); 2056657Snate@binkert.org 2066657Snate@binkert.org while (storesToWB > 0 && 2076657Snate@binkert.org storeWBIdx != storeTail && 2086657Snate@binkert.org storeQueue[storeWBIdx].inst && 2096657Snate@binkert.org storeQueue[storeWBIdx].canWB) { 2106657Snate@binkert.org 2116657Snate@binkert.org if (storeQueue[storeWBIdx].size == 0 || 2126657Snate@binkert.org storeQueue[storeWBIdx].inst->isDataPrefetch() || 2136657Snate@binkert.org storeQueue[storeWBIdx].committed || 2146657Snate@binkert.org storeQueue[storeWBIdx].req->flags & LOCKED) { 2156657Snate@binkert.org incrStIdx(storeWBIdx); 2166999Snate@binkert.org 2176657Snate@binkert.org continue; 2186657Snate@binkert.org } 2196657Snate@binkert.org 2206657Snate@binkert.org assert(storeQueue[storeWBIdx].req); 2216657Snate@binkert.org assert(!storeQueue[storeWBIdx].committed); 2226657Snate@binkert.org 2236657Snate@binkert.org MemReqPtr req = storeQueue[storeWBIdx].req; 2247007Snate@binkert.org storeQueue[storeWBIdx].committed = true; 2257007Snate@binkert.org 2266657Snate@binkert.org req->cmd = Write; 2277002Snate@binkert.org req->completionEvent = NULL; 2287002Snate@binkert.org req->time = curTick; 2299466Snilay@cs.wisc.edu assert(!req->data); 2306657Snate@binkert.org req->data = new uint8_t[64]; 2316657Snate@binkert.org memcpy(req->data, (uint8_t *)&storeQueue[storeWBIdx].data, req->size); 2326657Snate@binkert.org 2336657Snate@binkert.org DPRINTF(LSQUnit, "D-Cache: Writing back store idx:%i PC:%#x " 2346657Snate@binkert.org "to Addr:%#x, data:%#x [sn:%lli]\n", 2356657Snate@binkert.org storeWBIdx,storeQueue[storeWBIdx].inst->readPC(), 2366657Snate@binkert.org req->paddr, *(req->data), 2376657Snate@binkert.org storeQueue[storeWBIdx].inst->seqNum); 2386657Snate@binkert.org 2396657Snate@binkert.org switch(storeQueue[storeWBIdx].size) { 2406657Snate@binkert.org case 1: 2416657Snate@binkert.org cpu->write(req, (uint8_t &)storeQueue[storeWBIdx].data); 2427007Snate@binkert.org break; 2437007Snate@binkert.org case 2: 2446657Snate@binkert.org cpu->write(req, (uint16_t &)storeQueue[storeWBIdx].data); 2459466Snilay@cs.wisc.edu break; 2466657Snate@binkert.org case 4: 2476657Snate@binkert.org cpu->write(req, (uint32_t &)storeQueue[storeWBIdx].data); 2489466Snilay@cs.wisc.edu break; 2499508Snilay@cs.wisc.edu case 8: 2509466Snilay@cs.wisc.edu cpu->write(req, (uint64_t &)storeQueue[storeWBIdx].data); 2519466Snilay@cs.wisc.edu break; 2529466Snilay@cs.wisc.edu default: 2536657Snate@binkert.org panic("Unexpected store size!\n"); 2546657Snate@binkert.org } 2556657Snate@binkert.org incrStIdx(storeWBIdx); 2566657Snate@binkert.org } 2576657Snate@binkert.org} 2586657Snate@binkert.org 2596657Snate@binkert.orgtemplate<class Impl> 2606657Snate@binkert.orgvoid 2616657Snate@binkert.orgLSQUnit<Impl>::takeOverFrom() 2626657Snate@binkert.org{ 2636657Snate@binkert.org switchedOut = false; 2646657Snate@binkert.org loads = stores = storesToWB = 0; 2656657Snate@binkert.org 2666657Snate@binkert.org loadHead = loadTail = 0; 2676657Snate@binkert.org 2686657Snate@binkert.org storeHead = storeWBIdx = storeTail = 0; 2696657Snate@binkert.org 2707453Snate@binkert.org usedPorts = 0; 2717453Snate@binkert.org 2727453Snate@binkert.org memDepViolator = NULL; 2737453Snate@binkert.org 2747453Snate@binkert.org blockedLoadSeqNum = 0; 2757453Snate@binkert.org 2767453Snate@binkert.org stalled = false; 2777453Snate@binkert.org isLoadBlocked = false; 2787453Snate@binkert.org loadBlockedHandled = false; 2797453Snate@binkert.org} 2807453Snate@binkert.org 2817453Snate@binkert.orgtemplate<class Impl> 2827453Snate@binkert.orgvoid 2837453Snate@binkert.orgLSQUnit<Impl>::resizeLQ(unsigned size) 2847453Snate@binkert.org{ 2857453Snate@binkert.org unsigned size_plus_sentinel = size + 1; 2867453Snate@binkert.org assert(size_plus_sentinel >= LQEntries); 2876657Snate@binkert.org 2886657Snate@binkert.org if (size_plus_sentinel > LQEntries) { 2896657Snate@binkert.org while (size_plus_sentinel > loadQueue.size()) { 2906657Snate@binkert.org DynInstPtr dummy; 2919466Snilay@cs.wisc.edu loadQueue.push_back(dummy); 2926657Snate@binkert.org LQEntries++; 2939466Snilay@cs.wisc.edu } 2949508Snilay@cs.wisc.edu } else { 2959466Snilay@cs.wisc.edu LQEntries = size_plus_sentinel; 2966657Snate@binkert.org } 2976657Snate@binkert.org 2986657Snate@binkert.org} 2996657Snate@binkert.org 3009466Snilay@cs.wisc.edutemplate<class Impl> 3019466Snilay@cs.wisc.eduvoid 3029466Snilay@cs.wisc.eduLSQUnit<Impl>::resizeSQ(unsigned size) 3039466Snilay@cs.wisc.edu{ 3046657Snate@binkert.org unsigned size_plus_sentinel = size + 1; 3056657Snate@binkert.org if (size_plus_sentinel > SQEntries) { 3066657Snate@binkert.org while (size_plus_sentinel > storeQueue.size()) { 3076657Snate@binkert.org SQEntry dummy; 3086657Snate@binkert.org storeQueue.push_back(dummy); 3096657Snate@binkert.org SQEntries++; 3106657Snate@binkert.org } 3116657Snate@binkert.org } else { 3126657Snate@binkert.org SQEntries = size_plus_sentinel; 3136657Snate@binkert.org } 3146657Snate@binkert.org} 3159466Snilay@cs.wisc.edu 3167453Snate@binkert.orgtemplate <class Impl> 3177453Snate@binkert.orgvoid 3187007Snate@binkert.orgLSQUnit<Impl>::insert(DynInstPtr &inst) 3197007Snate@binkert.org{ 3207453Snate@binkert.org assert(inst->isMemRef()); 3217007Snate@binkert.org 3226657Snate@binkert.org assert(inst->isLoad() || inst->isStore()); 3236657Snate@binkert.org 3246657Snate@binkert.org if (inst->isLoad()) { 3256657Snate@binkert.org insertLoad(inst); 3266657Snate@binkert.org } else { 3276657Snate@binkert.org insertStore(inst); 3286657Snate@binkert.org } 3296657Snate@binkert.org 3306657Snate@binkert.org inst->setInLSQ(); 3316657Snate@binkert.org} 3327007Snate@binkert.org 3337007Snate@binkert.orgtemplate <class Impl> 3347007Snate@binkert.orgvoid 3357007Snate@binkert.orgLSQUnit<Impl>::insertLoad(DynInstPtr &load_inst) 3367007Snate@binkert.org{ 3376657Snate@binkert.org assert((loadTail + 1) % LQEntries != loadHead); 3386657Snate@binkert.org assert(loads < LQEntries); 3396657Snate@binkert.org 3406657Snate@binkert.org DPRINTF(LSQUnit, "Inserting load PC %#x, idx:%i [sn:%lli]\n", 3416657Snate@binkert.org load_inst->readPC(), loadTail, load_inst->seqNum); 3426657Snate@binkert.org 3436657Snate@binkert.org load_inst->lqIdx = loadTail; 3446657Snate@binkert.org 3456657Snate@binkert.org if (stores == 0) { 3467007Snate@binkert.org load_inst->sqIdx = -1; 3477007Snate@binkert.org } else { 3487007Snate@binkert.org load_inst->sqIdx = storeTail; 3497007Snate@binkert.org } 3507007Snate@binkert.org 3516657Snate@binkert.org loadQueue[loadTail] = load_inst; 3526657Snate@binkert.org 3536657Snate@binkert.org incrLdIdx(loadTail); 3546657Snate@binkert.org 3556657Snate@binkert.org ++loads; 3566657Snate@binkert.org} 3576657Snate@binkert.org 3587007Snate@binkert.orgtemplate <class Impl> 3597007Snate@binkert.orgvoid 3607007Snate@binkert.orgLSQUnit<Impl>::insertStore(DynInstPtr &store_inst) 3617007Snate@binkert.org{ 3627007Snate@binkert.org // Make sure it is not full before inserting an instruction. 3636657Snate@binkert.org assert((storeTail + 1) % SQEntries != storeHead); 3646657Snate@binkert.org assert(stores < SQEntries); 3657002Snate@binkert.org 3666657Snate@binkert.org DPRINTF(LSQUnit, "Inserting store PC %#x, idx:%i [sn:%lli]\n", 3676657Snate@binkert.org store_inst->readPC(), storeTail, store_inst->seqNum); 3686657Snate@binkert.org 3696657Snate@binkert.org store_inst->sqIdx = storeTail; 3706657Snate@binkert.org store_inst->lqIdx = loadTail; 3716657Snate@binkert.org 3726657Snate@binkert.org storeQueue[storeTail] = SQEntry(store_inst); 3736657Snate@binkert.org 3746657Snate@binkert.org incrStIdx(storeTail); 3756657Snate@binkert.org 3766657Snate@binkert.org ++stores; 3776657Snate@binkert.org} 3786657Snate@binkert.org 3796657Snate@binkert.orgtemplate <class Impl> 3806657Snate@binkert.orgtypename Impl::DynInstPtr 3816657Snate@binkert.orgLSQUnit<Impl>::getMemDepViolator() 3826657Snate@binkert.org{ 3836657Snate@binkert.org DynInstPtr temp = memDepViolator; 3846657Snate@binkert.org 3856657Snate@binkert.org memDepViolator = NULL; 3866657Snate@binkert.org 3877007Snate@binkert.org return temp; 3886657Snate@binkert.org} 3897007Snate@binkert.org 3906657Snate@binkert.orgtemplate <class Impl> 3919298Snilay@cs.wisc.eduunsigned 3929298Snilay@cs.wisc.eduLSQUnit<Impl>::numFreeEntries() 3939298Snilay@cs.wisc.edu{ 3949298Snilay@cs.wisc.edu unsigned free_lq_entries = LQEntries - loads; 3959298Snilay@cs.wisc.edu unsigned free_sq_entries = SQEntries - stores; 3969298Snilay@cs.wisc.edu 3976657Snate@binkert.org // Both the LQ and SQ entries have an extra dummy entry to differentiate 3986657Snate@binkert.org // empty/full conditions. Subtract 1 from the free entries. 3996657Snate@binkert.org if (free_lq_entries < free_sq_entries) { 4006657Snate@binkert.org return free_lq_entries - 1; 4017055Snate@binkert.org } else { 4027007Snate@binkert.org return free_sq_entries - 1; 4036657Snate@binkert.org } 4046657Snate@binkert.org} 4057002Snate@binkert.org 4066657Snate@binkert.orgtemplate <class Impl> 4076657Snate@binkert.orgint 4086657Snate@binkert.orgLSQUnit<Impl>::numLoadsReady() 4097007Snate@binkert.org{ 4106657Snate@binkert.org int load_idx = loadHead; 4116657Snate@binkert.org int retval = 0; 4126657Snate@binkert.org 4136657Snate@binkert.org while (load_idx != loadTail) { 4146657Snate@binkert.org assert(loadQueue[load_idx]); 4156999Snate@binkert.org 4166657Snate@binkert.org if (loadQueue[load_idx]->readyToIssue()) { 4176657Snate@binkert.org ++retval; 4186657Snate@binkert.org } 4196657Snate@binkert.org } 4206657Snate@binkert.org 4216657Snate@binkert.org return retval; 4226657Snate@binkert.org} 4237002Snate@binkert.org 4247002Snate@binkert.orgtemplate <class Impl> 4256657Snate@binkert.orgFault 4269499Snilay@cs.wisc.eduLSQUnit<Impl>::executeLoad(DynInstPtr &inst) 4279499Snilay@cs.wisc.edu{ 4287002Snate@binkert.org // Execute a specific load. 4297002Snate@binkert.org Fault load_fault = NoFault; 4306657Snate@binkert.org 4316657Snate@binkert.org DPRINTF(LSQUnit, "Executing load PC %#x, [sn:%lli]\n", 4326657Snate@binkert.org inst->readPC(),inst->seqNum); 4336657Snate@binkert.org 4347007Snate@binkert.org// load_fault = inst->initiateAcc(); 4357007Snate@binkert.org load_fault = inst->execute(); 4366657Snate@binkert.org 4376657Snate@binkert.org // If the instruction faulted, then we need to send it along to commit 4386657Snate@binkert.org // without the instruction completing. 4396657Snate@binkert.org if (load_fault != NoFault) { 4406657Snate@binkert.org // Send this instruction to commit, also make sure iew stage 4416657Snate@binkert.org // realizes there is activity. 4426657Snate@binkert.org iewStage->instToCommit(inst); 4436657Snate@binkert.org iewStage->activityThisCycle(); 4446657Snate@binkert.org } 4456657Snate@binkert.org 4469206Snilay@cs.wisc.edu return load_fault; 4476657Snate@binkert.org} 4486657Snate@binkert.org 4496657Snate@binkert.orgtemplate <class Impl> 4506657Snate@binkert.orgFault 4516657Snate@binkert.orgLSQUnit<Impl>::executeStore(DynInstPtr &store_inst) 4526657Snate@binkert.org{ 4536657Snate@binkert.org using namespace TheISA; 4549298Snilay@cs.wisc.edu // Make sure that a store exists. 4559298Snilay@cs.wisc.edu assert(stores != 0); 4569298Snilay@cs.wisc.edu 4579298Snilay@cs.wisc.edu int store_idx = store_inst->sqIdx; 4586657Snate@binkert.org 4596657Snate@binkert.org DPRINTF(LSQUnit, "Executing store PC %#x [sn:%lli]\n", 4606657Snate@binkert.org store_inst->readPC(), store_inst->seqNum); 4616999Snate@binkert.org 4626657Snate@binkert.org // Check the recently completed loads to see if any match this store's 4636657Snate@binkert.org // address. If so, then we have a memory ordering violation. 4646657Snate@binkert.org int load_idx = store_inst->lqIdx; 4656657Snate@binkert.org 4666657Snate@binkert.org Fault store_fault = store_inst->initiateAcc(); 4677007Snate@binkert.org// Fault store_fault = store_inst->execute(); 4687007Snate@binkert.org 4697007Snate@binkert.org if (storeQueue[store_idx].size == 0) { 4706657Snate@binkert.org DPRINTF(LSQUnit,"Fault on Store PC %#x, [sn:%lli],Size = 0\n", 4717002Snate@binkert.org store_inst->readPC(),store_inst->seqNum); 4727002Snate@binkert.org 4737002Snate@binkert.org return store_fault; 4748086SBrad.Beckmann@amd.com } 4758086SBrad.Beckmann@amd.com 4768086SBrad.Beckmann@amd.com assert(store_fault == NoFault); 4778086SBrad.Beckmann@amd.com 4788602Snilay@cs.wisc.edu if (store_inst->isStoreConditional()) { 4798602Snilay@cs.wisc.edu // Store conditionals need to set themselves as able to 4808602Snilay@cs.wisc.edu // writeback if we haven't had a fault by here. 4818602Snilay@cs.wisc.edu storeQueue[store_idx].canWB = true; 4828602Snilay@cs.wisc.edu 4838602Snilay@cs.wisc.edu ++storesToWB; 4848086SBrad.Beckmann@amd.com } 4856657Snate@binkert.org 4867007Snate@binkert.org if (!memDepViolator) { 4876657Snate@binkert.org while (load_idx != loadTail) { 4886657Snate@binkert.org // Really only need to check loads that have actually executed 4896657Snate@binkert.org // It's safe to check all loads because effAddr is set to 4906657Snate@binkert.org // InvalAddr when the dyn inst is created. 4916657Snate@binkert.org 4926657Snate@binkert.org // @todo: For now this is extra conservative, detecting a 4936657Snate@binkert.org // violation if the addresses match assuming all accesses 4946657Snate@binkert.org // are quad word accesses. 4956657Snate@binkert.org 4966657Snate@binkert.org // @todo: Fix this, magic number being used here 4976657Snate@binkert.org if ((loadQueue[load_idx]->effAddr >> 8) == 4986862Sdrh5@cs.wisc.edu (store_inst->effAddr >> 8)) { 4996862Sdrh5@cs.wisc.edu // A load incorrectly passed this store. Squash and refetch. 5006862Sdrh5@cs.wisc.edu // For now return a fault to show that it was unsuccessful. 5016862Sdrh5@cs.wisc.edu memDepViolator = loadQueue[load_idx]; 5026657Snate@binkert.org ++lsqMemOrderViolation; 5036657Snate@binkert.org 5046657Snate@binkert.org return genMachineCheckFault(); 5056657Snate@binkert.org } 5066657Snate@binkert.org 5077007Snate@binkert.org incrLdIdx(load_idx); 5087007Snate@binkert.org } 5097002Snate@binkert.org 5107007Snate@binkert.org // If we've reached this point, there was no violation. 5117007Snate@binkert.org memDepViolator = NULL; 5127002Snate@binkert.org } 5137007Snate@binkert.org 5147007Snate@binkert.org return store_fault; 5156657Snate@binkert.org} 5166657Snate@binkert.org 5176657Snate@binkert.orgtemplate <class Impl> 5186657Snate@binkert.orgvoid 5196657Snate@binkert.orgLSQUnit<Impl>::commitLoad() 5206657Snate@binkert.org{ 5216657Snate@binkert.org assert(loadQueue[loadHead]); 5226657Snate@binkert.org 5236657Snate@binkert.org DPRINTF(LSQUnit, "Committing head load instruction, PC %#x\n", 5246657Snate@binkert.org loadQueue[loadHead]->readPC()); 5256657Snate@binkert.org 5266657Snate@binkert.org loadQueue[loadHead] = NULL; 5276657Snate@binkert.org 5288602Snilay@cs.wisc.edu incrLdIdx(loadHead); 5298602Snilay@cs.wisc.edu 5308602Snilay@cs.wisc.edu --loads; 5318602Snilay@cs.wisc.edu} 5328602Snilay@cs.wisc.edu 5338602Snilay@cs.wisc.edutemplate <class Impl> 5348602Snilay@cs.wisc.eduvoid 5358602Snilay@cs.wisc.eduLSQUnit<Impl>::commitLoads(InstSeqNum &youngest_inst) 5368602Snilay@cs.wisc.edu{ 5378602Snilay@cs.wisc.edu assert(loads == 0 || loadQueue[loadHead]); 5388602Snilay@cs.wisc.edu 5398602Snilay@cs.wisc.edu while (loads != 0 && loadQueue[loadHead]->seqNum <= youngest_inst) { 5408602Snilay@cs.wisc.edu commitLoad(); 5418602Snilay@cs.wisc.edu } 5428602Snilay@cs.wisc.edu} 5438602Snilay@cs.wisc.edu 5448602Snilay@cs.wisc.edutemplate <class Impl> 5458602Snilay@cs.wisc.eduvoid 5468602Snilay@cs.wisc.eduLSQUnit<Impl>::commitStores(InstSeqNum &youngest_inst) 5478602Snilay@cs.wisc.edu{ 5488602Snilay@cs.wisc.edu assert(stores == 0 || storeQueue[storeHead].inst); 5498602Snilay@cs.wisc.edu 5508602Snilay@cs.wisc.edu int store_idx = storeHead; 5516657Snate@binkert.org 5528086SBrad.Beckmann@amd.com while (store_idx != storeTail) { 5538086SBrad.Beckmann@amd.com assert(storeQueue[store_idx].inst); 5548086SBrad.Beckmann@amd.com // Mark any stores that are now committed and have not yet 5558086SBrad.Beckmann@amd.com // been marked as able to write back. 5568086SBrad.Beckmann@amd.com if (!storeQueue[store_idx].canWB) { 5578086SBrad.Beckmann@amd.com if (storeQueue[store_idx].inst->seqNum > youngest_inst) { 5588086SBrad.Beckmann@amd.com break; 5598086SBrad.Beckmann@amd.com } 5606657Snate@binkert.org DPRINTF(LSQUnit, "Marking store as able to write back, PC " 5616657Snate@binkert.org "%#x [sn:%lli]\n", 5627002Snate@binkert.org storeQueue[store_idx].inst->readPC(), 5636657Snate@binkert.org storeQueue[store_idx].inst->seqNum); 5647007Snate@binkert.org 5656657Snate@binkert.org storeQueue[store_idx].canWB = true; 5666657Snate@binkert.org 5676657Snate@binkert.org ++storesToWB; 5686657Snate@binkert.org } 5696657Snate@binkert.org 5706999Snate@binkert.org incrStIdx(store_idx); 5716657Snate@binkert.org } 5726657Snate@binkert.org} 5736657Snate@binkert.org 5746657Snate@binkert.orgtemplate <class Impl> 5756657Snate@binkert.orgvoid 5766657Snate@binkert.orgLSQUnit<Impl>::writebackStores() 5777832Snate@binkert.org{ 5787002Snate@binkert.org while (storesToWB > 0 && 5797002Snate@binkert.org storeWBIdx != storeTail && 5807002Snate@binkert.org storeQueue[storeWBIdx].inst && 5817805Snilay@cs.wisc.edu storeQueue[storeWBIdx].canWB && 5826657Snate@binkert.org usedPorts < cachePorts) { 5836657Snate@binkert.org 5847002Snate@binkert.org // Store didn't write any data so no need to write it back to 5857002Snate@binkert.org // memory. 5866657Snate@binkert.org if (storeQueue[storeWBIdx].size == 0) { 5876657Snate@binkert.org completeStore(storeWBIdx); 5888086SBrad.Beckmann@amd.com 5898086SBrad.Beckmann@amd.com incrStIdx(storeWBIdx); 5908086SBrad.Beckmann@amd.com 5918086SBrad.Beckmann@amd.com continue; 5928086SBrad.Beckmann@amd.com } 5938086SBrad.Beckmann@amd.com 5948086SBrad.Beckmann@amd.com if (dcacheInterface && dcacheInterface->isBlocked()) { 5958086SBrad.Beckmann@amd.com DPRINTF(LSQUnit, "Unable to write back any more stores, cache" 5968086SBrad.Beckmann@amd.com " is blocked!\n"); 5978086SBrad.Beckmann@amd.com ++lsqCacheBlocked; 5988086SBrad.Beckmann@amd.com break; 5998086SBrad.Beckmann@amd.com } 6008086SBrad.Beckmann@amd.com 6018086SBrad.Beckmann@amd.com ++usedPorts; 6028086SBrad.Beckmann@amd.com 6038086SBrad.Beckmann@amd.com if (storeQueue[storeWBIdx].inst->isDataPrefetch()) { 6048086SBrad.Beckmann@amd.com incrStIdx(storeWBIdx); 6058086SBrad.Beckmann@amd.com 6068086SBrad.Beckmann@amd.com continue; 6078086SBrad.Beckmann@amd.com } 6088086SBrad.Beckmann@amd.com 6096657Snate@binkert.org assert(storeQueue[storeWBIdx].req); 6106657Snate@binkert.org assert(!storeQueue[storeWBIdx].committed); 6116657Snate@binkert.org 6128602Snilay@cs.wisc.edu MemReqPtr req = storeQueue[storeWBIdx].req; 6136657Snate@binkert.org storeQueue[storeWBIdx].committed = true; 6146657Snate@binkert.org 6157007Snate@binkert.org req->cmd = Write; 6167007Snate@binkert.org req->completionEvent = NULL; 6177007Snate@binkert.org req->time = curTick; 6186657Snate@binkert.org assert(!req->data); 6196657Snate@binkert.org req->data = new uint8_t[64]; 6206657Snate@binkert.org memcpy(req->data, (uint8_t *)&storeQueue[storeWBIdx].data, req->size); 6216657Snate@binkert.org 6226657Snate@binkert.org DPRINTF(LSQUnit, "D-Cache: Writing back store idx:%i PC:%#x " 6236657Snate@binkert.org "to Addr:%#x, data:%#x [sn:%lli]\n", 6247007Snate@binkert.org storeWBIdx,storeQueue[storeWBIdx].inst->readPC(), 6257007Snate@binkert.org req->paddr, *(req->data), 6267007Snate@binkert.org storeQueue[storeWBIdx].inst->seqNum); 6276657Snate@binkert.org 6286657Snate@binkert.org switch(storeQueue[storeWBIdx].size) { 6296657Snate@binkert.org case 1: 6306657Snate@binkert.org cpu->write(req, (uint8_t &)storeQueue[storeWBIdx].data); 6316657Snate@binkert.org break; 6326657Snate@binkert.org case 2: 6336657Snate@binkert.org cpu->write(req, (uint16_t &)storeQueue[storeWBIdx].data); 6346657Snate@binkert.org break; 6356657Snate@binkert.org case 4: 6366657Snate@binkert.org cpu->write(req, (uint32_t &)storeQueue[storeWBIdx].data); 6376657Snate@binkert.org break; 6386657Snate@binkert.org case 8: 6396657Snate@binkert.org cpu->write(req, (uint64_t &)storeQueue[storeWBIdx].data); 6406657Snate@binkert.org break; 6417805Snilay@cs.wisc.edu default: 6426657Snate@binkert.org panic("Unexpected store size!\n"); 6436657Snate@binkert.org } 6446657Snate@binkert.org 6457007Snate@binkert.org // Stores other than store conditionals are completed at this 6467007Snate@binkert.org // time. Mark them as completed and, if we have a checker, 6477007Snate@binkert.org // tell it that the instruction is completed. 6486657Snate@binkert.org // @todo: Figure out what time I can say stores are complete in 6496657Snate@binkert.org // the timing memory. 6506657Snate@binkert.org if (!(req->flags & LOCKED)) { 6516657Snate@binkert.org storeQueue[storeWBIdx].inst->setCompleted(); 6527007Snate@binkert.org if (cpu->checker) { 6536657Snate@binkert.org cpu->checker->tick(storeQueue[storeWBIdx].inst); 6546657Snate@binkert.org } 6556657Snate@binkert.org } 6566657Snate@binkert.org 6577007Snate@binkert.org if (dcacheInterface) { 6586657Snate@binkert.org assert(!req->completionEvent); 6596657Snate@binkert.org StoreCompletionEvent *store_event = new 6606657Snate@binkert.org StoreCompletionEvent(storeWBIdx, NULL, this); 6616657Snate@binkert.org req->completionEvent = store_event; 6627805Snilay@cs.wisc.edu 6636657Snate@binkert.org MemAccessResult result = dcacheInterface->access(req); 6646657Snate@binkert.org 6656657Snate@binkert.org if (isStalled() && 6667007Snate@binkert.org storeQueue[storeWBIdx].inst->seqNum == stallingStoreIsn) { 6677007Snate@binkert.org DPRINTF(LSQUnit, "Unstalling, stalling store [sn:%lli] " 6687007Snate@binkert.org "load idx:%i\n", 6697007Snate@binkert.org stallingStoreIsn, stallingLoadIdx); 6706657Snate@binkert.org stalled = false; 6716657Snate@binkert.org stallingStoreIsn = 0; 6726657Snate@binkert.org iewStage->replayMemInst(loadQueue[stallingLoadIdx]); 6736657Snate@binkert.org } 6746657Snate@binkert.org 6756657Snate@binkert.org typename IEW::LdWritebackEvent *wb = NULL; 6766657Snate@binkert.org if (req->flags & LOCKED) { 6776657Snate@binkert.org // Stx_C should not generate a system port transaction 6786657Snate@binkert.org // if it misses in the cache, but that might be hard 6797007Snate@binkert.org // to accomplish without explicit cache support. 6807007Snate@binkert.org wb = new typename 6816657Snate@binkert.org IEW::LdWritebackEvent(storeQueue[storeWBIdx].inst, 6826657Snate@binkert.org iewStage); 6836657Snate@binkert.org store_event->wbEvent = wb; 6846657Snate@binkert.org } 6857007Snate@binkert.org 6867007Snate@binkert.org if (result != MA_HIT && dcacheInterface->doEvents()) { 6876657Snate@binkert.org DPRINTF(LSQUnit,"D-Cache Write Miss on idx:%i!\n", 6886657Snate@binkert.org storeWBIdx); 6896657Snate@binkert.org 6906657Snate@binkert.org DPRINTF(Activity, "Active st accessing mem miss [sn:%lli]\n", 6916657Snate@binkert.org storeQueue[storeWBIdx].inst->seqNum); 6926657Snate@binkert.org 6936657Snate@binkert.org //mshrSeqNums.push_back(storeQueue[storeWBIdx].inst->seqNum); 6946657Snate@binkert.org 6956657Snate@binkert.org //DPRINTF(LSQUnit, "Added MSHR. count = %i\n",mshrSeqNums.size()); 6966657Snate@binkert.org 6976657Snate@binkert.org // @todo: Increment stat here. 6986657Snate@binkert.org } else { 6996657Snate@binkert.org DPRINTF(LSQUnit,"D-Cache: Write Hit on idx:%i !\n", 7006657Snate@binkert.org storeWBIdx); 7016657Snate@binkert.org 7026657Snate@binkert.org DPRINTF(Activity, "Active st accessing mem hit [sn:%lli]\n", 7036657Snate@binkert.org storeQueue[storeWBIdx].inst->seqNum); 7047805Snilay@cs.wisc.edu } 7056657Snate@binkert.org 7066657Snate@binkert.org incrStIdx(storeWBIdx); 7076657Snate@binkert.org } else { 7086657Snate@binkert.org panic("Must HAVE DCACHE!!!!!\n"); 7096657Snate@binkert.org } 7107007Snate@binkert.org } 7116657Snate@binkert.org 7127007Snate@binkert.org // Not sure this should set it to 0. 7137007Snate@binkert.org usedPorts = 0; 7146657Snate@binkert.org 7156657Snate@binkert.org assert(stores >= 0 && storesToWB >= 0); 7166657Snate@binkert.org} 7176657Snate@binkert.org 7186657Snate@binkert.org/*template <class Impl> 7196657Snate@binkert.orgvoid 7206657Snate@binkert.orgLSQUnit<Impl>::removeMSHR(InstSeqNum seqNum) 7216657Snate@binkert.org{ 7226657Snate@binkert.org list<InstSeqNum>::iterator mshr_it = find(mshrSeqNums.begin(), 7236657Snate@binkert.org mshrSeqNums.end(), 7246657Snate@binkert.org seqNum); 7256657Snate@binkert.org 7266657Snate@binkert.org if (mshr_it != mshrSeqNums.end()) { 7276657Snate@binkert.org mshrSeqNums.erase(mshr_it); 7287805Snilay@cs.wisc.edu DPRINTF(LSQUnit, "Removing MSHR. count = %i\n",mshrSeqNums.size()); 7296657Snate@binkert.org } 7306657Snate@binkert.org}*/ 7316657Snate@binkert.org 7326657Snate@binkert.orgtemplate <class Impl> 7336657Snate@binkert.orgvoid 7346657Snate@binkert.orgLSQUnit<Impl>::squash(const InstSeqNum &squashed_num) 7356657Snate@binkert.org{ 7366657Snate@binkert.org DPRINTF(LSQUnit, "Squashing until [sn:%lli]!" 7377007Snate@binkert.org "(Loads:%i Stores:%i)\n", squashed_num, loads, stores); 7387007Snate@binkert.org 7396657Snate@binkert.org int load_idx = loadTail; 7406657Snate@binkert.org decrLdIdx(load_idx); 7416657Snate@binkert.org 7426657Snate@binkert.org while (loads != 0 && loadQueue[load_idx]->seqNum > squashed_num) { 7436657Snate@binkert.org DPRINTF(LSQUnit,"Load Instruction PC %#x squashed, " 7446657Snate@binkert.org "[sn:%lli]\n", 7456657Snate@binkert.org loadQueue[load_idx]->readPC(), 7466657Snate@binkert.org loadQueue[load_idx]->seqNum); 7476657Snate@binkert.org 7486657Snate@binkert.org if (isStalled() && load_idx == stallingLoadIdx) { 7496657Snate@binkert.org stalled = false; 7506657Snate@binkert.org stallingStoreIsn = 0; 7516657Snate@binkert.org stallingLoadIdx = 0; 7526657Snate@binkert.org } 7536657Snate@binkert.org 7546657Snate@binkert.org // Clear the smart pointer to make sure it is decremented. 7557805Snilay@cs.wisc.edu loadQueue[load_idx]->setSquashed(); 7566657Snate@binkert.org loadQueue[load_idx] = NULL; 7576657Snate@binkert.org --loads; 7586657Snate@binkert.org 7596657Snate@binkert.org // Inefficient! 7606657Snate@binkert.org loadTail = load_idx; 7616657Snate@binkert.org 7626657Snate@binkert.org decrLdIdx(load_idx); 7636657Snate@binkert.org } 7647007Snate@binkert.org 7657007Snate@binkert.org if (isLoadBlocked) { 7666657Snate@binkert.org if (squashed_num < blockedLoadSeqNum) { 7676657Snate@binkert.org isLoadBlocked = false; 7686657Snate@binkert.org loadBlockedHandled = false; 7696657Snate@binkert.org blockedLoadSeqNum = 0; 7706657Snate@binkert.org } 7716657Snate@binkert.org } 7726657Snate@binkert.org 7736657Snate@binkert.org int store_idx = storeTail; 7746657Snate@binkert.org decrStIdx(store_idx); 7756657Snate@binkert.org 7766657Snate@binkert.org while (stores != 0 && 7776657Snate@binkert.org storeQueue[store_idx].inst->seqNum > squashed_num) { 7786657Snate@binkert.org // Instructions marked as can WB are already committed. 7796657Snate@binkert.org if (storeQueue[store_idx].canWB) { 7806657Snate@binkert.org break; 7817805Snilay@cs.wisc.edu } 7826657Snate@binkert.org 7836657Snate@binkert.org DPRINTF(LSQUnit,"Store Instruction PC %#x squashed, " 7846657Snate@binkert.org "idx:%i [sn:%lli]\n", 7856657Snate@binkert.org storeQueue[store_idx].inst->readPC(), 7868602Snilay@cs.wisc.edu store_idx, storeQueue[store_idx].inst->seqNum); 7878602Snilay@cs.wisc.edu 7888602Snilay@cs.wisc.edu // I don't think this can happen. It should have been cleared 7898602Snilay@cs.wisc.edu // by the stalling load. 7908602Snilay@cs.wisc.edu if (isStalled() && 7918602Snilay@cs.wisc.edu storeQueue[store_idx].inst->seqNum == stallingStoreIsn) { 7928602Snilay@cs.wisc.edu panic("Is stalled should have been cleared by stalling load!\n"); 7938602Snilay@cs.wisc.edu stalled = false; 7948602Snilay@cs.wisc.edu stallingStoreIsn = 0; 7958602Snilay@cs.wisc.edu } 7968602Snilay@cs.wisc.edu 7978602Snilay@cs.wisc.edu // Clear the smart pointer to make sure it is decremented. 7988602Snilay@cs.wisc.edu storeQueue[store_idx].inst->setSquashed(); 7998602Snilay@cs.wisc.edu storeQueue[store_idx].inst = NULL; 8008602Snilay@cs.wisc.edu storeQueue[store_idx].canWB = 0; 8018602Snilay@cs.wisc.edu 8028602Snilay@cs.wisc.edu if (storeQueue[store_idx].req) { 8038602Snilay@cs.wisc.edu // There should not be a completion event if the store has 8048602Snilay@cs.wisc.edu // not yet committed. 8058602Snilay@cs.wisc.edu assert(!storeQueue[store_idx].req->completionEvent); 8068602Snilay@cs.wisc.edu } 8076657Snate@binkert.org 8086657Snate@binkert.org storeQueue[store_idx].req = NULL; 8096657Snate@binkert.org --stores; 8106657Snate@binkert.org 811 // Inefficient! 812 storeTail = store_idx; 813 814 decrStIdx(store_idx); 815 ++lsqSquashedStores; 816 } 817} 818 819template <class Impl> 820void 821LSQUnit<Impl>::completeStore(int store_idx) 822{ 823 assert(storeQueue[store_idx].inst); 824 storeQueue[store_idx].completed = true; 825 --storesToWB; 826 // A bit conservative because a store completion may not free up entries, 827 // but hopefully avoids two store completions in one cycle from making 828 // the CPU tick twice. 829 cpu->activityThisCycle(); 830 831 if (store_idx == storeHead) { 832 do { 833 incrStIdx(storeHead); 834 835 --stores; 836 } while (storeQueue[storeHead].completed && 837 storeHead != storeTail); 838 839 iewStage->updateLSQNextCycle = true; 840 } 841 842 DPRINTF(LSQUnit, "Completing store [sn:%lli], idx:%i, store head " 843 "idx:%i\n", 844 storeQueue[store_idx].inst->seqNum, store_idx, storeHead); 845 846 if (isStalled() && 847 storeQueue[store_idx].inst->seqNum == stallingStoreIsn) { 848 DPRINTF(LSQUnit, "Unstalling, stalling store [sn:%lli] " 849 "load idx:%i\n", 850 stallingStoreIsn, stallingLoadIdx); 851 stalled = false; 852 stallingStoreIsn = 0; 853 iewStage->replayMemInst(loadQueue[stallingLoadIdx]); 854 } 855 856 storeQueue[store_idx].inst->setCompleted(); 857 858 // Tell the checker we've completed this instruction. Some stores 859 // may get reported twice to the checker, but the checker can 860 // handle that case. 861 if (cpu->checker) { 862 cpu->checker->tick(storeQueue[store_idx].inst); 863 } 864} 865 866template <class Impl> 867inline void 868LSQUnit<Impl>::incrStIdx(int &store_idx) 869{ 870 if (++store_idx >= SQEntries) 871 store_idx = 0; 872} 873 874template <class Impl> 875inline void 876LSQUnit<Impl>::decrStIdx(int &store_idx) 877{ 878 if (--store_idx < 0) 879 store_idx += SQEntries; 880} 881 882template <class Impl> 883inline void 884LSQUnit<Impl>::incrLdIdx(int &load_idx) 885{ 886 if (++load_idx >= LQEntries) 887 load_idx = 0; 888} 889 890template <class Impl> 891inline void 892LSQUnit<Impl>::decrLdIdx(int &load_idx) 893{ 894 if (--load_idx < 0) 895 load_idx += LQEntries; 896} 897 898template <class Impl> 899void 900LSQUnit<Impl>::dumpInsts() 901{ 902 cprintf("Load store queue: Dumping instructions.\n"); 903 cprintf("Load queue size: %i\n", loads); 904 cprintf("Load queue: "); 905 906 int load_idx = loadHead; 907 908 while (load_idx != loadTail && loadQueue[load_idx]) { 909 cprintf("%#x ", loadQueue[load_idx]->readPC()); 910 911 incrLdIdx(load_idx); 912 } 913 914 cprintf("Store queue size: %i\n", stores); 915 cprintf("Store queue: "); 916 917 int store_idx = storeHead; 918 919 while (store_idx != storeTail && storeQueue[store_idx].inst) { 920 cprintf("%#x ", storeQueue[store_idx].inst->readPC()); 921 922 incrStIdx(store_idx); 923 } 924 925 cprintf("\n"); 926} 927