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