lsq_unit_impl.hh revision 2329
12623SN/A/* 22623SN/A * Copyright (c) 2004-2005 The Regents of The University of Michigan 32623SN/A * All rights reserved. 42623SN/A * 52623SN/A * Redistribution and use in source and binary forms, with or without 62623SN/A * modification, are permitted provided that the following conditions are 72623SN/A * met: redistributions of source code must retain the above copyright 82623SN/A * notice, this list of conditions and the following disclaimer; 92623SN/A * redistributions in binary form must reproduce the above copyright 102623SN/A * notice, this list of conditions and the following disclaimer in the 112623SN/A * documentation and/or other materials provided with the distribution; 122623SN/A * neither the name of the copyright holders nor the names of its 132623SN/A * contributors may be used to endorse or promote products derived from 142623SN/A * this software without specific prior written permission. 152623SN/A * 162623SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 172623SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 182623SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 192623SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 202623SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 212623SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 222623SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 232623SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 242623SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 252623SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 262623SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 272665Ssaidi@eecs.umich.edu */ 282665Ssaidi@eecs.umich.edu 292623SN/A#include "cpu/checker/cpu.hh" 302623SN/A#include "cpu/o3/lsq_unit.hh" 313170Sstever@eecs.umich.edu#include "base/str.hh" 322623SN/A 334040Ssaidi@eecs.umich.edutemplate <class Impl> 342623SN/ALSQUnit<Impl>::StoreCompletionEvent::StoreCompletionEvent(int store_idx, 352623SN/A Event *wb_event, 363348Sbinkertn@umich.edu LSQUnit<Impl> *lsq_ptr) 373348Sbinkertn@umich.edu : Event(&mainEventQueue), 384762Snate@binkert.org wbEvent(wb_event), 392901Ssaidi@eecs.umich.edu storeIdx(store_idx), 402623SN/A lsqPtr(lsq_ptr) 412623SN/A{ 422623SN/A this->setFlags(Event::AutoDelete); 432623SN/A} 442856Srdreslin@umich.edu 452856Srdreslin@umich.edutemplate <class Impl> 462856Srdreslin@umich.eduvoid 472856Srdreslin@umich.eduLSQUnit<Impl>::StoreCompletionEvent::process() 482856Srdreslin@umich.edu{ 492856Srdreslin@umich.edu DPRINTF(LSQ, "Cache miss complete for store idx:%i\n", storeIdx); 502856Srdreslin@umich.edu DPRINTF(Activity, "Activity: st writeback event idx:%i\n", storeIdx); 512856Srdreslin@umich.edu 522856Srdreslin@umich.edu //lsqPtr->removeMSHR(lsqPtr->storeQueue[storeIdx].inst->seqNum); 532856Srdreslin@umich.edu 542623SN/A if (lsqPtr->isSwitchedOut()) 552623SN/A return; 562623SN/A 572623SN/A lsqPtr->cpu->wakeCPU(); 582623SN/A if (wbEvent) 592623SN/A wbEvent->process(); 602680Sktlim@umich.edu lsqPtr->completeStore(storeIdx); 612680Sktlim@umich.edu} 622623SN/A 632623SN/Atemplate <class Impl> 642680Sktlim@umich.educonst char * 652623SN/ALSQUnit<Impl>::StoreCompletionEvent::description() 662623SN/A{ 672623SN/A return "LSQ store completion event"; 682623SN/A} 692623SN/A 703349Sbinkertn@umich.edutemplate <class Impl> 712623SN/ALSQUnit<Impl>::LSQUnit() 722623SN/A : loads(0), stores(0), storesToWB(0), stalled(false), isLoadBlocked(false), 732623SN/A loadBlockedHandled(false) 742623SN/A{ 752623SN/A} 762623SN/A 773349Sbinkertn@umich.edutemplate<class Impl> 782623SN/Avoid 793184Srdreslin@umich.eduLSQUnit<Impl>::init(Params *params, unsigned maxLQEntries, 803184Srdreslin@umich.edu unsigned maxSQEntries, unsigned id) 812623SN/A 822623SN/A{ 832623SN/A DPRINTF(LSQUnit, "Creating LSQUnit%i object.\n",id); 842623SN/A 852623SN/A switchedOut = false; 863647Srdreslin@umich.edu 873647Srdreslin@umich.edu lsqID = id; 883647Srdreslin@umich.edu 893647Srdreslin@umich.edu // Add 1 for the sentinel entry (they are circular queues). 903647Srdreslin@umich.edu LQEntries = maxLQEntries + 1; 912631SN/A SQEntries = maxSQEntries + 1; 923647Srdreslin@umich.edu 932631SN/A loadQueue.resize(LQEntries); 942623SN/A storeQueue.resize(SQEntries); 952623SN/A 962623SN/A loadHead = loadTail = 0; 972948Ssaidi@eecs.umich.edu 982948Ssaidi@eecs.umich.edu storeHead = storeWBIdx = storeTail = 0; 993349Sbinkertn@umich.edu 1002948Ssaidi@eecs.umich.edu usedPorts = 0; 1012948Ssaidi@eecs.umich.edu cachePorts = params->cachePorts; 1022948Ssaidi@eecs.umich.edu 1032948Ssaidi@eecs.umich.edu dcacheInterface = params->dcacheInterface; 1042948Ssaidi@eecs.umich.edu 1052623SN/A memDepViolator = NULL; 1063170Sstever@eecs.umich.edu 1073170Sstever@eecs.umich.edu blockedLoadSeqNum = 0; 1082623SN/A} 1092623SN/A 1103647Srdreslin@umich.edutemplate<class Impl> 1113647Srdreslin@umich.edustd::string 1123647Srdreslin@umich.eduLSQUnit<Impl>::name() const 1133647Srdreslin@umich.edu{ 1142623SN/A if (Impl::MaxThreads == 1) { 1152839Sktlim@umich.edu return iewStage->name() + ".lsq"; 1162867Sktlim@umich.edu } else { 1173222Sktlim@umich.edu return iewStage->name() + ".lsq.thread." + to_string(lsqID); 1182901Ssaidi@eecs.umich.edu } 1192623SN/A} 1202623SN/A 1212623SN/Atemplate<class Impl> 1222623SN/Avoid 1232623SN/ALSQUnit<Impl>::clearLQ() 1242623SN/A{ 1252623SN/A loadQueue.clear(); 1262623SN/A} 1272623SN/A 1282623SN/Atemplate<class Impl> 1292915Sktlim@umich.eduvoid 1302915Sktlim@umich.eduLSQUnit<Impl>::clearSQ() 1312623SN/A{ 1322623SN/A storeQueue.clear(); 1332623SN/A} 1342623SN/A 1352623SN/A#if 0 1362623SN/Atemplate<class Impl> 1372915Sktlim@umich.eduvoid 1382915Sktlim@umich.eduLSQUnit<Impl>::setPageTable(PageTable *pt_ptr) 1392623SN/A{ 1402798Sktlim@umich.edu DPRINTF(LSQUnit, "Setting the page table pointer.\n"); 1412798Sktlim@umich.edu pTable = pt_ptr; 1422901Ssaidi@eecs.umich.edu} 1432839Sktlim@umich.edu#endif 1442798Sktlim@umich.edu 1452839Sktlim@umich.edutemplate<class Impl> 1462798Sktlim@umich.eduvoid 1472798Sktlim@umich.eduLSQUnit<Impl>::switchOut() 1482901Ssaidi@eecs.umich.edu{ 1492901Ssaidi@eecs.umich.edu switchedOut = true; 1502798Sktlim@umich.edu for (int i = 0; i < loadQueue.size(); ++i) 1512839Sktlim@umich.edu loadQueue[i] = NULL; 1522839Sktlim@umich.edu 1532901Ssaidi@eecs.umich.edu assert(storesToWB == 0); 1542798Sktlim@umich.edu 1552623SN/A while (storesToWB > 0 && 1562623SN/A storeWBIdx != storeTail && 1572623SN/A storeQueue[storeWBIdx].inst && 1582798Sktlim@umich.edu storeQueue[storeWBIdx].canWB) { 1592623SN/A 1602798Sktlim@umich.edu if (storeQueue[storeWBIdx].size == 0 || 1614762Snate@binkert.org storeQueue[storeWBIdx].inst->isDataPrefetch() || 1623201Shsul@eecs.umich.edu storeQueue[storeWBIdx].committed || 1632867Sktlim@umich.edu storeQueue[storeWBIdx].req->flags & LOCKED) { 1642867Sktlim@umich.edu incrStIdx(storeWBIdx); 1652915Sktlim@umich.edu 1662915Sktlim@umich.edu continue; 1672915Sktlim@umich.edu } 1682867Sktlim@umich.edu 1692867Sktlim@umich.edu assert(storeQueue[storeWBIdx].req); 1702867Sktlim@umich.edu assert(!storeQueue[storeWBIdx].committed); 1714471Sstever@eecs.umich.edu 1722623SN/A MemReqPtr req = storeQueue[storeWBIdx].req; 1732798Sktlim@umich.edu storeQueue[storeWBIdx].committed = true; 1742901Ssaidi@eecs.umich.edu 1753222Sktlim@umich.edu req->cmd = Write; 1762798Sktlim@umich.edu req->completionEvent = NULL; 1772798Sktlim@umich.edu req->time = curTick; 1782798Sktlim@umich.edu assert(!req->data); 1792798Sktlim@umich.edu req->data = new uint8_t[64]; 1802798Sktlim@umich.edu memcpy(req->data, (uint8_t *)&storeQueue[storeWBIdx].data, req->size); 1812798Sktlim@umich.edu 1822798Sktlim@umich.edu DPRINTF(LSQUnit, "D-Cache: Writing back store idx:%i PC:%#x " 1833222Sktlim@umich.edu "to Addr:%#x, data:%#x [sn:%lli]\n", 1842867Sktlim@umich.edu storeWBIdx,storeQueue[storeWBIdx].inst->readPC(), 1852867Sktlim@umich.edu req->paddr, *(req->data), 1862867Sktlim@umich.edu storeQueue[storeWBIdx].inst->seqNum); 1872867Sktlim@umich.edu 1882867Sktlim@umich.edu switch(storeQueue[storeWBIdx].size) { 1892623SN/A case 1: 1902623SN/A cpu->write(req, (uint8_t &)storeQueue[storeWBIdx].data); 1912623SN/A break; 1922623SN/A case 2: 1932623SN/A cpu->write(req, (uint16_t &)storeQueue[storeWBIdx].data); 1942623SN/A break; 1954192Sktlim@umich.edu case 4: 1962623SN/A cpu->write(req, (uint32_t &)storeQueue[storeWBIdx].data); 1972680Sktlim@umich.edu break; 1982623SN/A case 8: 1992680Sktlim@umich.edu cpu->write(req, (uint64_t &)storeQueue[storeWBIdx].data); 2002680Sktlim@umich.edu break; 2012680Sktlim@umich.edu default: 2022623SN/A panic("Unexpected store size!\n"); 2032623SN/A } 2042623SN/A incrStIdx(storeWBIdx); 2052623SN/A } 2063201Shsul@eecs.umich.edu} 2073201Shsul@eecs.umich.edu 2083201Shsul@eecs.umich.edutemplate<class Impl> 2093201Shsul@eecs.umich.eduvoid 2102623SN/ALSQUnit<Impl>::takeOverFrom() 2112623SN/A{ 2122623SN/A switchedOut = false; 2132623SN/A loads = stores = storesToWB = 0; 2142623SN/A 2152623SN/A loadHead = loadTail = 0; 2162623SN/A 2172683Sktlim@umich.edu storeHead = storeWBIdx = storeTail = 0; 2182623SN/A 2192623SN/A usedPorts = 0; 2202623SN/A 2212623SN/A memDepViolator = NULL; 2222623SN/A 2233686Sktlim@umich.edu blockedLoadSeqNum = 0; 2242623SN/A 2254471Sstever@eecs.umich.edu stalled = false; 2262623SN/A isLoadBlocked = false; 2272623SN/A loadBlockedHandled = false; 2282623SN/A} 2292623SN/A 2302623SN/Atemplate<class Impl> 2312623SN/Avoid 2322623SN/ALSQUnit<Impl>::resizeLQ(unsigned size) 2332683Sktlim@umich.edu{ 2342623SN/A unsigned size_plus_sentinel = size + 1; 2352644Sstever@eecs.umich.edu assert(size_plus_sentinel >= LQEntries); 2362623SN/A 2372644Sstever@eecs.umich.edu if (size_plus_sentinel > LQEntries) { 2382644Sstever@eecs.umich.edu while (size_plus_sentinel > loadQueue.size()) { 2392623SN/A DynInstPtr dummy; 2402623SN/A loadQueue.push_back(dummy); 2412623SN/A LQEntries++; 2422623SN/A } 2432623SN/A } else { 2442623SN/A LQEntries = size_plus_sentinel; 2452623SN/A } 2462623SN/A 2472623SN/A} 2482623SN/A 2493169Sstever@eecs.umich.edutemplate<class Impl> 2503169Sstever@eecs.umich.eduvoid 2513170Sstever@eecs.umich.eduLSQUnit<Impl>::resizeSQ(unsigned size) 2522623SN/A{ 2532623SN/A unsigned size_plus_sentinel = size + 1; 2543169Sstever@eecs.umich.edu if (size_plus_sentinel > SQEntries) { 2552623SN/A while (size_plus_sentinel > storeQueue.size()) { 2562623SN/A SQEntry dummy; 2572623SN/A storeQueue.push_back(dummy); 2583169Sstever@eecs.umich.edu SQEntries++; 2592623SN/A } 2602623SN/A } else { 2612623SN/A SQEntries = size_plus_sentinel; 2623349Sbinkertn@umich.edu } 2634022Sstever@eecs.umich.edu} 2643169Sstever@eecs.umich.edu 2652623SN/Atemplate <class Impl> 2663169Sstever@eecs.umich.eduvoid 2672623SN/ALSQUnit<Impl>::insert(DynInstPtr &inst) 2683169Sstever@eecs.umich.edu{ 2692623SN/A assert(inst->isMemRef()); 2702623SN/A 2713169Sstever@eecs.umich.edu assert(inst->isLoad() || inst->isStore()); 2722623SN/A 2732623SN/A if (inst->isLoad()) { 2744200Ssaidi@eecs.umich.edu insertLoad(inst); 2754200Ssaidi@eecs.umich.edu } else { 2764200Ssaidi@eecs.umich.edu insertStore(inst); 2774200Ssaidi@eecs.umich.edu } 2783658Sktlim@umich.edu 2793658Sktlim@umich.edu inst->setInLSQ(); 2802623SN/A} 2812623SN/A 2822623SN/Atemplate <class Impl> 2832623SN/Avoid 2842623SN/ALSQUnit<Impl>::insertLoad(DynInstPtr &load_inst) 2852623SN/A{ 2862623SN/A assert((loadTail + 1) % LQEntries != loadHead); 2872623SN/A assert(loads < LQEntries); 2882623SN/A 2894040Ssaidi@eecs.umich.edu DPRINTF(LSQUnit, "Inserting load PC %#x, idx:%i [sn:%lli]\n", 2904040Ssaidi@eecs.umich.edu load_inst->readPC(), loadTail, load_inst->seqNum); 2914040Ssaidi@eecs.umich.edu 2924040Ssaidi@eecs.umich.edu load_inst->lqIdx = loadTail; 2934115Ssaidi@eecs.umich.edu 2944115Ssaidi@eecs.umich.edu if (stores == 0) { 2954115Ssaidi@eecs.umich.edu load_inst->sqIdx = -1; 2964115Ssaidi@eecs.umich.edu } else { 2972623SN/A load_inst->sqIdx = storeTail; 2982623SN/A } 2992623SN/A 3002623SN/A loadQueue[loadTail] = load_inst; 3012623SN/A 3022623SN/A incrLdIdx(loadTail); 3032623SN/A 3042623SN/A ++loads; 3052623SN/A} 3062623SN/A 3072623SN/Atemplate <class Impl> 3082623SN/Avoid 3092623SN/ALSQUnit<Impl>::insertStore(DynInstPtr &store_inst) 3102623SN/A{ 3112623SN/A // Make sure it is not full before inserting an instruction. 3122623SN/A assert((storeTail + 1) % SQEntries != storeHead); 3132623SN/A assert(stores < SQEntries); 3142623SN/A 3152623SN/A DPRINTF(LSQUnit, "Inserting store PC %#x, idx:%i [sn:%lli]\n", 3162623SN/A store_inst->readPC(), storeTail, store_inst->seqNum); 3172623SN/A 3182623SN/A store_inst->sqIdx = storeTail; 3192623SN/A store_inst->lqIdx = loadTail; 3202623SN/A 3212623SN/A storeQueue[storeTail] = SQEntry(store_inst); 3222623SN/A 3232623SN/A incrStIdx(storeTail); 3242623SN/A 3252623SN/A ++stores; 3262623SN/A} 3272623SN/A 3282623SN/Atemplate <class Impl> 3292623SN/Atypename Impl::DynInstPtr 3302623SN/ALSQUnit<Impl>::getMemDepViolator() 3312623SN/A{ 3322623SN/A DynInstPtr temp = memDepViolator; 3332623SN/A 3342623SN/A memDepViolator = NULL; 3352623SN/A 3362623SN/A return temp; 3372623SN/A} 3382623SN/A 3392623SN/Atemplate <class Impl> 3403169Sstever@eecs.umich.eduunsigned 3413169Sstever@eecs.umich.eduLSQUnit<Impl>::numFreeEntries() 3423170Sstever@eecs.umich.edu{ 3432623SN/A unsigned free_lq_entries = LQEntries - loads; 3444040Ssaidi@eecs.umich.edu unsigned free_sq_entries = SQEntries - stores; 3454040Ssaidi@eecs.umich.edu 3464040Ssaidi@eecs.umich.edu // Both the LQ and SQ entries have an extra dummy entry to differentiate 3474040Ssaidi@eecs.umich.edu // empty/full conditions. Subtract 1 from the free entries. 3482623SN/A if (free_lq_entries < free_sq_entries) { 3493169Sstever@eecs.umich.edu return free_lq_entries - 1; 3503169Sstever@eecs.umich.edu } else { 3512623SN/A return free_sq_entries - 1; 3522623SN/A } 3533169Sstever@eecs.umich.edu} 3544040Ssaidi@eecs.umich.edu 3554040Ssaidi@eecs.umich.edutemplate <class Impl> 3564040Ssaidi@eecs.umich.eduint 3574040Ssaidi@eecs.umich.eduLSQUnit<Impl>::numLoadsReady() 3583169Sstever@eecs.umich.edu{ 3593169Sstever@eecs.umich.edu int load_idx = loadHead; 3602623SN/A int retval = 0; 3613170Sstever@eecs.umich.edu 3623170Sstever@eecs.umich.edu while (load_idx != loadTail) { 3633170Sstever@eecs.umich.edu assert(loadQueue[load_idx]); 3643170Sstever@eecs.umich.edu 3653170Sstever@eecs.umich.edu if (loadQueue[load_idx]->readyToIssue()) { 3664040Ssaidi@eecs.umich.edu ++retval; 3674040Ssaidi@eecs.umich.edu } 3684040Ssaidi@eecs.umich.edu } 3694040Ssaidi@eecs.umich.edu 3703170Sstever@eecs.umich.edu return retval; 3713170Sstever@eecs.umich.edu} 3723170Sstever@eecs.umich.edu 3733170Sstever@eecs.umich.edutemplate <class Impl> 3743170Sstever@eecs.umich.eduFault 3753170Sstever@eecs.umich.eduLSQUnit<Impl>::executeLoad(DynInstPtr &inst) 3763170Sstever@eecs.umich.edu{ 3773170Sstever@eecs.umich.edu // Execute a specific load. 3783170Sstever@eecs.umich.edu Fault load_fault = NoFault; 3792623SN/A 3804200Ssaidi@eecs.umich.edu DPRINTF(LSQUnit, "Executing load PC %#x, [sn:%lli]\n", 3814200Ssaidi@eecs.umich.edu inst->readPC(),inst->seqNum); 3824200Ssaidi@eecs.umich.edu 3833658Sktlim@umich.edu// load_fault = inst->initiateAcc(); 3843658Sktlim@umich.edu load_fault = inst->execute(); 3852623SN/A 3862623SN/A // If the instruction faulted, then we need to send it along to commit 3872623SN/A // without the instruction completing. 3882623SN/A if (load_fault != NoFault) { 3892623SN/A // Send this instruction to commit, also make sure iew stage 3902623SN/A // realizes there is activity. 3912623SN/A iewStage->instToCommit(inst); 3922623SN/A iewStage->activityThisCycle(); 3932623SN/A } 3942623SN/A 3952623SN/A return load_fault; 3962623SN/A} 3974224Sgblack@eecs.umich.edu 3984224Sgblack@eecs.umich.edutemplate <class Impl> 3994224Sgblack@eecs.umich.eduFault 4004224Sgblack@eecs.umich.eduLSQUnit<Impl>::executeStore(DynInstPtr &store_inst) 4014224Sgblack@eecs.umich.edu{ 4024224Sgblack@eecs.umich.edu using namespace TheISA; 4034224Sgblack@eecs.umich.edu // Make sure that a store exists. 4044224Sgblack@eecs.umich.edu assert(stores != 0); 4054224Sgblack@eecs.umich.edu 4064224Sgblack@eecs.umich.edu int store_idx = store_inst->sqIdx; 4072623SN/A 4082623SN/A DPRINTF(LSQUnit, "Executing store PC %#x [sn:%lli]\n", 4092623SN/A store_inst->readPC(), store_inst->seqNum); 4102623SN/A 4112623SN/A // Check the recently completed loads to see if any match this store's 4122623SN/A // address. If so, then we have a memory ordering violation. 4132623SN/A int load_idx = store_inst->lqIdx; 4142623SN/A 4152623SN/A Fault store_fault = store_inst->initiateAcc(); 4162623SN/A// Fault store_fault = store_inst->execute(); 4172623SN/A 4182623SN/A if (storeQueue[store_idx].size == 0) { 4192623SN/A DPRINTF(LSQUnit,"Fault on Store PC %#x, [sn:%lli],Size = 0\n", 4202623SN/A store_inst->readPC(),store_inst->seqNum); 4212623SN/A 4222623SN/A return store_fault; 4232623SN/A } 4242623SN/A 4252623SN/A assert(store_fault == NoFault); 4262623SN/A 4272623SN/A if (store_inst->isNonSpeculative()) { 4282623SN/A // Nonspeculative accesses (namely store conditionals) 4292623SN/A // need to set themselves as able to writeback if we 4302623SN/A // haven't had a fault by here. 4312623SN/A storeQueue[store_idx].canWB = true; 4322623SN/A 4332623SN/A ++storesToWB; 4342623SN/A } 4352623SN/A 4362623SN/A if (!memDepViolator) { 4372623SN/A while (load_idx != loadTail) { 4382623SN/A // Really only need to check loads that have actually executed 4392623SN/A // It's safe to check all loads because effAddr is set to 4402623SN/A // InvalAddr when the dyn inst is created. 4412623SN/A 4422623SN/A // @todo: For now this is extra conservative, detecting a 4432623SN/A // violation if the addresses match assuming all accesses 4442623SN/A // are quad word accesses. 4452623SN/A 4462623SN/A // @todo: Fix this, magic number being used here 4472623SN/A if ((loadQueue[load_idx]->effAddr >> 8) == 4482623SN/A (store_inst->effAddr >> 8)) { 4492623SN/A // A load incorrectly passed this store. Squash and refetch. 4502623SN/A // For now return a fault to show that it was unsuccessful. 4512623SN/A memDepViolator = loadQueue[load_idx]; 4522623SN/A 4533387Sgblack@eecs.umich.edu return genMachineCheckFault(); 4543387Sgblack@eecs.umich.edu } 4552631SN/A 4562663Sstever@eecs.umich.edu incrLdIdx(load_idx); 4573170Sstever@eecs.umich.edu } 4582662Sstever@eecs.umich.edu 4592623SN/A // If we've reached this point, there was no violation. 4604022Sstever@eecs.umich.edu memDepViolator = NULL; 4612623SN/A } 4622623SN/A 4632623SN/A return store_fault; 4642630SN/A} 4652623SN/A 4662623SN/Atemplate <class Impl> 4672623SN/Avoid 4682623SN/ALSQUnit<Impl>::commitLoad() 4692623SN/A{ 4702623SN/A assert(loadQueue[loadHead]); 4712623SN/A 4722623SN/A DPRINTF(LSQUnit, "Committing head load instruction, PC %#x\n", 4732623SN/A loadQueue[loadHead]->readPC()); 4743658Sktlim@umich.edu 4753658Sktlim@umich.edu 4762644Sstever@eecs.umich.edu loadQueue[loadHead] = NULL; 4772644Sstever@eecs.umich.edu 4782623SN/A incrLdIdx(loadHead); 4793222Sktlim@umich.edu 4803222Sktlim@umich.edu --loads; 4813222Sktlim@umich.edu} 4822623SN/A 4832623SN/Atemplate <class Impl> 4842623SN/Avoid 4852623SN/ALSQUnit<Impl>::commitLoads(InstSeqNum &youngest_inst) 4862644Sstever@eecs.umich.edu{ 4872623SN/A assert(loads == 0 || loadQueue[loadHead]); 4882623SN/A 4892623SN/A while (loads != 0 && loadQueue[loadHead]->seqNum <= youngest_inst) { 4902631SN/A commitLoad(); 4912631SN/A } 4922631SN/A} 4932631SN/A 4942631SN/Atemplate <class Impl> 4952631SN/Avoid 4962623SN/ALSQUnit<Impl>::commitStores(InstSeqNum &youngest_inst) 4972623SN/A{ 4982623SN/A assert(stores == 0 || storeQueue[storeHead].inst); 4992623SN/A 5003349Sbinkertn@umich.edu int store_idx = storeHead; 5012623SN/A 5022623SN/A while (store_idx != storeTail) { 5032623SN/A assert(storeQueue[store_idx].inst); 5042644Sstever@eecs.umich.edu // Mark any stores that are now committed and have not yet 5052623SN/A // been marked as able to write back. 5062798Sktlim@umich.edu if (!storeQueue[store_idx].canWB) { 5072623SN/A if (storeQueue[store_idx].inst->seqNum > youngest_inst) { 5082644Sstever@eecs.umich.edu break; 5093222Sktlim@umich.edu } 5103222Sktlim@umich.edu DPRINTF(LSQUnit, "Marking store as able to write back, PC " 5113222Sktlim@umich.edu "%#x [sn:%lli]\n", 5122839Sktlim@umich.edu storeQueue[store_idx].inst->readPC(), 5133658Sktlim@umich.edu storeQueue[store_idx].inst->seqNum); 5143658Sktlim@umich.edu 5153658Sktlim@umich.edu storeQueue[store_idx].canWB = true; 5162839Sktlim@umich.edu 5172798Sktlim@umich.edu ++storesToWB; 5182798Sktlim@umich.edu } 5192798Sktlim@umich.edu 5202623SN/A incrStIdx(store_idx); 5212644Sstever@eecs.umich.edu } 5222623SN/A} 5232623SN/A 5243170Sstever@eecs.umich.edutemplate <class Impl> 5253170Sstever@eecs.umich.eduvoid 5263170Sstever@eecs.umich.eduLSQUnit<Impl>::writebackStores() 5273170Sstever@eecs.umich.edu{ 5282644Sstever@eecs.umich.edu while (storesToWB > 0 && 5293170Sstever@eecs.umich.edu storeWBIdx != storeTail && 5303170Sstever@eecs.umich.edu storeQueue[storeWBIdx].inst && 5313170Sstever@eecs.umich.edu storeQueue[storeWBIdx].canWB && 5323170Sstever@eecs.umich.edu usedPorts < cachePorts) { 5333170Sstever@eecs.umich.edu 5343170Sstever@eecs.umich.edu // Store didn't write any data so no need to write it back to 5353170Sstever@eecs.umich.edu // memory. 5363170Sstever@eecs.umich.edu if (storeQueue[storeWBIdx].size == 0) { 5373170Sstever@eecs.umich.edu completeStore(storeWBIdx); 5382644Sstever@eecs.umich.edu 5392644Sstever@eecs.umich.edu incrStIdx(storeWBIdx); 5402644Sstever@eecs.umich.edu 5412623SN/A continue; 5422623SN/A } 5432623SN/A 5442644Sstever@eecs.umich.edu if (dcacheInterface && dcacheInterface->isBlocked()) { 5452644Sstever@eecs.umich.edu DPRINTF(LSQUnit, "Unable to write back any more stores, cache" 5462623SN/A " is blocked!\n"); 5473658Sktlim@umich.edu break; 5483658Sktlim@umich.edu } 5493658Sktlim@umich.edu 5502623SN/A ++usedPorts; 5512623SN/A 5522948Ssaidi@eecs.umich.edu if (storeQueue[storeWBIdx].inst->isDataPrefetch()) { 5532948Ssaidi@eecs.umich.edu incrStIdx(storeWBIdx); 5542948Ssaidi@eecs.umich.edu 5552948Ssaidi@eecs.umich.edu continue; 5562948Ssaidi@eecs.umich.edu } 5572623SN/A 5582623SN/A assert(storeQueue[storeWBIdx].req); 5593349Sbinkertn@umich.edu assert(!storeQueue[storeWBIdx].committed); 5602623SN/A 5613310Srdreslin@umich.edu MemReqPtr req = storeQueue[storeWBIdx].req; 5623310Srdreslin@umich.edu storeQueue[storeWBIdx].committed = true; 5634584Ssaidi@eecs.umich.edu 5642948Ssaidi@eecs.umich.edu req->cmd = Write; 5653495Sktlim@umich.edu req->completionEvent = NULL; 5663310Srdreslin@umich.edu req->time = curTick; 5673310Srdreslin@umich.edu assert(!req->data); 5683495Sktlim@umich.edu req->data = new uint8_t[64]; 5692948Ssaidi@eecs.umich.edu memcpy(req->data, (uint8_t *)&storeQueue[storeWBIdx].data, req->size); 5703310Srdreslin@umich.edu 5713310Srdreslin@umich.edu DPRINTF(LSQUnit, "D-Cache: Writing back store idx:%i PC:%#x " 5724433Ssaidi@eecs.umich.edu "to Addr:%#x, data:%#x [sn:%lli]\n", 5734433Ssaidi@eecs.umich.edu storeWBIdx,storeQueue[storeWBIdx].inst->readPC(), 5744433Ssaidi@eecs.umich.edu req->paddr, *(req->data), 5754433Ssaidi@eecs.umich.edu storeQueue[storeWBIdx].inst->seqNum); 5764433Ssaidi@eecs.umich.edu 5774433Ssaidi@eecs.umich.edu switch(storeQueue[storeWBIdx].size) { 5784433Ssaidi@eecs.umich.edu case 1: 5793310Srdreslin@umich.edu cpu->write(req, (uint8_t &)storeQueue[storeWBIdx].data); 5804433Ssaidi@eecs.umich.edu break; 5814433Ssaidi@eecs.umich.edu case 2: 5822623SN/A cpu->write(req, (uint16_t &)storeQueue[storeWBIdx].data); 5832623SN/A break; 5842657Ssaidi@eecs.umich.edu case 4: 5852623SN/A cpu->write(req, (uint32_t &)storeQueue[storeWBIdx].data); 5862623SN/A break; 5872623SN/A case 8: 5882623SN/A cpu->write(req, (uint64_t &)storeQueue[storeWBIdx].data); 5892623SN/A break; 5902623SN/A default: 5913349Sbinkertn@umich.edu panic("Unexpected store size!\n"); 5922657Ssaidi@eecs.umich.edu } 5932657Ssaidi@eecs.umich.edu 5942657Ssaidi@eecs.umich.edu // Stores other than store conditionals are completed at this 5952657Ssaidi@eecs.umich.edu // time. Mark them as completed and, if we have a checker, 5962623SN/A // tell it that the instruction is completed. 5972623SN/A // @todo: Figure out what time I can say stores are complete in 5982623SN/A // the timing memory. 5993349Sbinkertn@umich.edu if (!(req->flags & LOCKED)) { 6002623SN/A storeQueue[storeWBIdx].inst->setCompleted(); 6012623SN/A if (cpu->checker) { 6022623SN/A cpu->checker->tick(storeQueue[storeWBIdx].inst); 6032641Sstever@eecs.umich.edu } 6042623SN/A } 6052623SN/A 6062623SN/A if (dcacheInterface) { 6073222Sktlim@umich.edu assert(!req->completionEvent); 6083222Sktlim@umich.edu StoreCompletionEvent *store_event = new 6093184Srdreslin@umich.edu StoreCompletionEvent(storeWBIdx, NULL, this); 6102623SN/A req->completionEvent = store_event; 6112623SN/A 6123170Sstever@eecs.umich.edu MemAccessResult result = dcacheInterface->access(req); 6133170Sstever@eecs.umich.edu 6143170Sstever@eecs.umich.edu if (isStalled() && 6153170Sstever@eecs.umich.edu storeQueue[storeWBIdx].inst->seqNum == stallingStoreIsn) { 6162644Sstever@eecs.umich.edu DPRINTF(LSQUnit, "Unstalling, stalling store [sn:%lli] " 6172644Sstever@eecs.umich.edu "load idx:%i\n", 6182644Sstever@eecs.umich.edu stallingStoreIsn, stallingLoadIdx); 6193184Srdreslin@umich.edu stalled = false; 6203227Sktlim@umich.edu stallingStoreIsn = 0; 6213201Shsul@eecs.umich.edu iewStage->replayMemInst(loadQueue[stallingLoadIdx]); 6223201Shsul@eecs.umich.edu } 6233201Shsul@eecs.umich.edu 6243201Shsul@eecs.umich.edu typename IEW::LdWritebackEvent *wb = NULL; 6253201Shsul@eecs.umich.edu if (req->flags & LOCKED) { 6263201Shsul@eecs.umich.edu // Stx_C should not generate a system port transaction 6273201Shsul@eecs.umich.edu // if it misses in the cache, but that might be hard 6282644Sstever@eecs.umich.edu // to accomplish without explicit cache support. 6292623SN/A wb = new typename 6302623SN/A IEW::LdWritebackEvent(storeQueue[storeWBIdx].inst, 6312623SN/A iewStage); 6322798Sktlim@umich.edu store_event->wbEvent = wb; 6332839Sktlim@umich.edu } 6342798Sktlim@umich.edu 6352839Sktlim@umich.edu if (result != MA_HIT && dcacheInterface->doEvents()) { 6362901Ssaidi@eecs.umich.edu DPRINTF(LSQUnit,"D-Cache Write Miss on idx:%i!\n", 6372839Sktlim@umich.edu storeWBIdx); 6382798Sktlim@umich.edu 6392623SN/A DPRINTF(Activity, "Active st accessing mem miss [sn:%lli]\n", 6404192Sktlim@umich.edu storeQueue[storeWBIdx].inst->seqNum); 6414192Sktlim@umich.edu 6424192Sktlim@umich.edu //mshrSeqNums.push_back(storeQueue[storeWBIdx].inst->seqNum); 6434192Sktlim@umich.edu 6444192Sktlim@umich.edu //DPRINTF(LSQUnit, "Added MSHR. count = %i\n",mshrSeqNums.size()); 6454192Sktlim@umich.edu 6464192Sktlim@umich.edu // @todo: Increment stat here. 6474192Sktlim@umich.edu } else { 6484192Sktlim@umich.edu DPRINTF(LSQUnit,"D-Cache: Write Hit on idx:%i !\n", 6494192Sktlim@umich.edu storeWBIdx); 6504192Sktlim@umich.edu 6514192Sktlim@umich.edu DPRINTF(Activity, "Active st accessing mem hit [sn:%lli]\n", 6522623SN/A storeQueue[storeWBIdx].inst->seqNum); 6533349Sbinkertn@umich.edu } 6542623SN/A 6553310Srdreslin@umich.edu incrStIdx(storeWBIdx); 6563310Srdreslin@umich.edu } else { 6574584Ssaidi@eecs.umich.edu panic("Must HAVE DCACHE!!!!!\n"); 6582948Ssaidi@eecs.umich.edu } 6593495Sktlim@umich.edu } 6603310Srdreslin@umich.edu 6613310Srdreslin@umich.edu // Not sure this should set it to 0. 6623495Sktlim@umich.edu usedPorts = 0; 6632948Ssaidi@eecs.umich.edu 6643310Srdreslin@umich.edu assert(stores >= 0 && storesToWB >= 0); 6653310Srdreslin@umich.edu} 6664433Ssaidi@eecs.umich.edu 6674433Ssaidi@eecs.umich.edu/*template <class Impl> 6684433Ssaidi@eecs.umich.eduvoid 6694433Ssaidi@eecs.umich.eduLSQUnit<Impl>::removeMSHR(InstSeqNum seqNum) 6704433Ssaidi@eecs.umich.edu{ 6714433Ssaidi@eecs.umich.edu list<InstSeqNum>::iterator mshr_it = find(mshrSeqNums.begin(), 6724433Ssaidi@eecs.umich.edu mshrSeqNums.end(), 6733310Srdreslin@umich.edu seqNum); 6744433Ssaidi@eecs.umich.edu 6754433Ssaidi@eecs.umich.edu if (mshr_it != mshrSeqNums.end()) { 6762948Ssaidi@eecs.umich.edu mshrSeqNums.erase(mshr_it); 6772948Ssaidi@eecs.umich.edu DPRINTF(LSQUnit, "Removing MSHR. count = %i\n",mshrSeqNums.size()); 6782948Ssaidi@eecs.umich.edu } 6792948Ssaidi@eecs.umich.edu}*/ 6802948Ssaidi@eecs.umich.edu 6812630SN/Atemplate <class Impl> 6822623SN/Avoid 6832623SN/ALSQUnit<Impl>::squash(const InstSeqNum &squashed_num) 6842657Ssaidi@eecs.umich.edu{ 6852623SN/A DPRINTF(LSQUnit, "Squashing until [sn:%lli]!" 6862623SN/A "(Loads:%i Stores:%i)\n", squashed_num, loads, stores); 6872623SN/A 6882623SN/A int load_idx = loadTail; 6892623SN/A decrLdIdx(load_idx); 6902623SN/A 6913349Sbinkertn@umich.edu while (loads != 0 && loadQueue[load_idx]->seqNum > squashed_num) { 6922657Ssaidi@eecs.umich.edu DPRINTF(LSQUnit,"Load Instruction PC %#x squashed, " 6932657Ssaidi@eecs.umich.edu "[sn:%lli]\n", 6943170Sstever@eecs.umich.edu loadQueue[load_idx]->readPC(), 6952657Ssaidi@eecs.umich.edu loadQueue[load_idx]->seqNum); 6962657Ssaidi@eecs.umich.edu 6972623SN/A if (isStalled() && load_idx == stallingLoadIdx) { 6982623SN/A stalled = false; 6992623SN/A stallingStoreIsn = 0; 7002623SN/A stallingLoadIdx = 0; 7012623SN/A } 7022623SN/A 7032623SN/A // Clear the smart pointer to make sure it is decremented. 7044762Snate@binkert.org loadQueue[load_idx]->squashed = true; 7054762Snate@binkert.org loadQueue[load_idx] = NULL; 7062623SN/A --loads; 7072623SN/A 7084762Snate@binkert.org // Inefficient! 7092623SN/A loadTail = load_idx; 7102623SN/A 7112623SN/A decrLdIdx(load_idx); 7122623SN/A } 7132623SN/A 7143119Sktlim@umich.edu if (isLoadBlocked) { 7152623SN/A if (squashed_num < blockedLoadSeqNum) { 7162623SN/A isLoadBlocked = false; 7173661Srdreslin@umich.edu loadBlockedHandled = false; 7182623SN/A blockedLoadSeqNum = 0; 7192623SN/A } 7202901Ssaidi@eecs.umich.edu } 7213170Sstever@eecs.umich.edu 7222623SN/A int store_idx = storeTail; 7232623SN/A decrStIdx(store_idx); 7242623SN/A 7252623SN/A while (stores != 0 && 7262623SN/A storeQueue[store_idx].inst->seqNum > squashed_num) { 7273617Sbinkertn@umich.edu // Instructions marked as can WB are already committed. 7283617Sbinkertn@umich.edu if (storeQueue[store_idx].canWB) { 7293617Sbinkertn@umich.edu break; 7302623SN/A } 7314762Snate@binkert.org 7324762Snate@binkert.org DPRINTF(LSQUnit,"Store Instruction PC %#x squashed, " 7334762Snate@binkert.org "idx:%i [sn:%lli]\n", 7342623SN/A storeQueue[store_idx].inst->readPC(), 7352623SN/A store_idx, storeQueue[store_idx].inst->seqNum); 7362623SN/A 7372623SN/A // I don't think this can happen. It should have been cleared 7382623SN/A // 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