lsq_unit_impl.hh revision 2329
19793Sakash.bagdia@arm.com/* 27586SAli.Saidi@arm.com * Copyright (c) 2004-2005 The Regents of The University of Michigan 37586SAli.Saidi@arm.com * All rights reserved. 47586SAli.Saidi@arm.com * 57586SAli.Saidi@arm.com * Redistribution and use in source and binary forms, with or without 67586SAli.Saidi@arm.com * modification, are permitted provided that the following conditions are 77586SAli.Saidi@arm.com * met: redistributions of source code must retain the above copyright 87586SAli.Saidi@arm.com * notice, this list of conditions and the following disclaimer; 97586SAli.Saidi@arm.com * redistributions in binary form must reproduce the above copyright 107586SAli.Saidi@arm.com * notice, this list of conditions and the following disclaimer in the 117586SAli.Saidi@arm.com * documentation and/or other materials provided with the distribution; 127586SAli.Saidi@arm.com * neither the name of the copyright holders nor the names of its 1310118Snilay@cs.wisc.edu * contributors may be used to endorse or promote products derived from 1410118Snilay@cs.wisc.edu * this software without specific prior written permission. 153970Sgblack@eecs.umich.edu * 163005Sstever@eecs.umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 173005Sstever@eecs.umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 183005Sstever@eecs.umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 193005Sstever@eecs.umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 203005Sstever@eecs.umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 213005Sstever@eecs.umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 223005Sstever@eecs.umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 233005Sstever@eecs.umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 243005Sstever@eecs.umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 253005Sstever@eecs.umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 263005Sstever@eecs.umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 273005Sstever@eecs.umich.edu */ 283005Sstever@eecs.umich.edu 293005Sstever@eecs.umich.edu#include "cpu/checker/cpu.hh" 303005Sstever@eecs.umich.edu#include "cpu/o3/lsq_unit.hh" 313005Sstever@eecs.umich.edu#include "base/str.hh" 323005Sstever@eecs.umich.edu 333005Sstever@eecs.umich.edutemplate <class Impl> 343005Sstever@eecs.umich.eduLSQUnit<Impl>::StoreCompletionEvent::StoreCompletionEvent(int store_idx, 353005Sstever@eecs.umich.edu Event *wb_event, 363005Sstever@eecs.umich.edu LSQUnit<Impl> *lsq_ptr) 373005Sstever@eecs.umich.edu : Event(&mainEventQueue), 383005Sstever@eecs.umich.edu wbEvent(wb_event), 393005Sstever@eecs.umich.edu storeIdx(store_idx), 403005Sstever@eecs.umich.edu lsqPtr(lsq_ptr) 413005Sstever@eecs.umich.edu{ 4210118Snilay@cs.wisc.edu this->setFlags(Event::AutoDelete); 433005Sstever@eecs.umich.edu} 446654Snate@binkert.org 456654Snate@binkert.orgtemplate <class Impl> 462889SN/Avoid 472710SN/ALSQUnit<Impl>::StoreCompletionEvent::process() 486654Snate@binkert.org{ 496654Snate@binkert.org DPRINTF(LSQ, "Cache miss complete for store idx:%i\n", storeIdx); 506654Snate@binkert.org DPRINTF(Activity, "Activity: st writeback event idx:%i\n", storeIdx); 515457Ssaidi@eecs.umich.edu 526654Snate@binkert.org //lsqPtr->removeMSHR(lsqPtr->storeQueue[storeIdx].inst->seqNum); 5310118Snilay@cs.wisc.edu 5410118Snilay@cs.wisc.edu if (lsqPtr->isSwitchedOut()) 5510118Snilay@cs.wisc.edu return; 566654Snate@binkert.org 572934SN/A lsqPtr->cpu->wakeCPU(); 582549SN/A if (wbEvent) 592995SN/A wbEvent->process(); 603395Shsul@eecs.umich.edu lsqPtr->completeStore(storeIdx); 616981SLisa.Hsu@amd.com} 629836Sandreas.hansson@arm.com 633448Shsul@eecs.umich.edutemplate <class Impl> 648920Snilay@cs.wisc.educonst char * 653444Sktlim@umich.eduLSQUnit<Impl>::StoreCompletionEvent::description() 663304Sstever@eecs.umich.edu{ 679653SAndreas.Sandberg@ARM.com return "LSQ store completion event"; 689653SAndreas.Sandberg@ARM.com} 699653SAndreas.Sandberg@ARM.com 709653SAndreas.Sandberg@ARM.comtemplate <class Impl> 719653SAndreas.Sandberg@ARM.comLSQUnit<Impl>::LSQUnit() 729653SAndreas.Sandberg@ARM.com : loads(0), stores(0), storesToWB(0), stalled(false), isLoadBlocked(false), 739653SAndreas.Sandberg@ARM.com loadBlockedHandled(false) 7410594Sgabeblack@google.com{ 7510594Sgabeblack@google.com} 7610594Sgabeblack@google.com 7710594Sgabeblack@google.comtemplate<class Impl> 7810594Sgabeblack@google.comvoid 7910594Sgabeblack@google.comLSQUnit<Impl>::init(Params *params, unsigned maxLQEntries, 8010594Sgabeblack@google.com unsigned maxSQEntries, unsigned id) 8110594Sgabeblack@google.com 8210594Sgabeblack@google.com{ 8310594Sgabeblack@google.com DPRINTF(LSQUnit, "Creating LSQUnit%i object.\n",id); 8410594Sgabeblack@google.com 8510119Snilay@cs.wisc.edu switchedOut = false; 8610594Sgabeblack@google.com 8710119Snilay@cs.wisc.edu lsqID = id; 8810594Sgabeblack@google.com 8910594Sgabeblack@google.com // Add 1 for the sentinel entry (they are circular queues). 9010119Snilay@cs.wisc.edu LQEntries = maxLQEntries + 1; 9110594Sgabeblack@google.com SQEntries = maxSQEntries + 1; 9210119Snilay@cs.wisc.edu 9310594Sgabeblack@google.com loadQueue.resize(LQEntries); 9410119Snilay@cs.wisc.edu storeQueue.resize(SQEntries); 9510119Snilay@cs.wisc.edu 9610594Sgabeblack@google.com loadHead = loadTail = 0; 9710119Snilay@cs.wisc.edu 9810512SAli.Saidi@ARM.com storeHead = storeWBIdx = storeTail = 0; 9910512SAli.Saidi@ARM.com 10010594Sgabeblack@google.com usedPorts = 0; 10110780SCurtis.Dunham@arm.com cachePorts = params->cachePorts; 10210780SCurtis.Dunham@arm.com 10310119Snilay@cs.wisc.edu dcacheInterface = params->dcacheInterface; 10410119Snilay@cs.wisc.edu 10510119Snilay@cs.wisc.edu memDepViolator = NULL; 10610119Snilay@cs.wisc.edu 1072566SN/A blockedLoadSeqNum = 0; 10810119Snilay@cs.wisc.edu} 10910119Snilay@cs.wisc.edu 1109665Sandreas.hansson@arm.comtemplate<class Impl> 11110119Snilay@cs.wisc.edustd::string 11210119Snilay@cs.wisc.eduLSQUnit<Impl>::name() const 11310119Snilay@cs.wisc.edu{ 11410119Snilay@cs.wisc.edu if (Impl::MaxThreads == 1) { 11510119Snilay@cs.wisc.edu return iewStage->name() + ".lsq"; 11610119Snilay@cs.wisc.edu } else { 11710119Snilay@cs.wisc.edu return iewStage->name() + ".lsq.thread." + to_string(lsqID); 11810119Snilay@cs.wisc.edu } 11910119Snilay@cs.wisc.edu} 12010119Snilay@cs.wisc.edu 12110119Snilay@cs.wisc.edutemplate<class Impl> 12210119Snilay@cs.wisc.eduvoid 12310119Snilay@cs.wisc.eduLSQUnit<Impl>::clearLQ() 12410119Snilay@cs.wisc.edu{ 12510119Snilay@cs.wisc.edu loadQueue.clear(); 12610119Snilay@cs.wisc.edu} 12710119Snilay@cs.wisc.edu 12810119Snilay@cs.wisc.edutemplate<class Impl> 12910119Snilay@cs.wisc.eduvoid 13010119Snilay@cs.wisc.eduLSQUnit<Impl>::clearSQ() 13110119Snilay@cs.wisc.edu{ 13210119Snilay@cs.wisc.edu storeQueue.clear(); 13310119Snilay@cs.wisc.edu} 13410119Snilay@cs.wisc.edu 13510119Snilay@cs.wisc.edu#if 0 13610119Snilay@cs.wisc.edutemplate<class Impl> 13710119Snilay@cs.wisc.eduvoid 13810119Snilay@cs.wisc.eduLSQUnit<Impl>::setPageTable(PageTable *pt_ptr) 13910119Snilay@cs.wisc.edu{ 14010119Snilay@cs.wisc.edu DPRINTF(LSQUnit, "Setting the page table pointer.\n"); 14110119Snilay@cs.wisc.edu pTable = pt_ptr; 14210119Snilay@cs.wisc.edu} 14310119Snilay@cs.wisc.edu#endif 14410119Snilay@cs.wisc.edu 14510119Snilay@cs.wisc.edutemplate<class Impl> 14610119Snilay@cs.wisc.eduvoid 14710119Snilay@cs.wisc.eduLSQUnit<Impl>::switchOut() 14810119Snilay@cs.wisc.edu{ 14910119Snilay@cs.wisc.edu switchedOut = true; 15010119Snilay@cs.wisc.edu for (int i = 0; i < loadQueue.size(); ++i) 15110119Snilay@cs.wisc.edu loadQueue[i] = NULL; 15210119Snilay@cs.wisc.edu 15310519Snilay@cs.wisc.edu assert(storesToWB == 0); 15410519Snilay@cs.wisc.edu 15510119Snilay@cs.wisc.edu while (storesToWB > 0 && 15610119Snilay@cs.wisc.edu storeWBIdx != storeTail && 15710119Snilay@cs.wisc.edu storeQueue[storeWBIdx].inst && 15810119Snilay@cs.wisc.edu storeQueue[storeWBIdx].canWB) { 15910119Snilay@cs.wisc.edu 16010547Snilay@cs.wisc.edu if (storeQueue[storeWBIdx].size == 0 || 16110547Snilay@cs.wisc.edu storeQueue[storeWBIdx].inst->isDataPrefetch() || 16210547Snilay@cs.wisc.edu storeQueue[storeWBIdx].committed || 16310547Snilay@cs.wisc.edu storeQueue[storeWBIdx].req->flags & LOCKED) { 16410119Snilay@cs.wisc.edu incrStIdx(storeWBIdx); 16510119Snilay@cs.wisc.edu 16610119Snilay@cs.wisc.edu continue; 16710119Snilay@cs.wisc.edu } 16810119Snilay@cs.wisc.edu 16910119Snilay@cs.wisc.edu assert(storeQueue[storeWBIdx].req); 17010119Snilay@cs.wisc.edu assert(!storeQueue[storeWBIdx].committed); 17110119Snilay@cs.wisc.edu 17210120Snilay@cs.wisc.edu MemReqPtr req = storeQueue[storeWBIdx].req; 17310120Snilay@cs.wisc.edu storeQueue[storeWBIdx].committed = true; 17410119Snilay@cs.wisc.edu 17510119Snilay@cs.wisc.edu req->cmd = Write; 17610120Snilay@cs.wisc.edu req->completionEvent = NULL; 17710120Snilay@cs.wisc.edu req->time = curTick; 17810119Snilay@cs.wisc.edu assert(!req->data); 17911150Smitch.hayenga@arm.com req->data = new uint8_t[64]; 18011150Smitch.hayenga@arm.com memcpy(req->data, (uint8_t *)&storeQueue[storeWBIdx].data, req->size); 18111150Smitch.hayenga@arm.com 18210119Snilay@cs.wisc.edu DPRINTF(LSQUnit, "D-Cache: Writing back store idx:%i PC:%#x " 1832995SN/A "to Addr:%#x, data:%#x [sn:%lli]\n", 18410119Snilay@cs.wisc.edu storeWBIdx,storeQueue[storeWBIdx].inst->readPC(), 18510119Snilay@cs.wisc.edu req->paddr, *(req->data), 18610119Snilay@cs.wisc.edu storeQueue[storeWBIdx].inst->seqNum); 18710119Snilay@cs.wisc.edu 18810119Snilay@cs.wisc.edu switch(storeQueue[storeWBIdx].size) { 18910780SCurtis.Dunham@arm.com case 1: 19010119Snilay@cs.wisc.edu cpu->write(req, (uint8_t &)storeQueue[storeWBIdx].data); 19110119Snilay@cs.wisc.edu break; 19210119Snilay@cs.wisc.edu case 2: 1933304Sstever@eecs.umich.edu cpu->write(req, (uint16_t &)storeQueue[storeWBIdx].data); 19410119Snilay@cs.wisc.edu break; 19510119Snilay@cs.wisc.edu case 4: 19610119Snilay@cs.wisc.edu cpu->write(req, (uint32_t &)storeQueue[storeWBIdx].data); 19710119Snilay@cs.wisc.edu break; 19810119Snilay@cs.wisc.edu case 8: 19910119Snilay@cs.wisc.edu cpu->write(req, (uint64_t &)storeQueue[storeWBIdx].data); 2006135Sgblack@eecs.umich.edu break; 20110608Sdam.sunwoo@arm.com default: 20210608Sdam.sunwoo@arm.com panic("Unexpected store size!\n"); 20310608Sdam.sunwoo@arm.com } 20410608Sdam.sunwoo@arm.com incrStIdx(storeWBIdx); 20510608Sdam.sunwoo@arm.com } 20610608Sdam.sunwoo@arm.com} 20710608Sdam.sunwoo@arm.com 20810119Snilay@cs.wisc.edutemplate<class Impl> 20910119Snilay@cs.wisc.eduvoid 21010119Snilay@cs.wisc.eduLSQUnit<Impl>::takeOverFrom() 21110608Sdam.sunwoo@arm.com{ 21210608Sdam.sunwoo@arm.com switchedOut = false; 21310119Snilay@cs.wisc.edu loads = stores = storesToWB = 0; 21410119Snilay@cs.wisc.edu 21510119Snilay@cs.wisc.edu loadHead = loadTail = 0; 2163819Shsul@eecs.umich.edu 21711251Sradhika.jagtap@ARM.com storeHead = storeWBIdx = storeTail = 0; 21811251Sradhika.jagtap@ARM.com 21911251Sradhika.jagtap@ARM.com usedPorts = 0; 22011251Sradhika.jagtap@ARM.com 22111251Sradhika.jagtap@ARM.com memDepViolator = NULL; 22211251Sradhika.jagtap@ARM.com 22311251Sradhika.jagtap@ARM.com blockedLoadSeqNum = 0; 22411251Sradhika.jagtap@ARM.com 22511251Sradhika.jagtap@ARM.com stalled = false; 22611251Sradhika.jagtap@ARM.com isLoadBlocked = false; 22711251Sradhika.jagtap@ARM.com loadBlockedHandled = false; 22810119Snilay@cs.wisc.edu} 22911183Serfan.azarkhish@unibo.it 23010119Snilay@cs.wisc.edutemplate<class Impl> 23110118Snilay@cs.wisc.eduvoid 23210119Snilay@cs.wisc.eduLSQUnit<Impl>::resizeLQ(unsigned size) 2339827Sakash.bagdia@arm.com{ 23410119Snilay@cs.wisc.edu unsigned size_plus_sentinel = size + 1; 23510119Snilay@cs.wisc.edu assert(size_plus_sentinel >= LQEntries); 23610119Snilay@cs.wisc.edu 23710119Snilay@cs.wisc.edu if (size_plus_sentinel > LQEntries) { 23810119Snilay@cs.wisc.edu while (size_plus_sentinel > loadQueue.size()) { 23910119Snilay@cs.wisc.edu DynInstPtr dummy; 2409827Sakash.bagdia@arm.com loadQueue.push_back(dummy); 24110594Sgabeblack@google.com LQEntries++; 2426654Snate@binkert.org } 24310594Sgabeblack@google.com } else { 2446654Snate@binkert.org LQEntries = size_plus_sentinel; 24510594Sgabeblack@google.com } 2466654Snate@binkert.org 24710594Sgabeblack@google.com} 2486654Snate@binkert.org 24910594Sgabeblack@google.comtemplate<class Impl> 25010594Sgabeblack@google.comvoid 2517586SAli.Saidi@arm.comLSQUnit<Impl>::resizeSQ(unsigned size) 25210635Satgutier@umich.edu{ 25310635Satgutier@umich.edu unsigned size_plus_sentinel = size + 1; 2548661SAli.Saidi@ARM.com if (size_plus_sentinel > SQEntries) { 2559827Sakash.bagdia@arm.com while (size_plus_sentinel > storeQueue.size()) { 2569827Sakash.bagdia@arm.com SQEntry dummy; 2579827Sakash.bagdia@arm.com storeQueue.push_back(dummy); 2589793Sakash.bagdia@arm.com SQEntries++; 25910119Snilay@cs.wisc.edu } 26010119Snilay@cs.wisc.edu } else { 2619790Sakash.bagdia@arm.com SQEntries = size_plus_sentinel; 2629827Sakash.bagdia@arm.com } 2639827Sakash.bagdia@arm.com} 2649827Sakash.bagdia@arm.com 2659793Sakash.bagdia@arm.comtemplate <class Impl> 2669827Sakash.bagdia@arm.comvoid 2679827Sakash.bagdia@arm.comLSQUnit<Impl>::insert(DynInstPtr &inst) 2689827Sakash.bagdia@arm.com{ 2699793Sakash.bagdia@arm.com assert(inst->isMemRef()); 2709793Sakash.bagdia@arm.com 2719793Sakash.bagdia@arm.com assert(inst->isLoad() || inst->isStore()); 2729384SAndreas.Sandberg@arm.com 2738863Snilay@cs.wisc.edu if (inst->isLoad()) { 2747876Sgblack@eecs.umich.edu insertLoad(inst); 2754968Sacolyte@umich.edu } else { 2768926Sandreas.hansson@arm.com insertStore(inst); 2774837Ssaidi@eecs.umich.edu } 2784837Ssaidi@eecs.umich.edu 2799408Sandreas.hansson@arm.com inst->setInLSQ(); 2809653SAndreas.Sandberg@ARM.com} 2819653SAndreas.Sandberg@ARM.com 2829653SAndreas.Sandberg@ARM.comtemplate <class Impl> 2839164Sandreas.hansson@arm.comvoid 2849408Sandreas.hansson@arm.comLSQUnit<Impl>::insertLoad(DynInstPtr &load_inst) 2858845Sandreas.hansson@arm.com{ 2868845Sandreas.hansson@arm.com assert((loadTail + 1) % LQEntries != loadHead); 2874837Ssaidi@eecs.umich.edu assert(loads < LQEntries); 2889826Sandreas.hansson@arm.com 2899826Sandreas.hansson@arm.com DPRINTF(LSQUnit, "Inserting load PC %#x, idx:%i [sn:%lli]\n", 2909835Sandreas.hansson@arm.com load_inst->readPC(), loadTail, load_inst->seqNum); 2919826Sandreas.hansson@arm.com 2929826Sandreas.hansson@arm.com load_inst->lqIdx = loadTail; 2939826Sandreas.hansson@arm.com 2949826Sandreas.hansson@arm.com if (stores == 0) { 2958659SAli.Saidi@ARM.com load_inst->sqIdx = -1; 29610119Snilay@cs.wisc.edu } else { 29710119Snilay@cs.wisc.edu load_inst->sqIdx = storeTail; 29810119Snilay@cs.wisc.edu } 29910119Snilay@cs.wisc.edu 30010119Snilay@cs.wisc.edu loadQueue[loadTail] = load_inst; 30110119Snilay@cs.wisc.edu 30210119Snilay@cs.wisc.edu incrLdIdx(loadTail); 30310119Snilay@cs.wisc.edu 30410119Snilay@cs.wisc.edu ++loads; 30510119Snilay@cs.wisc.edu} 30610119Snilay@cs.wisc.edu 30710119Snilay@cs.wisc.edutemplate <class Impl> 30810119Snilay@cs.wisc.eduvoid 30910119Snilay@cs.wisc.eduLSQUnit<Impl>::insertStore(DynInstPtr &store_inst) 31010119Snilay@cs.wisc.edu{ 31110119Snilay@cs.wisc.edu // Make sure it is not full before inserting an instruction. 31210119Snilay@cs.wisc.edu assert((storeTail + 1) % SQEntries != storeHead); 31310119Snilay@cs.wisc.edu assert(stores < SQEntries); 31410119Snilay@cs.wisc.edu 31510119Snilay@cs.wisc.edu DPRINTF(LSQUnit, "Inserting store PC %#x, idx:%i [sn:%lli]\n", 31610119Snilay@cs.wisc.edu store_inst->readPC(), storeTail, store_inst->seqNum); 31710119Snilay@cs.wisc.edu 31810119Snilay@cs.wisc.edu store_inst->sqIdx = storeTail; 31910119Snilay@cs.wisc.edu store_inst->lqIdx = loadTail; 32010119Snilay@cs.wisc.edu 32110119Snilay@cs.wisc.edu storeQueue[storeTail] = SQEntry(store_inst); 32210119Snilay@cs.wisc.edu 32310119Snilay@cs.wisc.edu incrStIdx(storeTail); 32410119Snilay@cs.wisc.edu 32510119Snilay@cs.wisc.edu ++stores; 32610119Snilay@cs.wisc.edu} 32710119Snilay@cs.wisc.edu 32810119Snilay@cs.wisc.edutemplate <class Impl> 32910697SCurtis.Dunham@arm.comtypename Impl::DynInstPtr 33010747SChris.Emmons@arm.comLSQUnit<Impl>::getMemDepViolator() 33110697SCurtis.Dunham@arm.com{ 33210747SChris.Emmons@arm.com DynInstPtr temp = memDepViolator; 33310119Snilay@cs.wisc.edu 33410697SCurtis.Dunham@arm.com memDepViolator = NULL; 33510747SChris.Emmons@arm.com 33610119Snilay@cs.wisc.edu return temp; 33710119Snilay@cs.wisc.edu} 33810119Snilay@cs.wisc.edu 33910119Snilay@cs.wisc.edutemplate <class Impl> 34010119Snilay@cs.wisc.eduunsigned 34110119Snilay@cs.wisc.eduLSQUnit<Impl>::numFreeEntries() 3428801Sgblack@eecs.umich.edu{ 3433005Sstever@eecs.umich.edu unsigned free_lq_entries = LQEntries - loads; 3448801Sgblack@eecs.umich.edu unsigned free_sq_entries = SQEntries - stores; 3453005Sstever@eecs.umich.edu 3463005Sstever@eecs.umich.edu // Both the LQ and SQ entries have an extra dummy entry to differentiate 3473005Sstever@eecs.umich.edu // empty/full conditions. Subtract 1 from the free entries. 3482566SN/A if (free_lq_entries < free_sq_entries) { 3497861Sgblack@eecs.umich.edu return free_lq_entries - 1; 3507861Sgblack@eecs.umich.edu } else { 3517861Sgblack@eecs.umich.edu return free_sq_entries - 1; 3528635Schris.emmons@arm.com } 3538635Schris.emmons@arm.com} 3548635Schris.emmons@arm.com 3559061Snilay@cs.wisc.edutemplate <class Impl> 3563481Shsul@eecs.umich.eduint 357LSQUnit<Impl>::numLoadsReady() 358{ 359 int load_idx = loadHead; 360 int retval = 0; 361 362 while (load_idx != loadTail) { 363 assert(loadQueue[load_idx]); 364 365 if (loadQueue[load_idx]->readyToIssue()) { 366 ++retval; 367 } 368 } 369 370 return retval; 371} 372 373template <class Impl> 374Fault 375LSQUnit<Impl>::executeLoad(DynInstPtr &inst) 376{ 377 // Execute a specific load. 378 Fault load_fault = NoFault; 379 380 DPRINTF(LSQUnit, "Executing load PC %#x, [sn:%lli]\n", 381 inst->readPC(),inst->seqNum); 382 383// load_fault = inst->initiateAcc(); 384 load_fault = inst->execute(); 385 386 // If the instruction faulted, then we need to send it along to commit 387 // without the instruction completing. 388 if (load_fault != NoFault) { 389 // Send this instruction to commit, also make sure iew stage 390 // realizes there is activity. 391 iewStage->instToCommit(inst); 392 iewStage->activityThisCycle(); 393 } 394 395 return load_fault; 396} 397 398template <class Impl> 399Fault 400LSQUnit<Impl>::executeStore(DynInstPtr &store_inst) 401{ 402 using namespace TheISA; 403 // Make sure that a store exists. 404 assert(stores != 0); 405 406 int store_idx = store_inst->sqIdx; 407 408 DPRINTF(LSQUnit, "Executing store PC %#x [sn:%lli]\n", 409 store_inst->readPC(), store_inst->seqNum); 410 411 // Check the recently completed loads to see if any match this store's 412 // address. If so, then we have a memory ordering violation. 413 int load_idx = store_inst->lqIdx; 414 415 Fault store_fault = store_inst->initiateAcc(); 416// Fault store_fault = store_inst->execute(); 417 418 if (storeQueue[store_idx].size == 0) { 419 DPRINTF(LSQUnit,"Fault on Store PC %#x, [sn:%lli],Size = 0\n", 420 store_inst->readPC(),store_inst->seqNum); 421 422 return store_fault; 423 } 424 425 assert(store_fault == NoFault); 426 427 if (store_inst->isNonSpeculative()) { 428 // Nonspeculative accesses (namely store conditionals) 429 // need to set themselves as able to writeback if we 430 // haven't had a fault by here. 431 storeQueue[store_idx].canWB = true; 432 433 ++storesToWB; 434 } 435 436 if (!memDepViolator) { 437 while (load_idx != loadTail) { 438 // Really only need to check loads that have actually executed 439 // It's safe to check all loads because effAddr is set to 440 // InvalAddr when the dyn inst is created. 441 442 // @todo: For now this is extra conservative, detecting a 443 // violation if the addresses match assuming all accesses 444 // are quad word accesses. 445 446 // @todo: Fix this, magic number being used here 447 if ((loadQueue[load_idx]->effAddr >> 8) == 448 (store_inst->effAddr >> 8)) { 449 // A load incorrectly passed this store. Squash and refetch. 450 // For now return a fault to show that it was unsuccessful. 451 memDepViolator = loadQueue[load_idx]; 452 453 return genMachineCheckFault(); 454 } 455 456 incrLdIdx(load_idx); 457 } 458 459 // If we've reached this point, there was no violation. 460 memDepViolator = NULL; 461 } 462 463 return store_fault; 464} 465 466template <class Impl> 467void 468LSQUnit<Impl>::commitLoad() 469{ 470 assert(loadQueue[loadHead]); 471 472 DPRINTF(LSQUnit, "Committing head load instruction, PC %#x\n", 473 loadQueue[loadHead]->readPC()); 474 475 476 loadQueue[loadHead] = NULL; 477 478 incrLdIdx(loadHead); 479 480 --loads; 481} 482 483template <class Impl> 484void 485LSQUnit<Impl>::commitLoads(InstSeqNum &youngest_inst) 486{ 487 assert(loads == 0 || loadQueue[loadHead]); 488 489 while (loads != 0 && loadQueue[loadHead]->seqNum <= youngest_inst) { 490 commitLoad(); 491 } 492} 493 494template <class Impl> 495void 496LSQUnit<Impl>::commitStores(InstSeqNum &youngest_inst) 497{ 498 assert(stores == 0 || storeQueue[storeHead].inst); 499 500 int store_idx = storeHead; 501 502 while (store_idx != storeTail) { 503 assert(storeQueue[store_idx].inst); 504 // Mark any stores that are now committed and have not yet 505 // been marked as able to write back. 506 if (!storeQueue[store_idx].canWB) { 507 if (storeQueue[store_idx].inst->seqNum > youngest_inst) { 508 break; 509 } 510 DPRINTF(LSQUnit, "Marking store as able to write back, PC " 511 "%#x [sn:%lli]\n", 512 storeQueue[store_idx].inst->readPC(), 513 storeQueue[store_idx].inst->seqNum); 514 515 storeQueue[store_idx].canWB = true; 516 517 ++storesToWB; 518 } 519 520 incrStIdx(store_idx); 521 } 522} 523 524template <class Impl> 525void 526LSQUnit<Impl>::writebackStores() 527{ 528 while (storesToWB > 0 && 529 storeWBIdx != storeTail && 530 storeQueue[storeWBIdx].inst && 531 storeQueue[storeWBIdx].canWB && 532 usedPorts < cachePorts) { 533 534 // Store didn't write any data so no need to write it back to 535 // memory. 536 if (storeQueue[storeWBIdx].size == 0) { 537 completeStore(storeWBIdx); 538 539 incrStIdx(storeWBIdx); 540 541 continue; 542 } 543 544 if (dcacheInterface && dcacheInterface->isBlocked()) { 545 DPRINTF(LSQUnit, "Unable to write back any more stores, cache" 546 " is blocked!\n"); 547 break; 548 } 549 550 ++usedPorts; 551 552 if (storeQueue[storeWBIdx].inst->isDataPrefetch()) { 553 incrStIdx(storeWBIdx); 554 555 continue; 556 } 557 558 assert(storeQueue[storeWBIdx].req); 559 assert(!storeQueue[storeWBIdx].committed); 560 561 MemReqPtr req = storeQueue[storeWBIdx].req; 562 storeQueue[storeWBIdx].committed = true; 563 564 req->cmd = Write; 565 req->completionEvent = NULL; 566 req->time = curTick; 567 assert(!req->data); 568 req->data = new uint8_t[64]; 569 memcpy(req->data, (uint8_t *)&storeQueue[storeWBIdx].data, req->size); 570 571 DPRINTF(LSQUnit, "D-Cache: Writing back store idx:%i PC:%#x " 572 "to Addr:%#x, data:%#x [sn:%lli]\n", 573 storeWBIdx,storeQueue[storeWBIdx].inst->readPC(), 574 req->paddr, *(req->data), 575 storeQueue[storeWBIdx].inst->seqNum); 576 577 switch(storeQueue[storeWBIdx].size) { 578 case 1: 579 cpu->write(req, (uint8_t &)storeQueue[storeWBIdx].data); 580 break; 581 case 2: 582 cpu->write(req, (uint16_t &)storeQueue[storeWBIdx].data); 583 break; 584 case 4: 585 cpu->write(req, (uint32_t &)storeQueue[storeWBIdx].data); 586 break; 587 case 8: 588 cpu->write(req, (uint64_t &)storeQueue[storeWBIdx].data); 589 break; 590 default: 591 panic("Unexpected store size!\n"); 592 } 593 594 // Stores other than store conditionals are completed at this 595 // time. Mark them as completed and, if we have a checker, 596 // tell it that the instruction is completed. 597 // @todo: Figure out what time I can say stores are complete in 598 // the timing memory. 599 if (!(req->flags & LOCKED)) { 600 storeQueue[storeWBIdx].inst->setCompleted(); 601 if (cpu->checker) { 602 cpu->checker->tick(storeQueue[storeWBIdx].inst); 603 } 604 } 605 606 if (dcacheInterface) { 607 assert(!req->completionEvent); 608 StoreCompletionEvent *store_event = new 609 StoreCompletionEvent(storeWBIdx, NULL, this); 610 req->completionEvent = store_event; 611 612 MemAccessResult result = dcacheInterface->access(req); 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 IEW::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 IEW::LdWritebackEvent(storeQueue[storeWBIdx].inst, 631 iewStage); 632 store_event->wbEvent = wb; 633 } 634 635 if (result != MA_HIT && dcacheInterface->doEvents()) { 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 } else { 657 panic("Must HAVE DCACHE!!!!!\n"); 658 } 659 } 660 661 // Not sure this should set it to 0. 662 usedPorts = 0; 663 664 assert(stores >= 0 && storesToWB >= 0); 665} 666 667/*template <class Impl> 668void 669LSQUnit<Impl>::removeMSHR(InstSeqNum seqNum) 670{ 671 list<InstSeqNum>::iterator mshr_it = find(mshrSeqNums.begin(), 672 mshrSeqNums.end(), 673 seqNum); 674 675 if (mshr_it != mshrSeqNums.end()) { 676 mshrSeqNums.erase(mshr_it); 677 DPRINTF(LSQUnit, "Removing MSHR. count = %i\n",mshrSeqNums.size()); 678 } 679}*/ 680 681template <class Impl> 682void 683LSQUnit<Impl>::squash(const InstSeqNum &squashed_num) 684{ 685 DPRINTF(LSQUnit, "Squashing until [sn:%lli]!" 686 "(Loads:%i Stores:%i)\n", squashed_num, loads, stores); 687 688 int load_idx = loadTail; 689 decrLdIdx(load_idx); 690 691 while (loads != 0 && loadQueue[load_idx]->seqNum > squashed_num) { 692 DPRINTF(LSQUnit,"Load Instruction PC %#x squashed, " 693 "[sn:%lli]\n", 694 loadQueue[load_idx]->readPC(), 695 loadQueue[load_idx]->seqNum); 696 697 if (isStalled() && load_idx == stallingLoadIdx) { 698 stalled = false; 699 stallingStoreIsn = 0; 700 stallingLoadIdx = 0; 701 } 702 703 // Clear the smart pointer to make sure it is decremented. 704 loadQueue[load_idx]->squashed = true; 705 loadQueue[load_idx] = NULL; 706 --loads; 707 708 // Inefficient! 709 loadTail = load_idx; 710 711 decrLdIdx(load_idx); 712 } 713 714 if (isLoadBlocked) { 715 if (squashed_num < blockedLoadSeqNum) { 716 isLoadBlocked = false; 717 loadBlockedHandled = false; 718 blockedLoadSeqNum = 0; 719 } 720 } 721 722 int store_idx = storeTail; 723 decrStIdx(store_idx); 724 725 while (stores != 0 && 726 storeQueue[store_idx].inst->seqNum > squashed_num) { 727 // Instructions marked as can WB are already committed. 728 if (storeQueue[store_idx].canWB) { 729 break; 730 } 731 732 DPRINTF(LSQUnit,"Store Instruction PC %#x squashed, " 733 "idx:%i [sn:%lli]\n", 734 storeQueue[store_idx].inst->readPC(), 735 store_idx, storeQueue[store_idx].inst->seqNum); 736 737 // I don't think this can happen. It should have been cleared 738 // by the stalling load. 739 if (isStalled() && 740 storeQueue[store_idx].inst->seqNum == stallingStoreIsn) { 741 panic("Is stalled should have been cleared by stalling load!\n"); 742 stalled = false; 743 stallingStoreIsn = 0; 744 } 745 746 // Clear the smart pointer to make sure it is decremented. 747 storeQueue[store_idx].inst->squashed = true; 748 storeQueue[store_idx].inst = NULL; 749 storeQueue[store_idx].canWB = 0; 750 751 if (storeQueue[store_idx].req) { 752 // There should not be a completion event if the store has 753 // not yet committed. 754 assert(!storeQueue[store_idx].req->completionEvent); 755 } 756 757 storeQueue[store_idx].req = NULL; 758 --stores; 759 760 // Inefficient! 761 storeTail = store_idx; 762 763 decrStIdx(store_idx); 764 } 765} 766 767template <class Impl> 768void 769LSQUnit<Impl>::completeStore(int store_idx) 770{ 771 assert(storeQueue[store_idx].inst); 772 storeQueue[store_idx].completed = true; 773 --storesToWB; 774 // A bit conservative because a store completion may not free up entries, 775 // but hopefully avoids two store completions in one cycle from making 776 // the CPU tick twice. 777 cpu->activityThisCycle(); 778 779 if (store_idx == storeHead) { 780 do { 781 incrStIdx(storeHead); 782 783 --stores; 784 } while (storeQueue[storeHead].completed && 785 storeHead != storeTail); 786 787 iewStage->updateLSQNextCycle = true; 788 } 789 790 DPRINTF(LSQUnit, "Completing store [sn:%lli], idx:%i, store head " 791 "idx:%i\n", 792 storeQueue[store_idx].inst->seqNum, store_idx, storeHead); 793 794 if (isStalled() && 795 storeQueue[store_idx].inst->seqNum == stallingStoreIsn) { 796 DPRINTF(LSQUnit, "Unstalling, stalling store [sn:%lli] " 797 "load idx:%i\n", 798 stallingStoreIsn, stallingLoadIdx); 799 stalled = false; 800 stallingStoreIsn = 0; 801 iewStage->replayMemInst(loadQueue[stallingLoadIdx]); 802 } 803 804 storeQueue[store_idx].inst->setCompleted(); 805 806 // Tell the checker we've completed this instruction. Some stores 807 // may get reported twice to the checker, but the checker can 808 // handle that case. 809 if (cpu->checker) { 810 cpu->checker->tick(storeQueue[store_idx].inst); 811 } 812} 813 814template <class Impl> 815inline void 816LSQUnit<Impl>::incrStIdx(int &store_idx) 817{ 818 if (++store_idx >= SQEntries) 819 store_idx = 0; 820} 821 822template <class Impl> 823inline void 824LSQUnit<Impl>::decrStIdx(int &store_idx) 825{ 826 if (--store_idx < 0) 827 store_idx += SQEntries; 828} 829 830template <class Impl> 831inline void 832LSQUnit<Impl>::incrLdIdx(int &load_idx) 833{ 834 if (++load_idx >= LQEntries) 835 load_idx = 0; 836} 837 838template <class Impl> 839inline void 840LSQUnit<Impl>::decrLdIdx(int &load_idx) 841{ 842 if (--load_idx < 0) 843 load_idx += LQEntries; 844} 845 846template <class Impl> 847void 848LSQUnit<Impl>::dumpInsts() 849{ 850 cprintf("Load store queue: Dumping instructions.\n"); 851 cprintf("Load queue size: %i\n", loads); 852 cprintf("Load queue: "); 853 854 int load_idx = loadHead; 855 856 while (load_idx != loadTail && loadQueue[load_idx]) { 857 cprintf("%#x ", loadQueue[load_idx]->readPC()); 858 859 incrLdIdx(load_idx); 860 } 861 862 cprintf("Store queue size: %i\n", stores); 863 cprintf("Store queue: "); 864 865 int store_idx = storeHead; 866 867 while (store_idx != storeTail && storeQueue[store_idx].inst) { 868 cprintf("%#x ", storeQueue[store_idx].inst->readPC()); 869 870 incrStIdx(store_idx); 871 } 872 873 cprintf("\n"); 874} 875