lsq_impl.hh (3125:febd811bccc6) | lsq_impl.hh (3126:756092c6383c) |
---|---|
1/* 2 * Copyright (c) 2005-2006 The Regents of The University of Michigan 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are 7 * met: redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer; 9 * redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution; 12 * neither the name of the copyright holders nor the names of its 13 * contributors may be used to endorse or promote products derived from 14 * this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 * 28 * Authors: Korey Sewell 29 */ 30 31#include <algorithm> 32#include <list> 33#include <string> 34 35#include "cpu/o3/lsq.hh" 36 37template <class Impl> 38Tick 39LSQ<Impl>::DcachePort::recvAtomic(PacketPtr pkt) 40{ 41 panic("O3CPU model does not work with atomic mode!"); 42 return curTick; 43} 44 45template <class Impl> 46void 47LSQ<Impl>::DcachePort::recvFunctional(PacketPtr pkt) 48{ 49 panic("O3CPU doesn't expect recvFunctional callback!"); 50} 51 52template <class Impl> 53void 54LSQ<Impl>::DcachePort::recvStatusChange(Status status) 55{ 56 if (status == RangeChange) 57 return; 58 59 panic("O3CPU doesn't expect recvStatusChange callback!"); 60} 61 62template <class Impl> 63bool 64LSQ<Impl>::DcachePort::recvTiming(PacketPtr pkt) 65{ 66 lsq->thread[pkt->req->getThreadNum()].completeDataAccess(pkt); 67 return true; 68} 69 70template <class Impl> 71void 72LSQ<Impl>::DcachePort::recvRetry() 73{ 74 if (lsq->retryTid == -1) 75 { 76 //Squashed, so drop it 77 return; 78 } 79 lsq->thread[lsq->retryTid].recvRetry(); 80 // Speculatively clear the retry Tid. This will get set again if 81 // the LSQUnit was unable to complete its access. 82 lsq->retryTid = -1; 83} 84 85template <class Impl> 86LSQ<Impl>::LSQ(Params *params) 87 : dcachePort(this), LQEntries(params->LQEntries), 88 SQEntries(params->SQEntries), numThreads(params->numberOfThreads), 89 retryTid(-1) 90{ 91 DPRINTF(LSQ, "Creating LSQ object.\n"); 92 93 //**********************************************/ 94 //************ Handle SMT Parameters ***********/ 95 //**********************************************/ 96 std::string policy = params->smtLSQPolicy; 97 98 //Convert string to lowercase 99 std::transform(policy.begin(), policy.end(), policy.begin(), 100 (int(*)(int)) tolower); 101 102 //Figure out fetch policy 103 if (policy == "dynamic") { 104 lsqPolicy = Dynamic; 105 106 maxLQEntries = LQEntries; 107 maxSQEntries = SQEntries; 108 109 DPRINTF(LSQ, "LSQ sharing policy set to Dynamic\n"); 110 111 } else if (policy == "partitioned") { 112 lsqPolicy = Partitioned; 113 114 //@todo:make work if part_amt doesnt divide evenly. 115 maxLQEntries = LQEntries / numThreads; 116 maxSQEntries = SQEntries / numThreads; 117 118 DPRINTF(Fetch, "LSQ sharing policy set to Partitioned: " 119 "%i entries per LQ | %i entries per SQ", 120 maxLQEntries,maxSQEntries); 121 122 } else if (policy == "threshold") { 123 lsqPolicy = Threshold; 124 125 assert(params->smtLSQThreshold > LQEntries); 126 assert(params->smtLSQThreshold > SQEntries); 127 128 //Divide up by threshold amount 129 //@todo: Should threads check the max and the total 130 //amount of the LSQ 131 maxLQEntries = params->smtLSQThreshold; 132 maxSQEntries = params->smtLSQThreshold; 133 134 DPRINTF(LSQ, "LSQ sharing policy set to Threshold: " 135 "%i entries per LQ | %i entries per SQ", 136 maxLQEntries,maxSQEntries); 137 138 } else { 139 assert(0 && "Invalid LSQ Sharing Policy.Options Are:{Dynamic," 140 "Partitioned, Threshold}"); 141 } 142 143 //Initialize LSQs 144 for (int tid=0; tid < numThreads; tid++) { 145 thread[tid].init(params, this, maxLQEntries, maxSQEntries, tid); 146 thread[tid].setDcachePort(&dcachePort); 147 } 148} 149 150 151template<class Impl> 152std::string 153LSQ<Impl>::name() const 154{ 155 return iewStage->name() + ".lsq"; 156} 157 158template<class Impl> 159void 160LSQ<Impl>::regStats() 161{ 162 //Initialize LSQs 163 for (int tid=0; tid < numThreads; tid++) { 164 thread[tid].regStats(); 165 } 166} 167 168template<class Impl> 169void | 1/* 2 * Copyright (c) 2005-2006 The Regents of The University of Michigan 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are 7 * met: redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer; 9 * redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution; 12 * neither the name of the copyright holders nor the names of its 13 * contributors may be used to endorse or promote products derived from 14 * this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 * 28 * Authors: Korey Sewell 29 */ 30 31#include <algorithm> 32#include <list> 33#include <string> 34 35#include "cpu/o3/lsq.hh" 36 37template <class Impl> 38Tick 39LSQ<Impl>::DcachePort::recvAtomic(PacketPtr pkt) 40{ 41 panic("O3CPU model does not work with atomic mode!"); 42 return curTick; 43} 44 45template <class Impl> 46void 47LSQ<Impl>::DcachePort::recvFunctional(PacketPtr pkt) 48{ 49 panic("O3CPU doesn't expect recvFunctional callback!"); 50} 51 52template <class Impl> 53void 54LSQ<Impl>::DcachePort::recvStatusChange(Status status) 55{ 56 if (status == RangeChange) 57 return; 58 59 panic("O3CPU doesn't expect recvStatusChange callback!"); 60} 61 62template <class Impl> 63bool 64LSQ<Impl>::DcachePort::recvTiming(PacketPtr pkt) 65{ 66 lsq->thread[pkt->req->getThreadNum()].completeDataAccess(pkt); 67 return true; 68} 69 70template <class Impl> 71void 72LSQ<Impl>::DcachePort::recvRetry() 73{ 74 if (lsq->retryTid == -1) 75 { 76 //Squashed, so drop it 77 return; 78 } 79 lsq->thread[lsq->retryTid].recvRetry(); 80 // Speculatively clear the retry Tid. This will get set again if 81 // the LSQUnit was unable to complete its access. 82 lsq->retryTid = -1; 83} 84 85template <class Impl> 86LSQ<Impl>::LSQ(Params *params) 87 : dcachePort(this), LQEntries(params->LQEntries), 88 SQEntries(params->SQEntries), numThreads(params->numberOfThreads), 89 retryTid(-1) 90{ 91 DPRINTF(LSQ, "Creating LSQ object.\n"); 92 93 //**********************************************/ 94 //************ Handle SMT Parameters ***********/ 95 //**********************************************/ 96 std::string policy = params->smtLSQPolicy; 97 98 //Convert string to lowercase 99 std::transform(policy.begin(), policy.end(), policy.begin(), 100 (int(*)(int)) tolower); 101 102 //Figure out fetch policy 103 if (policy == "dynamic") { 104 lsqPolicy = Dynamic; 105 106 maxLQEntries = LQEntries; 107 maxSQEntries = SQEntries; 108 109 DPRINTF(LSQ, "LSQ sharing policy set to Dynamic\n"); 110 111 } else if (policy == "partitioned") { 112 lsqPolicy = Partitioned; 113 114 //@todo:make work if part_amt doesnt divide evenly. 115 maxLQEntries = LQEntries / numThreads; 116 maxSQEntries = SQEntries / numThreads; 117 118 DPRINTF(Fetch, "LSQ sharing policy set to Partitioned: " 119 "%i entries per LQ | %i entries per SQ", 120 maxLQEntries,maxSQEntries); 121 122 } else if (policy == "threshold") { 123 lsqPolicy = Threshold; 124 125 assert(params->smtLSQThreshold > LQEntries); 126 assert(params->smtLSQThreshold > SQEntries); 127 128 //Divide up by threshold amount 129 //@todo: Should threads check the max and the total 130 //amount of the LSQ 131 maxLQEntries = params->smtLSQThreshold; 132 maxSQEntries = params->smtLSQThreshold; 133 134 DPRINTF(LSQ, "LSQ sharing policy set to Threshold: " 135 "%i entries per LQ | %i entries per SQ", 136 maxLQEntries,maxSQEntries); 137 138 } else { 139 assert(0 && "Invalid LSQ Sharing Policy.Options Are:{Dynamic," 140 "Partitioned, Threshold}"); 141 } 142 143 //Initialize LSQs 144 for (int tid=0; tid < numThreads; tid++) { 145 thread[tid].init(params, this, maxLQEntries, maxSQEntries, tid); 146 thread[tid].setDcachePort(&dcachePort); 147 } 148} 149 150 151template<class Impl> 152std::string 153LSQ<Impl>::name() const 154{ 155 return iewStage->name() + ".lsq"; 156} 157 158template<class Impl> 159void 160LSQ<Impl>::regStats() 161{ 162 //Initialize LSQs 163 for (int tid=0; tid < numThreads; tid++) { 164 thread[tid].regStats(); 165 } 166} 167 168template<class Impl> 169void |
170LSQ<Impl>::regStats() 171{ 172 //Initialize LSQs 173 for (int tid=0; tid < numThreads; tid++) { 174 thread[tid].regStats(); 175 } 176} 177 178template<class Impl> 179void | |
180LSQ<Impl>::setActiveThreads(std::list<unsigned> *at_ptr) 181{ 182 activeThreads = at_ptr; 183 assert(activeThreads != 0); 184} 185 186template<class Impl> 187void 188LSQ<Impl>::setCPU(O3CPU *cpu_ptr) 189{ 190 cpu = cpu_ptr; 191 192 dcachePort.setName(name()); 193 194 for (int tid=0; tid < numThreads; tid++) { 195 thread[tid].setCPU(cpu_ptr); 196 } 197} 198 199template<class Impl> 200void 201LSQ<Impl>::setIEW(IEW *iew_ptr) 202{ 203 iewStage = iew_ptr; 204 205 for (int tid=0; tid < numThreads; tid++) { 206 thread[tid].setIEW(iew_ptr); 207 } 208} 209 210template <class Impl> 211void 212LSQ<Impl>::switchOut() 213{ 214 for (int tid = 0; tid < numThreads; tid++) { 215 thread[tid].switchOut(); 216 } 217} 218 219template <class Impl> 220void 221LSQ<Impl>::takeOverFrom() 222{ 223 for (int tid = 0; tid < numThreads; tid++) { 224 thread[tid].takeOverFrom(); 225 } 226} 227 228template <class Impl> 229int 230LSQ<Impl>::entryAmount(int num_threads) 231{ 232 if (lsqPolicy == Partitioned) { 233 return LQEntries / num_threads; 234 } else { 235 return 0; 236 } 237} 238 239template <class Impl> 240void 241LSQ<Impl>::resetEntries() 242{ 243 if (lsqPolicy != Dynamic || numThreads > 1) { 244 int active_threads = (*activeThreads).size(); 245 246 std::list<unsigned>::iterator threads = (*activeThreads).begin(); 247 std::list<unsigned>::iterator list_end = (*activeThreads).end(); 248 249 int maxEntries; 250 251 if (lsqPolicy == Partitioned) { 252 maxEntries = LQEntries / active_threads; 253 } else if (lsqPolicy == Threshold && active_threads == 1) { 254 maxEntries = LQEntries; 255 } else { 256 maxEntries = LQEntries; 257 } 258 259 while (threads != list_end) { 260 resizeEntries(maxEntries,*threads++); 261 } 262 } 263} 264 265template<class Impl> 266void 267LSQ<Impl>::removeEntries(unsigned tid) 268{ 269 thread[tid].clearLQ(); 270 thread[tid].clearSQ(); 271} 272 273template<class Impl> 274void 275LSQ<Impl>::resizeEntries(unsigned size,unsigned tid) 276{ 277 thread[tid].resizeLQ(size); 278 thread[tid].resizeSQ(size); 279} 280 281template<class Impl> 282void 283LSQ<Impl>::tick() 284{ 285 std::list<unsigned>::iterator active_threads = (*activeThreads).begin(); 286 287 while (active_threads != (*activeThreads).end()) { 288 unsigned tid = *active_threads++; 289 290 thread[tid].tick(); 291 } 292} 293 294template<class Impl> 295void 296LSQ<Impl>::insertLoad(DynInstPtr &load_inst) 297{ 298 unsigned tid = load_inst->threadNumber; 299 300 thread[tid].insertLoad(load_inst); 301} 302 303template<class Impl> 304void 305LSQ<Impl>::insertStore(DynInstPtr &store_inst) 306{ 307 unsigned tid = store_inst->threadNumber; 308 309 thread[tid].insertStore(store_inst); 310} 311 312template<class Impl> 313Fault 314LSQ<Impl>::executeLoad(DynInstPtr &inst) 315{ 316 unsigned tid = inst->threadNumber; 317 318 return thread[tid].executeLoad(inst); 319} 320 321template<class Impl> 322Fault 323LSQ<Impl>::executeStore(DynInstPtr &inst) 324{ 325 unsigned tid = inst->threadNumber; 326 327 return thread[tid].executeStore(inst); 328} 329 330template<class Impl> 331void 332LSQ<Impl>::writebackStores() 333{ 334 std::list<unsigned>::iterator active_threads = (*activeThreads).begin(); 335 336 while (active_threads != (*activeThreads).end()) { 337 unsigned tid = *active_threads++; 338 339 if (numStoresToWB(tid) > 0) { 340 DPRINTF(Writeback,"[tid:%i] Writing back stores. %i stores " 341 "available for Writeback.\n", tid, numStoresToWB(tid)); 342 } 343 344 thread[tid].writebackStores(); 345 } 346} 347 348template<class Impl> 349bool 350LSQ<Impl>::violation() 351{ 352 /* Answers: Does Anybody Have a Violation?*/ 353 std::list<unsigned>::iterator active_threads = (*activeThreads).begin(); 354 355 while (active_threads != (*activeThreads).end()) { 356 unsigned tid = *active_threads++; 357 if (thread[tid].violation()) 358 return true; 359 } 360 361 return false; 362} 363 364template<class Impl> 365int 366LSQ<Impl>::getCount() 367{ 368 unsigned total = 0; 369 370 std::list<unsigned>::iterator active_threads = (*activeThreads).begin(); 371 372 while (active_threads != (*activeThreads).end()) { 373 unsigned tid = *active_threads++; 374 total += getCount(tid); 375 } 376 377 return total; 378} 379 380template<class Impl> 381int 382LSQ<Impl>::numLoads() 383{ 384 unsigned total = 0; 385 386 std::list<unsigned>::iterator active_threads = (*activeThreads).begin(); 387 388 while (active_threads != (*activeThreads).end()) { 389 unsigned tid = *active_threads++; 390 total += numLoads(tid); 391 } 392 393 return total; 394} 395 396template<class Impl> 397int 398LSQ<Impl>::numStores() 399{ 400 unsigned total = 0; 401 402 std::list<unsigned>::iterator active_threads = (*activeThreads).begin(); 403 404 while (active_threads != (*activeThreads).end()) { 405 unsigned tid = *active_threads++; 406 total += thread[tid].numStores(); 407 } 408 409 return total; 410} 411 412template<class Impl> 413int 414LSQ<Impl>::numLoadsReady() 415{ 416 unsigned total = 0; 417 418 std::list<unsigned>::iterator active_threads = (*activeThreads).begin(); 419 420 while (active_threads != (*activeThreads).end()) { 421 unsigned tid = *active_threads++; 422 total += thread[tid].numLoadsReady(); 423 } 424 425 return total; 426} 427 428template<class Impl> 429unsigned 430LSQ<Impl>::numFreeEntries() 431{ 432 unsigned total = 0; 433 434 std::list<unsigned>::iterator active_threads = (*activeThreads).begin(); 435 436 while (active_threads != (*activeThreads).end()) { 437 unsigned tid = *active_threads++; 438 total += thread[tid].numFreeEntries(); 439 } 440 441 return total; 442} 443 444template<class Impl> 445unsigned 446LSQ<Impl>::numFreeEntries(unsigned tid) 447{ 448 //if( lsqPolicy == Dynamic ) 449 //return numFreeEntries(); 450 //else 451 return thread[tid].numFreeEntries(); 452} 453 454template<class Impl> 455bool 456LSQ<Impl>::isFull() 457{ 458 std::list<unsigned>::iterator active_threads = (*activeThreads).begin(); 459 460 while (active_threads != (*activeThreads).end()) { 461 unsigned tid = *active_threads++; 462 if (! (thread[tid].lqFull() || thread[tid].sqFull()) ) 463 return false; 464 } 465 466 return true; 467} 468 469template<class Impl> 470bool 471LSQ<Impl>::isFull(unsigned tid) 472{ 473 //@todo: Change to Calculate All Entries for 474 //Dynamic Policy 475 if( lsqPolicy == Dynamic ) 476 return isFull(); 477 else 478 return thread[tid].lqFull() || thread[tid].sqFull(); 479} 480 481template<class Impl> 482bool 483LSQ<Impl>::lqFull() 484{ 485 std::list<unsigned>::iterator active_threads = (*activeThreads).begin(); 486 487 while (active_threads != (*activeThreads).end()) { 488 unsigned tid = *active_threads++; 489 if (!thread[tid].lqFull()) 490 return false; 491 } 492 493 return true; 494} 495 496template<class Impl> 497bool 498LSQ<Impl>::lqFull(unsigned tid) 499{ 500 //@todo: Change to Calculate All Entries for 501 //Dynamic Policy 502 if( lsqPolicy == Dynamic ) 503 return lqFull(); 504 else 505 return thread[tid].lqFull(); 506} 507 508template<class Impl> 509bool 510LSQ<Impl>::sqFull() 511{ 512 std::list<unsigned>::iterator active_threads = (*activeThreads).begin(); 513 514 while (active_threads != (*activeThreads).end()) { 515 unsigned tid = *active_threads++; 516 if (!sqFull(tid)) 517 return false; 518 } 519 520 return true; 521} 522 523template<class Impl> 524bool 525LSQ<Impl>::sqFull(unsigned tid) 526{ 527 //@todo: Change to Calculate All Entries for 528 //Dynamic Policy 529 if( lsqPolicy == Dynamic ) 530 return sqFull(); 531 else 532 return thread[tid].sqFull(); 533} 534 535template<class Impl> 536bool 537LSQ<Impl>::isStalled() 538{ 539 std::list<unsigned>::iterator active_threads = (*activeThreads).begin(); 540 541 while (active_threads != (*activeThreads).end()) { 542 unsigned tid = *active_threads++; 543 if (!thread[tid].isStalled()) 544 return false; 545 } 546 547 return true; 548} 549 550template<class Impl> 551bool 552LSQ<Impl>::isStalled(unsigned tid) 553{ 554 if( lsqPolicy == Dynamic ) 555 return isStalled(); 556 else 557 return thread[tid].isStalled(); 558} 559 560template<class Impl> 561bool 562LSQ<Impl>::hasStoresToWB() 563{ 564 std::list<unsigned>::iterator active_threads = (*activeThreads).begin(); 565 566 if ((*activeThreads).empty()) 567 return false; 568 569 while (active_threads != (*activeThreads).end()) { 570 unsigned tid = *active_threads++; 571 if (!hasStoresToWB(tid)) 572 return false; 573 } 574 575 return true; 576} 577 578template<class Impl> 579bool 580LSQ<Impl>::willWB() 581{ 582 std::list<unsigned>::iterator active_threads = (*activeThreads).begin(); 583 584 while (active_threads != (*activeThreads).end()) { 585 unsigned tid = *active_threads++; 586 if (!willWB(tid)) 587 return false; 588 } 589 590 return true; 591} 592 593template<class Impl> 594void 595LSQ<Impl>::dumpInsts() 596{ 597 std::list<unsigned>::iterator active_threads = (*activeThreads).begin(); 598 599 while (active_threads != (*activeThreads).end()) { 600 unsigned tid = *active_threads++; 601 thread[tid].dumpInsts(); 602 } 603} | 170LSQ<Impl>::setActiveThreads(std::list<unsigned> *at_ptr) 171{ 172 activeThreads = at_ptr; 173 assert(activeThreads != 0); 174} 175 176template<class Impl> 177void 178LSQ<Impl>::setCPU(O3CPU *cpu_ptr) 179{ 180 cpu = cpu_ptr; 181 182 dcachePort.setName(name()); 183 184 for (int tid=0; tid < numThreads; tid++) { 185 thread[tid].setCPU(cpu_ptr); 186 } 187} 188 189template<class Impl> 190void 191LSQ<Impl>::setIEW(IEW *iew_ptr) 192{ 193 iewStage = iew_ptr; 194 195 for (int tid=0; tid < numThreads; tid++) { 196 thread[tid].setIEW(iew_ptr); 197 } 198} 199 200template <class Impl> 201void 202LSQ<Impl>::switchOut() 203{ 204 for (int tid = 0; tid < numThreads; tid++) { 205 thread[tid].switchOut(); 206 } 207} 208 209template <class Impl> 210void 211LSQ<Impl>::takeOverFrom() 212{ 213 for (int tid = 0; tid < numThreads; tid++) { 214 thread[tid].takeOverFrom(); 215 } 216} 217 218template <class Impl> 219int 220LSQ<Impl>::entryAmount(int num_threads) 221{ 222 if (lsqPolicy == Partitioned) { 223 return LQEntries / num_threads; 224 } else { 225 return 0; 226 } 227} 228 229template <class Impl> 230void 231LSQ<Impl>::resetEntries() 232{ 233 if (lsqPolicy != Dynamic || numThreads > 1) { 234 int active_threads = (*activeThreads).size(); 235 236 std::list<unsigned>::iterator threads = (*activeThreads).begin(); 237 std::list<unsigned>::iterator list_end = (*activeThreads).end(); 238 239 int maxEntries; 240 241 if (lsqPolicy == Partitioned) { 242 maxEntries = LQEntries / active_threads; 243 } else if (lsqPolicy == Threshold && active_threads == 1) { 244 maxEntries = LQEntries; 245 } else { 246 maxEntries = LQEntries; 247 } 248 249 while (threads != list_end) { 250 resizeEntries(maxEntries,*threads++); 251 } 252 } 253} 254 255template<class Impl> 256void 257LSQ<Impl>::removeEntries(unsigned tid) 258{ 259 thread[tid].clearLQ(); 260 thread[tid].clearSQ(); 261} 262 263template<class Impl> 264void 265LSQ<Impl>::resizeEntries(unsigned size,unsigned tid) 266{ 267 thread[tid].resizeLQ(size); 268 thread[tid].resizeSQ(size); 269} 270 271template<class Impl> 272void 273LSQ<Impl>::tick() 274{ 275 std::list<unsigned>::iterator active_threads = (*activeThreads).begin(); 276 277 while (active_threads != (*activeThreads).end()) { 278 unsigned tid = *active_threads++; 279 280 thread[tid].tick(); 281 } 282} 283 284template<class Impl> 285void 286LSQ<Impl>::insertLoad(DynInstPtr &load_inst) 287{ 288 unsigned tid = load_inst->threadNumber; 289 290 thread[tid].insertLoad(load_inst); 291} 292 293template<class Impl> 294void 295LSQ<Impl>::insertStore(DynInstPtr &store_inst) 296{ 297 unsigned tid = store_inst->threadNumber; 298 299 thread[tid].insertStore(store_inst); 300} 301 302template<class Impl> 303Fault 304LSQ<Impl>::executeLoad(DynInstPtr &inst) 305{ 306 unsigned tid = inst->threadNumber; 307 308 return thread[tid].executeLoad(inst); 309} 310 311template<class Impl> 312Fault 313LSQ<Impl>::executeStore(DynInstPtr &inst) 314{ 315 unsigned tid = inst->threadNumber; 316 317 return thread[tid].executeStore(inst); 318} 319 320template<class Impl> 321void 322LSQ<Impl>::writebackStores() 323{ 324 std::list<unsigned>::iterator active_threads = (*activeThreads).begin(); 325 326 while (active_threads != (*activeThreads).end()) { 327 unsigned tid = *active_threads++; 328 329 if (numStoresToWB(tid) > 0) { 330 DPRINTF(Writeback,"[tid:%i] Writing back stores. %i stores " 331 "available for Writeback.\n", tid, numStoresToWB(tid)); 332 } 333 334 thread[tid].writebackStores(); 335 } 336} 337 338template<class Impl> 339bool 340LSQ<Impl>::violation() 341{ 342 /* Answers: Does Anybody Have a Violation?*/ 343 std::list<unsigned>::iterator active_threads = (*activeThreads).begin(); 344 345 while (active_threads != (*activeThreads).end()) { 346 unsigned tid = *active_threads++; 347 if (thread[tid].violation()) 348 return true; 349 } 350 351 return false; 352} 353 354template<class Impl> 355int 356LSQ<Impl>::getCount() 357{ 358 unsigned total = 0; 359 360 std::list<unsigned>::iterator active_threads = (*activeThreads).begin(); 361 362 while (active_threads != (*activeThreads).end()) { 363 unsigned tid = *active_threads++; 364 total += getCount(tid); 365 } 366 367 return total; 368} 369 370template<class Impl> 371int 372LSQ<Impl>::numLoads() 373{ 374 unsigned total = 0; 375 376 std::list<unsigned>::iterator active_threads = (*activeThreads).begin(); 377 378 while (active_threads != (*activeThreads).end()) { 379 unsigned tid = *active_threads++; 380 total += numLoads(tid); 381 } 382 383 return total; 384} 385 386template<class Impl> 387int 388LSQ<Impl>::numStores() 389{ 390 unsigned total = 0; 391 392 std::list<unsigned>::iterator active_threads = (*activeThreads).begin(); 393 394 while (active_threads != (*activeThreads).end()) { 395 unsigned tid = *active_threads++; 396 total += thread[tid].numStores(); 397 } 398 399 return total; 400} 401 402template<class Impl> 403int 404LSQ<Impl>::numLoadsReady() 405{ 406 unsigned total = 0; 407 408 std::list<unsigned>::iterator active_threads = (*activeThreads).begin(); 409 410 while (active_threads != (*activeThreads).end()) { 411 unsigned tid = *active_threads++; 412 total += thread[tid].numLoadsReady(); 413 } 414 415 return total; 416} 417 418template<class Impl> 419unsigned 420LSQ<Impl>::numFreeEntries() 421{ 422 unsigned total = 0; 423 424 std::list<unsigned>::iterator active_threads = (*activeThreads).begin(); 425 426 while (active_threads != (*activeThreads).end()) { 427 unsigned tid = *active_threads++; 428 total += thread[tid].numFreeEntries(); 429 } 430 431 return total; 432} 433 434template<class Impl> 435unsigned 436LSQ<Impl>::numFreeEntries(unsigned tid) 437{ 438 //if( lsqPolicy == Dynamic ) 439 //return numFreeEntries(); 440 //else 441 return thread[tid].numFreeEntries(); 442} 443 444template<class Impl> 445bool 446LSQ<Impl>::isFull() 447{ 448 std::list<unsigned>::iterator active_threads = (*activeThreads).begin(); 449 450 while (active_threads != (*activeThreads).end()) { 451 unsigned tid = *active_threads++; 452 if (! (thread[tid].lqFull() || thread[tid].sqFull()) ) 453 return false; 454 } 455 456 return true; 457} 458 459template<class Impl> 460bool 461LSQ<Impl>::isFull(unsigned tid) 462{ 463 //@todo: Change to Calculate All Entries for 464 //Dynamic Policy 465 if( lsqPolicy == Dynamic ) 466 return isFull(); 467 else 468 return thread[tid].lqFull() || thread[tid].sqFull(); 469} 470 471template<class Impl> 472bool 473LSQ<Impl>::lqFull() 474{ 475 std::list<unsigned>::iterator active_threads = (*activeThreads).begin(); 476 477 while (active_threads != (*activeThreads).end()) { 478 unsigned tid = *active_threads++; 479 if (!thread[tid].lqFull()) 480 return false; 481 } 482 483 return true; 484} 485 486template<class Impl> 487bool 488LSQ<Impl>::lqFull(unsigned tid) 489{ 490 //@todo: Change to Calculate All Entries for 491 //Dynamic Policy 492 if( lsqPolicy == Dynamic ) 493 return lqFull(); 494 else 495 return thread[tid].lqFull(); 496} 497 498template<class Impl> 499bool 500LSQ<Impl>::sqFull() 501{ 502 std::list<unsigned>::iterator active_threads = (*activeThreads).begin(); 503 504 while (active_threads != (*activeThreads).end()) { 505 unsigned tid = *active_threads++; 506 if (!sqFull(tid)) 507 return false; 508 } 509 510 return true; 511} 512 513template<class Impl> 514bool 515LSQ<Impl>::sqFull(unsigned tid) 516{ 517 //@todo: Change to Calculate All Entries for 518 //Dynamic Policy 519 if( lsqPolicy == Dynamic ) 520 return sqFull(); 521 else 522 return thread[tid].sqFull(); 523} 524 525template<class Impl> 526bool 527LSQ<Impl>::isStalled() 528{ 529 std::list<unsigned>::iterator active_threads = (*activeThreads).begin(); 530 531 while (active_threads != (*activeThreads).end()) { 532 unsigned tid = *active_threads++; 533 if (!thread[tid].isStalled()) 534 return false; 535 } 536 537 return true; 538} 539 540template<class Impl> 541bool 542LSQ<Impl>::isStalled(unsigned tid) 543{ 544 if( lsqPolicy == Dynamic ) 545 return isStalled(); 546 else 547 return thread[tid].isStalled(); 548} 549 550template<class Impl> 551bool 552LSQ<Impl>::hasStoresToWB() 553{ 554 std::list<unsigned>::iterator active_threads = (*activeThreads).begin(); 555 556 if ((*activeThreads).empty()) 557 return false; 558 559 while (active_threads != (*activeThreads).end()) { 560 unsigned tid = *active_threads++; 561 if (!hasStoresToWB(tid)) 562 return false; 563 } 564 565 return true; 566} 567 568template<class Impl> 569bool 570LSQ<Impl>::willWB() 571{ 572 std::list<unsigned>::iterator active_threads = (*activeThreads).begin(); 573 574 while (active_threads != (*activeThreads).end()) { 575 unsigned tid = *active_threads++; 576 if (!willWB(tid)) 577 return false; 578 } 579 580 return true; 581} 582 583template<class Impl> 584void 585LSQ<Impl>::dumpInsts() 586{ 587 std::list<unsigned>::iterator active_threads = (*activeThreads).begin(); 588 589 while (active_threads != (*activeThreads).end()) { 590 unsigned tid = *active_threads++; 591 thread[tid].dumpInsts(); 592 } 593} |