lsq_impl.hh revision 2689
12292SN/A/* 22329SN/A * Copyright (c) 2004-2006 The Regents of The University of Michigan 32292SN/A * All rights reserved. 42292SN/A * 52292SN/A * Redistribution and use in source and binary forms, with or without 62292SN/A * modification, are permitted provided that the following conditions are 72292SN/A * met: redistributions of source code must retain the above copyright 82292SN/A * notice, this list of conditions and the following disclaimer; 92292SN/A * redistributions in binary form must reproduce the above copyright 102292SN/A * notice, this list of conditions and the following disclaimer in the 112292SN/A * documentation and/or other materials provided with the distribution; 122292SN/A * neither the name of the copyright holders nor the names of its 132292SN/A * contributors may be used to endorse or promote products derived from 142292SN/A * this software without specific prior written permission. 152292SN/A * 162292SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 172292SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 182292SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 192292SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 202292SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 212292SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 222292SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 232292SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 242292SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 252292SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 262292SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 272689Sktlim@umich.edu * 282689Sktlim@umich.edu * Authors: Korey Sewell 292292SN/A */ 302292SN/A 312329SN/A#include <algorithm> 322329SN/A#include <string> 332329SN/A 342292SN/A#include "cpu/o3/lsq.hh" 352292SN/A 362292SN/Ausing namespace std; 372292SN/A 382292SN/Atemplate <class Impl> 392292SN/ALSQ<Impl>::LSQ(Params *params) 402292SN/A : LQEntries(params->LQEntries), SQEntries(params->SQEntries), 412292SN/A numThreads(params->numberOfThreads) 422292SN/A{ 432292SN/A DPRINTF(LSQ, "Creating LSQ object.\n"); 442292SN/A 452292SN/A //**********************************************/ 462292SN/A //************ Handle SMT Parameters ***********/ 472292SN/A //**********************************************/ 482292SN/A string policy = params->smtLSQPolicy; 492292SN/A 502292SN/A //Convert string to lowercase 512292SN/A std::transform(policy.begin(), policy.end(), policy.begin(), 522292SN/A (int(*)(int)) tolower); 532292SN/A 542292SN/A //Figure out fetch policy 552292SN/A if (policy == "dynamic") { 562292SN/A lsqPolicy = Dynamic; 572292SN/A 582292SN/A maxLQEntries = LQEntries; 592292SN/A maxSQEntries = SQEntries; 602292SN/A 612292SN/A DPRINTF(LSQ, "LSQ sharing policy set to Dynamic\n"); 622292SN/A 632292SN/A } else if (policy == "partitioned") { 642292SN/A lsqPolicy = Partitioned; 652292SN/A 662292SN/A //@todo:make work if part_amt doesnt divide evenly. 672292SN/A maxLQEntries = LQEntries / numThreads; 682292SN/A maxSQEntries = SQEntries / numThreads; 692292SN/A 702292SN/A DPRINTF(Fetch, "LSQ sharing policy set to Partitioned: " 712292SN/A "%i entries per LQ | %i entries per SQ", 722292SN/A maxLQEntries,maxSQEntries); 732292SN/A 742292SN/A } else if (policy == "threshold") { 752292SN/A lsqPolicy = Threshold; 762292SN/A 772292SN/A assert(params->smtLSQThreshold > LQEntries); 782292SN/A assert(params->smtLSQThreshold > SQEntries); 792292SN/A 802292SN/A //Divide up by threshold amount 812292SN/A //@todo: Should threads check the max and the total 822292SN/A //amount of the LSQ 832292SN/A maxLQEntries = params->smtLSQThreshold; 842292SN/A maxSQEntries = params->smtLSQThreshold; 852292SN/A 862292SN/A DPRINTF(LSQ, "LSQ sharing policy set to Threshold: " 872292SN/A "%i entries per LQ | %i entries per SQ", 882292SN/A maxLQEntries,maxSQEntries); 892292SN/A 902292SN/A } else { 912292SN/A assert(0 && "Invalid LSQ Sharing Policy.Options Are:{Dynamic," 922292SN/A "Partitioned, Threshold}"); 932292SN/A } 942292SN/A 952292SN/A //Initialize LSQs 962292SN/A for (int tid=0; tid < numThreads; tid++) { 972329SN/A thread[tid].init(params, maxLQEntries, maxSQEntries, tid); 982292SN/A } 992292SN/A} 1002292SN/A 1012292SN/A 1022292SN/Atemplate<class Impl> 1032292SN/Astd::string 1042292SN/ALSQ<Impl>::name() const 1052292SN/A{ 1062292SN/A return iewStage->name() + ".lsq"; 1072292SN/A} 1082292SN/A 1092292SN/Atemplate<class Impl> 1102292SN/Avoid 1112292SN/ALSQ<Impl>::setActiveThreads(list<unsigned> *at_ptr) 1122292SN/A{ 1132292SN/A activeThreads = at_ptr; 1142292SN/A assert(activeThreads != 0); 1152292SN/A} 1162292SN/A 1172292SN/Atemplate<class Impl> 1182292SN/Avoid 1192292SN/ALSQ<Impl>::setCPU(FullCPU *cpu_ptr) 1202292SN/A{ 1212292SN/A cpu = cpu_ptr; 1222292SN/A 1232292SN/A for (int tid=0; tid < numThreads; tid++) { 1242292SN/A thread[tid].setCPU(cpu_ptr); 1252292SN/A } 1262292SN/A} 1272292SN/A 1282292SN/Atemplate<class Impl> 1292292SN/Avoid 1302292SN/ALSQ<Impl>::setIEW(IEW *iew_ptr) 1312292SN/A{ 1322292SN/A iewStage = iew_ptr; 1332292SN/A 1342292SN/A for (int tid=0; tid < numThreads; tid++) { 1352292SN/A thread[tid].setIEW(iew_ptr); 1362292SN/A } 1372292SN/A} 1382292SN/A 1392292SN/A#if 0 1402292SN/Atemplate<class Impl> 1412292SN/Avoid 1422292SN/ALSQ<Impl>::setPageTable(PageTable *pt_ptr) 1432292SN/A{ 1442292SN/A for (int tid=0; tid < numThreads; tid++) { 1452292SN/A thread[tid].setPageTable(pt_ptr); 1462292SN/A } 1472292SN/A} 1482292SN/A#endif 1492292SN/A 1502292SN/Atemplate <class Impl> 1512307SN/Avoid 1522307SN/ALSQ<Impl>::switchOut() 1532307SN/A{ 1542307SN/A for (int tid = 0; tid < numThreads; tid++) { 1552307SN/A thread[tid].switchOut(); 1562307SN/A } 1572307SN/A} 1582307SN/A 1592307SN/Atemplate <class Impl> 1602307SN/Avoid 1612307SN/ALSQ<Impl>::takeOverFrom() 1622307SN/A{ 1632307SN/A for (int tid = 0; tid < numThreads; tid++) { 1642307SN/A thread[tid].takeOverFrom(); 1652307SN/A } 1662307SN/A} 1672307SN/A 1682307SN/Atemplate <class Impl> 1692292SN/Aint 1702292SN/ALSQ<Impl>::entryAmount(int num_threads) 1712292SN/A{ 1722292SN/A if (lsqPolicy == Partitioned) { 1732292SN/A return LQEntries / num_threads; 1742292SN/A } else { 1752292SN/A return 0; 1762292SN/A } 1772292SN/A} 1782292SN/A 1792292SN/Atemplate <class Impl> 1802292SN/Avoid 1812292SN/ALSQ<Impl>::resetEntries() 1822292SN/A{ 1832292SN/A if (lsqPolicy != Dynamic || numThreads > 1) { 1842292SN/A int active_threads = (*activeThreads).size(); 1852292SN/A 1862292SN/A list<unsigned>::iterator threads = (*activeThreads).begin(); 1872292SN/A list<unsigned>::iterator list_end = (*activeThreads).end(); 1882292SN/A 1892292SN/A int maxEntries; 1902292SN/A 1912292SN/A if (lsqPolicy == Partitioned) { 1922292SN/A maxEntries = LQEntries / active_threads; 1932292SN/A } else if (lsqPolicy == Threshold && active_threads == 1) { 1942292SN/A maxEntries = LQEntries; 1952292SN/A } else { 1962292SN/A maxEntries = LQEntries; 1972292SN/A } 1982292SN/A 1992292SN/A while (threads != list_end) { 2002292SN/A resizeEntries(maxEntries,*threads++); 2012292SN/A } 2022292SN/A } 2032292SN/A} 2042292SN/A 2052292SN/Atemplate<class Impl> 2062292SN/Avoid 2072292SN/ALSQ<Impl>::removeEntries(unsigned tid) 2082292SN/A{ 2092292SN/A thread[tid].clearLQ(); 2102292SN/A thread[tid].clearSQ(); 2112292SN/A} 2122292SN/A 2132292SN/Atemplate<class Impl> 2142292SN/Avoid 2152292SN/ALSQ<Impl>::resizeEntries(unsigned size,unsigned tid) 2162292SN/A{ 2172292SN/A thread[tid].resizeLQ(size); 2182292SN/A thread[tid].resizeSQ(size); 2192292SN/A} 2202292SN/A 2212292SN/Atemplate<class Impl> 2222292SN/Avoid 2232292SN/ALSQ<Impl>::tick() 2242292SN/A{ 2252292SN/A list<unsigned>::iterator active_threads = (*activeThreads).begin(); 2262292SN/A 2272292SN/A while (active_threads != (*activeThreads).end()) { 2282292SN/A unsigned tid = *active_threads++; 2292292SN/A 2302292SN/A thread[tid].tick(); 2312292SN/A } 2322292SN/A} 2332292SN/A 2342292SN/Atemplate<class Impl> 2352292SN/Avoid 2362292SN/ALSQ<Impl>::insertLoad(DynInstPtr &load_inst) 2372292SN/A{ 2382292SN/A unsigned tid = load_inst->threadNumber; 2392292SN/A 2402292SN/A thread[tid].insertLoad(load_inst); 2412292SN/A} 2422292SN/A 2432292SN/Atemplate<class Impl> 2442292SN/Avoid 2452292SN/ALSQ<Impl>::insertStore(DynInstPtr &store_inst) 2462292SN/A{ 2472292SN/A unsigned tid = store_inst->threadNumber; 2482292SN/A 2492292SN/A thread[tid].insertStore(store_inst); 2502292SN/A} 2512292SN/A 2522292SN/Atemplate<class Impl> 2532292SN/AFault 2542292SN/ALSQ<Impl>::executeLoad(DynInstPtr &inst) 2552292SN/A{ 2562292SN/A unsigned tid = inst->threadNumber; 2572292SN/A 2582292SN/A return thread[tid].executeLoad(inst); 2592292SN/A} 2602292SN/A 2612292SN/Atemplate<class Impl> 2622292SN/AFault 2632292SN/ALSQ<Impl>::executeStore(DynInstPtr &inst) 2642292SN/A{ 2652292SN/A unsigned tid = inst->threadNumber; 2662292SN/A 2672292SN/A return thread[tid].executeStore(inst); 2682292SN/A} 2692292SN/A 2702292SN/Atemplate<class Impl> 2712292SN/Avoid 2722292SN/ALSQ<Impl>::writebackStores() 2732292SN/A{ 2742292SN/A list<unsigned>::iterator active_threads = (*activeThreads).begin(); 2752292SN/A 2762292SN/A while (active_threads != (*activeThreads).end()) { 2772292SN/A unsigned tid = *active_threads++; 2782292SN/A 2792292SN/A if (numStoresToWB(tid) > 0) { 2802329SN/A DPRINTF(Writeback,"[tid:%i] Writing back stores. %i stores " 2812329SN/A "available for Writeback.\n", tid, numStoresToWB(tid)); 2822292SN/A } 2832292SN/A 2842292SN/A thread[tid].writebackStores(); 2852292SN/A } 2862292SN/A} 2872292SN/A 2882292SN/Atemplate<class Impl> 2892292SN/Abool 2902292SN/ALSQ<Impl>::violation() 2912292SN/A{ 2922292SN/A /* Answers: Does Anybody Have a Violation?*/ 2932292SN/A list<unsigned>::iterator active_threads = (*activeThreads).begin(); 2942292SN/A 2952292SN/A while (active_threads != (*activeThreads).end()) { 2962292SN/A unsigned tid = *active_threads++; 2972292SN/A if (thread[tid].violation()) 2982292SN/A return true; 2992292SN/A } 3002292SN/A 3012292SN/A return false; 3022292SN/A} 3032292SN/A 3042292SN/Atemplate<class Impl> 3052292SN/Aint 3062292SN/ALSQ<Impl>::getCount() 3072292SN/A{ 3082292SN/A unsigned total = 0; 3092292SN/A 3102292SN/A list<unsigned>::iterator active_threads = (*activeThreads).begin(); 3112292SN/A 3122292SN/A while (active_threads != (*activeThreads).end()) { 3132292SN/A unsigned tid = *active_threads++; 3142292SN/A total += getCount(tid); 3152292SN/A } 3162292SN/A 3172292SN/A return total; 3182292SN/A} 3192292SN/A 3202292SN/Atemplate<class Impl> 3212292SN/Aint 3222292SN/ALSQ<Impl>::numLoads() 3232292SN/A{ 3242292SN/A unsigned total = 0; 3252292SN/A 3262292SN/A list<unsigned>::iterator active_threads = (*activeThreads).begin(); 3272292SN/A 3282292SN/A while (active_threads != (*activeThreads).end()) { 3292292SN/A unsigned tid = *active_threads++; 3302292SN/A total += numLoads(tid); 3312292SN/A } 3322292SN/A 3332292SN/A return total; 3342292SN/A} 3352292SN/A 3362292SN/Atemplate<class Impl> 3372292SN/Aint 3382292SN/ALSQ<Impl>::numStores() 3392292SN/A{ 3402292SN/A unsigned total = 0; 3412292SN/A 3422292SN/A list<unsigned>::iterator active_threads = (*activeThreads).begin(); 3432292SN/A 3442292SN/A while (active_threads != (*activeThreads).end()) { 3452292SN/A unsigned tid = *active_threads++; 3462292SN/A total += thread[tid].numStores(); 3472292SN/A } 3482292SN/A 3492292SN/A return total; 3502292SN/A} 3512292SN/A 3522292SN/Atemplate<class Impl> 3532292SN/Aint 3542292SN/ALSQ<Impl>::numLoadsReady() 3552292SN/A{ 3562292SN/A unsigned total = 0; 3572292SN/A 3582292SN/A list<unsigned>::iterator active_threads = (*activeThreads).begin(); 3592292SN/A 3602292SN/A while (active_threads != (*activeThreads).end()) { 3612292SN/A unsigned tid = *active_threads++; 3622292SN/A total += thread[tid].numLoadsReady(); 3632292SN/A } 3642292SN/A 3652292SN/A return total; 3662292SN/A} 3672292SN/A 3682292SN/Atemplate<class Impl> 3692292SN/Aunsigned 3702292SN/ALSQ<Impl>::numFreeEntries() 3712292SN/A{ 3722292SN/A unsigned total = 0; 3732292SN/A 3742292SN/A list<unsigned>::iterator active_threads = (*activeThreads).begin(); 3752292SN/A 3762292SN/A while (active_threads != (*activeThreads).end()) { 3772292SN/A unsigned tid = *active_threads++; 3782292SN/A total += thread[tid].numFreeEntries(); 3792292SN/A } 3802292SN/A 3812292SN/A return total; 3822292SN/A} 3832292SN/A 3842292SN/Atemplate<class Impl> 3852292SN/Aunsigned 3862292SN/ALSQ<Impl>::numFreeEntries(unsigned tid) 3872292SN/A{ 3882292SN/A //if( lsqPolicy == Dynamic ) 3892292SN/A //return numFreeEntries(); 3902292SN/A //else 3912292SN/A return thread[tid].numFreeEntries(); 3922292SN/A} 3932292SN/A 3942292SN/Atemplate<class Impl> 3952292SN/Abool 3962292SN/ALSQ<Impl>::isFull() 3972292SN/A{ 3982292SN/A list<unsigned>::iterator active_threads = (*activeThreads).begin(); 3992292SN/A 4002292SN/A while (active_threads != (*activeThreads).end()) { 4012292SN/A unsigned tid = *active_threads++; 4022292SN/A if (! (thread[tid].lqFull() || thread[tid].sqFull()) ) 4032292SN/A return false; 4042292SN/A } 4052292SN/A 4062292SN/A return true; 4072292SN/A} 4082292SN/A 4092292SN/Atemplate<class Impl> 4102292SN/Abool 4112292SN/ALSQ<Impl>::isFull(unsigned tid) 4122292SN/A{ 4132292SN/A //@todo: Change to Calculate All Entries for 4142292SN/A //Dynamic Policy 4152292SN/A if( lsqPolicy == Dynamic ) 4162292SN/A return isFull(); 4172292SN/A else 4182292SN/A return thread[tid].lqFull() || thread[tid].sqFull(); 4192292SN/A} 4202292SN/A 4212292SN/Atemplate<class Impl> 4222292SN/Abool 4232292SN/ALSQ<Impl>::lqFull() 4242292SN/A{ 4252292SN/A list<unsigned>::iterator active_threads = (*activeThreads).begin(); 4262292SN/A 4272292SN/A while (active_threads != (*activeThreads).end()) { 4282292SN/A unsigned tid = *active_threads++; 4292292SN/A if (!thread[tid].lqFull()) 4302292SN/A return false; 4312292SN/A } 4322292SN/A 4332292SN/A return true; 4342292SN/A} 4352292SN/A 4362292SN/Atemplate<class Impl> 4372292SN/Abool 4382292SN/ALSQ<Impl>::lqFull(unsigned tid) 4392292SN/A{ 4402292SN/A //@todo: Change to Calculate All Entries for 4412292SN/A //Dynamic Policy 4422292SN/A if( lsqPolicy == Dynamic ) 4432292SN/A return lqFull(); 4442292SN/A else 4452292SN/A return thread[tid].lqFull(); 4462292SN/A} 4472292SN/A 4482292SN/Atemplate<class Impl> 4492292SN/Abool 4502292SN/ALSQ<Impl>::sqFull() 4512292SN/A{ 4522292SN/A list<unsigned>::iterator active_threads = (*activeThreads).begin(); 4532292SN/A 4542292SN/A while (active_threads != (*activeThreads).end()) { 4552292SN/A unsigned tid = *active_threads++; 4562292SN/A if (!sqFull(tid)) 4572292SN/A return false; 4582292SN/A } 4592292SN/A 4602292SN/A return true; 4612292SN/A} 4622292SN/A 4632292SN/Atemplate<class Impl> 4642292SN/Abool 4652292SN/ALSQ<Impl>::sqFull(unsigned tid) 4662292SN/A{ 4672292SN/A //@todo: Change to Calculate All Entries for 4682292SN/A //Dynamic Policy 4692292SN/A if( lsqPolicy == Dynamic ) 4702292SN/A return sqFull(); 4712292SN/A else 4722292SN/A return thread[tid].sqFull(); 4732292SN/A} 4742292SN/A 4752292SN/Atemplate<class Impl> 4762292SN/Abool 4772292SN/ALSQ<Impl>::isStalled() 4782292SN/A{ 4792292SN/A list<unsigned>::iterator active_threads = (*activeThreads).begin(); 4802292SN/A 4812292SN/A while (active_threads != (*activeThreads).end()) { 4822292SN/A unsigned tid = *active_threads++; 4832292SN/A if (!thread[tid].isStalled()) 4842292SN/A return false; 4852292SN/A } 4862292SN/A 4872292SN/A return true; 4882292SN/A} 4892292SN/A 4902292SN/Atemplate<class Impl> 4912292SN/Abool 4922292SN/ALSQ<Impl>::isStalled(unsigned tid) 4932292SN/A{ 4942292SN/A if( lsqPolicy == Dynamic ) 4952292SN/A return isStalled(); 4962292SN/A else 4972292SN/A return thread[tid].isStalled(); 4982292SN/A} 4992292SN/A 5002292SN/Atemplate<class Impl> 5012292SN/Abool 5022292SN/ALSQ<Impl>::hasStoresToWB() 5032292SN/A{ 5042292SN/A list<unsigned>::iterator active_threads = (*activeThreads).begin(); 5052292SN/A 5062292SN/A while (active_threads != (*activeThreads).end()) { 5072292SN/A unsigned tid = *active_threads++; 5082292SN/A if (!hasStoresToWB(tid)) 5092292SN/A return false; 5102292SN/A } 5112292SN/A 5122292SN/A return true; 5132292SN/A} 5142292SN/A 5152292SN/Atemplate<class Impl> 5162292SN/Abool 5172292SN/ALSQ<Impl>::willWB() 5182292SN/A{ 5192292SN/A list<unsigned>::iterator active_threads = (*activeThreads).begin(); 5202292SN/A 5212292SN/A while (active_threads != (*activeThreads).end()) { 5222292SN/A unsigned tid = *active_threads++; 5232292SN/A if (!willWB(tid)) 5242292SN/A return false; 5252292SN/A } 5262292SN/A 5272292SN/A return true; 5282292SN/A} 5292292SN/A 5302292SN/Atemplate<class Impl> 5312292SN/Avoid 5322292SN/ALSQ<Impl>::dumpInsts() 5332292SN/A{ 5342292SN/A list<unsigned>::iterator active_threads = (*activeThreads).begin(); 5352292SN/A 5362292SN/A while (active_threads != (*activeThreads).end()) { 5372292SN/A unsigned tid = *active_threads++; 5382292SN/A thread[tid].dumpInsts(); 5392292SN/A } 5402292SN/A} 541