1/* 2 * Copyright (c) 2011-2012, 2014 ARM Limited 3 * Copyright (c) 2013 Advanced Micro Devices, Inc. 4 * All rights reserved 5 * 6 * The license below extends only to copyright in the software and shall 7 * not be construed as granting a license to any other intellectual 8 * property including but not limited to intellectual property relating 9 * to a hardware implementation of the functionality of the software 10 * licensed hereunder. You may use the software subject to the license 11 * terms below provided that you ensure that this notice is replicated 12 * unmodified and in its entirety in all distributions of the software, 13 * modified or unmodified, in source code or in binary form. 14 * 15 * Copyright (c) 2005-2006 The Regents of The University of Michigan 16 * All rights reserved. 17 * 18 * Redistribution and use in source and binary forms, with or without 19 * modification, are permitted provided that the following conditions are 20 * met: redistributions of source code must retain the above copyright 21 * notice, this list of conditions and the following disclaimer; 22 * redistributions in binary form must reproduce the above copyright 23 * notice, this list of conditions and the following disclaimer in the 24 * documentation and/or other materials provided with the distribution; 25 * neither the name of the copyright holders nor the names of its 26 * contributors may be used to endorse or promote products derived from 27 * this software without specific prior written permission. 28 * 29 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 30 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 31 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 32 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 33 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 34 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 35 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 36 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 37 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 38 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 39 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 40 * 41 * Authors: Korey Sewell 42 */ 43 44#ifndef __CPU_O3_LSQ_IMPL_HH__ 45#define __CPU_O3_LSQ_IMPL_HH__ 46 47#include <algorithm> 48#include <list> 49#include <string> 50 51#include "cpu/o3/lsq.hh" 52#include "debug/Drain.hh" 53#include "debug/Fetch.hh" 54#include "debug/LSQ.hh" 55#include "debug/Writeback.hh" 56#include "params/DerivO3CPU.hh" 57 58using namespace std; 59 60template <class Impl> 61LSQ<Impl>::LSQ(O3CPU *cpu_ptr, IEW *iew_ptr, DerivO3CPUParams *params) 62 : cpu(cpu_ptr), iewStage(iew_ptr), 63 LQEntries(params->LQEntries), 64 SQEntries(params->SQEntries), 65 numThreads(params->numThreads) 66{ 67 assert(numThreads > 0 && numThreads <= Impl::MaxThreads); 68 69 //**********************************************/ 70 //************ Handle SMT Parameters ***********/ 71 //**********************************************/ 72 std::string policy = params->smtLSQPolicy; 73 74 //Convert string to lowercase 75 std::transform(policy.begin(), policy.end(), policy.begin(), 76 (int(*)(int)) tolower); 77 78 //Figure out fetch policy 79 if (policy == "dynamic") { 80 lsqPolicy = Dynamic; 81 82 maxLQEntries = LQEntries; 83 maxSQEntries = SQEntries; 84 85 DPRINTF(LSQ, "LSQ sharing policy set to Dynamic\n"); 86 } else if (policy == "partitioned") { 87 lsqPolicy = Partitioned; 88 89 //@todo:make work if part_amt doesnt divide evenly. 90 maxLQEntries = LQEntries / numThreads; 91 maxSQEntries = SQEntries / numThreads; 92 93 DPRINTF(Fetch, "LSQ sharing policy set to Partitioned: " 94 "%i entries per LQ | %i entries per SQ\n", 95 maxLQEntries,maxSQEntries); 96 } else if (policy == "threshold") { 97 lsqPolicy = Threshold; 98 99 assert(params->smtLSQThreshold > LQEntries); 100 assert(params->smtLSQThreshold > SQEntries); 101 102 //Divide up by threshold amount 103 //@todo: Should threads check the max and the total 104 //amount of the LSQ 105 maxLQEntries = params->smtLSQThreshold; 106 maxSQEntries = params->smtLSQThreshold; 107 108 DPRINTF(LSQ, "LSQ sharing policy set to Threshold: " 109 "%i entries per LQ | %i entries per SQ\n", 110 maxLQEntries,maxSQEntries); 111 } else { 112 assert(0 && "Invalid LSQ Sharing Policy.Options Are:{Dynamic," 113 "Partitioned, Threshold}"); 114 } 115 116 //Initialize LSQs 117 thread = new LSQUnit[numThreads]; 118 for (ThreadID tid = 0; tid < numThreads; tid++) { 119 thread[tid].init(cpu, iew_ptr, params, this, 120 maxLQEntries, maxSQEntries, tid); 121 thread[tid].setDcachePort(&cpu_ptr->getDataPort()); 122 } 123} 124 125 126template<class Impl> 127std::string 128LSQ<Impl>::name() const 129{ 130 return iewStage->name() + ".lsq"; 131} 132 133template<class Impl> 134void 135LSQ<Impl>::regStats() 136{ 137 //Initialize LSQs 138 for (ThreadID tid = 0; tid < numThreads; tid++) { 139 thread[tid].regStats(); 140 } 141} 142 143template<class Impl> 144void 145LSQ<Impl>::setActiveThreads(list<ThreadID> *at_ptr) 146{ 147 activeThreads = at_ptr; 148 assert(activeThreads != 0); 149} 150 151template <class Impl> 152void 153LSQ<Impl>::drainSanityCheck() const 154{ 155 assert(isDrained()); 156 157 for (ThreadID tid = 0; tid < numThreads; tid++) 158 thread[tid].drainSanityCheck(); 159} 160 161template <class Impl> 162bool 163LSQ<Impl>::isDrained() const 164{ 165 bool drained(true); 166 167 if (!lqEmpty()) { 168 DPRINTF(Drain, "Not drained, LQ not empty.\n"); 169 drained = false; 170 } 171 172 if (!sqEmpty()) { 173 DPRINTF(Drain, "Not drained, SQ not empty.\n"); 174 drained = false; 175 } 176 177 return drained; 178} 179 180template <class Impl> 181void 182LSQ<Impl>::takeOverFrom() 183{ 184 for (ThreadID tid = 0; tid < numThreads; tid++) { 185 thread[tid].takeOverFrom(); 186 } 187} 188 189template <class Impl> 190int 191LSQ<Impl>::entryAmount(ThreadID num_threads) 192{ 193 if (lsqPolicy == Partitioned) { 194 return LQEntries / num_threads; 195 } else { 196 return 0; 197 } 198} 199 200template <class Impl> 201void 202LSQ<Impl>::resetEntries() 203{ 204 if (lsqPolicy != Dynamic || numThreads > 1) { 205 int active_threads = activeThreads->size(); 206 207 int maxEntries; 208 209 if (lsqPolicy == Partitioned) { 210 maxEntries = LQEntries / active_threads; 211 } else if (lsqPolicy == Threshold && active_threads == 1) { 212 maxEntries = LQEntries; 213 } else { 214 maxEntries = LQEntries; 215 } 216 217 list<ThreadID>::iterator threads = activeThreads->begin(); 218 list<ThreadID>::iterator end = activeThreads->end(); 219 220 while (threads != end) { 221 ThreadID tid = *threads++; 222 223 resizeEntries(maxEntries, tid); 224 } 225 } 226} 227 228template<class Impl> 229void 230LSQ<Impl>::removeEntries(ThreadID tid) 231{ 232 thread[tid].clearLQ(); 233 thread[tid].clearSQ(); 234} 235 236template<class Impl> 237void 238LSQ<Impl>::resizeEntries(unsigned size, ThreadID tid) 239{ 240 thread[tid].resizeLQ(size); 241 thread[tid].resizeSQ(size); 242} 243 244template<class Impl> 245void 246LSQ<Impl>::tick() 247{ 248 list<ThreadID>::iterator threads = activeThreads->begin(); 249 list<ThreadID>::iterator end = activeThreads->end(); 250 251 while (threads != end) { 252 ThreadID tid = *threads++; 253 254 thread[tid].tick(); 255 } 256} 257 258template<class Impl> 259void 260LSQ<Impl>::insertLoad(DynInstPtr &load_inst) 261{ 262 ThreadID tid = load_inst->threadNumber; 263 264 thread[tid].insertLoad(load_inst); 265} 266 267template<class Impl> 268void 269LSQ<Impl>::insertStore(DynInstPtr &store_inst) 270{ 271 ThreadID tid = store_inst->threadNumber; 272 273 thread[tid].insertStore(store_inst); 274} 275 276template<class Impl> 277Fault 278LSQ<Impl>::executeLoad(DynInstPtr &inst) 279{ 280 ThreadID tid = inst->threadNumber; 281 282 return thread[tid].executeLoad(inst); 283} 284 285template<class Impl> 286Fault 287LSQ<Impl>::executeStore(DynInstPtr &inst) 288{ 289 ThreadID tid = inst->threadNumber; 290 291 return thread[tid].executeStore(inst); 292} 293 294template<class Impl> 295void 296LSQ<Impl>::writebackStores() 297{ 298 list<ThreadID>::iterator threads = activeThreads->begin(); 299 list<ThreadID>::iterator end = activeThreads->end(); 300 301 while (threads != end) { 302 ThreadID tid = *threads++; 303 304 if (numStoresToWB(tid) > 0) { 305 DPRINTF(Writeback,"[tid:%i] Writing back stores. %i stores " 306 "available for Writeback.\n", tid, numStoresToWB(tid)); 307 } 308 309 thread[tid].writebackStores(); 310 } 311} 312 313template<class Impl> 314bool 315LSQ<Impl>::violation() 316{ 317 /* Answers: Does Anybody Have a Violation?*/ 318 list<ThreadID>::iterator threads = activeThreads->begin(); 319 list<ThreadID>::iterator end = activeThreads->end(); 320 321 while (threads != end) { 322 ThreadID tid = *threads++; 323 324 if (thread[tid].violation()) 325 return true; 326 } 327 328 return false; 329} 330 331template <class Impl> 332void 333LSQ<Impl>::recvRetry() 334{ 335 iewStage->cacheUnblocked(); 336 337 for (ThreadID tid : *activeThreads) { 338 thread[tid].recvRetry(); 339 } 340} 341 342template <class Impl> 343bool 344LSQ<Impl>::recvTimingResp(PacketPtr pkt) 345{ 346 if (pkt->isError()) 347 DPRINTF(LSQ, "Got error packet back for address: %#X\n", 348 pkt->getAddr()); 349 thread[pkt->req->threadId()].completeDataAccess(pkt);
| 1/* 2 * Copyright (c) 2011-2012, 2014 ARM Limited 3 * Copyright (c) 2013 Advanced Micro Devices, Inc. 4 * All rights reserved 5 * 6 * The license below extends only to copyright in the software and shall 7 * not be construed as granting a license to any other intellectual 8 * property including but not limited to intellectual property relating 9 * to a hardware implementation of the functionality of the software 10 * licensed hereunder. You may use the software subject to the license 11 * terms below provided that you ensure that this notice is replicated 12 * unmodified and in its entirety in all distributions of the software, 13 * modified or unmodified, in source code or in binary form. 14 * 15 * Copyright (c) 2005-2006 The Regents of The University of Michigan 16 * All rights reserved. 17 * 18 * Redistribution and use in source and binary forms, with or without 19 * modification, are permitted provided that the following conditions are 20 * met: redistributions of source code must retain the above copyright 21 * notice, this list of conditions and the following disclaimer; 22 * redistributions in binary form must reproduce the above copyright 23 * notice, this list of conditions and the following disclaimer in the 24 * documentation and/or other materials provided with the distribution; 25 * neither the name of the copyright holders nor the names of its 26 * contributors may be used to endorse or promote products derived from 27 * this software without specific prior written permission. 28 * 29 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 30 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 31 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 32 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 33 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 34 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 35 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 36 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 37 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 38 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 39 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 40 * 41 * Authors: Korey Sewell 42 */ 43 44#ifndef __CPU_O3_LSQ_IMPL_HH__ 45#define __CPU_O3_LSQ_IMPL_HH__ 46 47#include <algorithm> 48#include <list> 49#include <string> 50 51#include "cpu/o3/lsq.hh" 52#include "debug/Drain.hh" 53#include "debug/Fetch.hh" 54#include "debug/LSQ.hh" 55#include "debug/Writeback.hh" 56#include "params/DerivO3CPU.hh" 57 58using namespace std; 59 60template <class Impl> 61LSQ<Impl>::LSQ(O3CPU *cpu_ptr, IEW *iew_ptr, DerivO3CPUParams *params) 62 : cpu(cpu_ptr), iewStage(iew_ptr), 63 LQEntries(params->LQEntries), 64 SQEntries(params->SQEntries), 65 numThreads(params->numThreads) 66{ 67 assert(numThreads > 0 && numThreads <= Impl::MaxThreads); 68 69 //**********************************************/ 70 //************ Handle SMT Parameters ***********/ 71 //**********************************************/ 72 std::string policy = params->smtLSQPolicy; 73 74 //Convert string to lowercase 75 std::transform(policy.begin(), policy.end(), policy.begin(), 76 (int(*)(int)) tolower); 77 78 //Figure out fetch policy 79 if (policy == "dynamic") { 80 lsqPolicy = Dynamic; 81 82 maxLQEntries = LQEntries; 83 maxSQEntries = SQEntries; 84 85 DPRINTF(LSQ, "LSQ sharing policy set to Dynamic\n"); 86 } else if (policy == "partitioned") { 87 lsqPolicy = Partitioned; 88 89 //@todo:make work if part_amt doesnt divide evenly. 90 maxLQEntries = LQEntries / numThreads; 91 maxSQEntries = SQEntries / numThreads; 92 93 DPRINTF(Fetch, "LSQ sharing policy set to Partitioned: " 94 "%i entries per LQ | %i entries per SQ\n", 95 maxLQEntries,maxSQEntries); 96 } else if (policy == "threshold") { 97 lsqPolicy = Threshold; 98 99 assert(params->smtLSQThreshold > LQEntries); 100 assert(params->smtLSQThreshold > SQEntries); 101 102 //Divide up by threshold amount 103 //@todo: Should threads check the max and the total 104 //amount of the LSQ 105 maxLQEntries = params->smtLSQThreshold; 106 maxSQEntries = params->smtLSQThreshold; 107 108 DPRINTF(LSQ, "LSQ sharing policy set to Threshold: " 109 "%i entries per LQ | %i entries per SQ\n", 110 maxLQEntries,maxSQEntries); 111 } else { 112 assert(0 && "Invalid LSQ Sharing Policy.Options Are:{Dynamic," 113 "Partitioned, Threshold}"); 114 } 115 116 //Initialize LSQs 117 thread = new LSQUnit[numThreads]; 118 for (ThreadID tid = 0; tid < numThreads; tid++) { 119 thread[tid].init(cpu, iew_ptr, params, this, 120 maxLQEntries, maxSQEntries, tid); 121 thread[tid].setDcachePort(&cpu_ptr->getDataPort()); 122 } 123} 124 125 126template<class Impl> 127std::string 128LSQ<Impl>::name() const 129{ 130 return iewStage->name() + ".lsq"; 131} 132 133template<class Impl> 134void 135LSQ<Impl>::regStats() 136{ 137 //Initialize LSQs 138 for (ThreadID tid = 0; tid < numThreads; tid++) { 139 thread[tid].regStats(); 140 } 141} 142 143template<class Impl> 144void 145LSQ<Impl>::setActiveThreads(list<ThreadID> *at_ptr) 146{ 147 activeThreads = at_ptr; 148 assert(activeThreads != 0); 149} 150 151template <class Impl> 152void 153LSQ<Impl>::drainSanityCheck() const 154{ 155 assert(isDrained()); 156 157 for (ThreadID tid = 0; tid < numThreads; tid++) 158 thread[tid].drainSanityCheck(); 159} 160 161template <class Impl> 162bool 163LSQ<Impl>::isDrained() const 164{ 165 bool drained(true); 166 167 if (!lqEmpty()) { 168 DPRINTF(Drain, "Not drained, LQ not empty.\n"); 169 drained = false; 170 } 171 172 if (!sqEmpty()) { 173 DPRINTF(Drain, "Not drained, SQ not empty.\n"); 174 drained = false; 175 } 176 177 return drained; 178} 179 180template <class Impl> 181void 182LSQ<Impl>::takeOverFrom() 183{ 184 for (ThreadID tid = 0; tid < numThreads; tid++) { 185 thread[tid].takeOverFrom(); 186 } 187} 188 189template <class Impl> 190int 191LSQ<Impl>::entryAmount(ThreadID num_threads) 192{ 193 if (lsqPolicy == Partitioned) { 194 return LQEntries / num_threads; 195 } else { 196 return 0; 197 } 198} 199 200template <class Impl> 201void 202LSQ<Impl>::resetEntries() 203{ 204 if (lsqPolicy != Dynamic || numThreads > 1) { 205 int active_threads = activeThreads->size(); 206 207 int maxEntries; 208 209 if (lsqPolicy == Partitioned) { 210 maxEntries = LQEntries / active_threads; 211 } else if (lsqPolicy == Threshold && active_threads == 1) { 212 maxEntries = LQEntries; 213 } else { 214 maxEntries = LQEntries; 215 } 216 217 list<ThreadID>::iterator threads = activeThreads->begin(); 218 list<ThreadID>::iterator end = activeThreads->end(); 219 220 while (threads != end) { 221 ThreadID tid = *threads++; 222 223 resizeEntries(maxEntries, tid); 224 } 225 } 226} 227 228template<class Impl> 229void 230LSQ<Impl>::removeEntries(ThreadID tid) 231{ 232 thread[tid].clearLQ(); 233 thread[tid].clearSQ(); 234} 235 236template<class Impl> 237void 238LSQ<Impl>::resizeEntries(unsigned size, ThreadID tid) 239{ 240 thread[tid].resizeLQ(size); 241 thread[tid].resizeSQ(size); 242} 243 244template<class Impl> 245void 246LSQ<Impl>::tick() 247{ 248 list<ThreadID>::iterator threads = activeThreads->begin(); 249 list<ThreadID>::iterator end = activeThreads->end(); 250 251 while (threads != end) { 252 ThreadID tid = *threads++; 253 254 thread[tid].tick(); 255 } 256} 257 258template<class Impl> 259void 260LSQ<Impl>::insertLoad(DynInstPtr &load_inst) 261{ 262 ThreadID tid = load_inst->threadNumber; 263 264 thread[tid].insertLoad(load_inst); 265} 266 267template<class Impl> 268void 269LSQ<Impl>::insertStore(DynInstPtr &store_inst) 270{ 271 ThreadID tid = store_inst->threadNumber; 272 273 thread[tid].insertStore(store_inst); 274} 275 276template<class Impl> 277Fault 278LSQ<Impl>::executeLoad(DynInstPtr &inst) 279{ 280 ThreadID tid = inst->threadNumber; 281 282 return thread[tid].executeLoad(inst); 283} 284 285template<class Impl> 286Fault 287LSQ<Impl>::executeStore(DynInstPtr &inst) 288{ 289 ThreadID tid = inst->threadNumber; 290 291 return thread[tid].executeStore(inst); 292} 293 294template<class Impl> 295void 296LSQ<Impl>::writebackStores() 297{ 298 list<ThreadID>::iterator threads = activeThreads->begin(); 299 list<ThreadID>::iterator end = activeThreads->end(); 300 301 while (threads != end) { 302 ThreadID tid = *threads++; 303 304 if (numStoresToWB(tid) > 0) { 305 DPRINTF(Writeback,"[tid:%i] Writing back stores. %i stores " 306 "available for Writeback.\n", tid, numStoresToWB(tid)); 307 } 308 309 thread[tid].writebackStores(); 310 } 311} 312 313template<class Impl> 314bool 315LSQ<Impl>::violation() 316{ 317 /* Answers: Does Anybody Have a Violation?*/ 318 list<ThreadID>::iterator threads = activeThreads->begin(); 319 list<ThreadID>::iterator end = activeThreads->end(); 320 321 while (threads != end) { 322 ThreadID tid = *threads++; 323 324 if (thread[tid].violation()) 325 return true; 326 } 327 328 return false; 329} 330 331template <class Impl> 332void 333LSQ<Impl>::recvRetry() 334{ 335 iewStage->cacheUnblocked(); 336 337 for (ThreadID tid : *activeThreads) { 338 thread[tid].recvRetry(); 339 } 340} 341 342template <class Impl> 343bool 344LSQ<Impl>::recvTimingResp(PacketPtr pkt) 345{ 346 if (pkt->isError()) 347 DPRINTF(LSQ, "Got error packet back for address: %#X\n", 348 pkt->getAddr()); 349 thread[pkt->req->threadId()].completeDataAccess(pkt);
|