1/* 2 * Copyright (c) 2011-2012 ARM Limited 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
| 1/* 2 * Copyright (c) 2011-2012 ARM Limited 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#include <algorithm> 44#include <list> 45#include <string> 46 47#include "cpu/o3/lsq.hh" 48#include "debug/Drain.hh" 49#include "debug/Fetch.hh" 50#include "debug/LSQ.hh" 51#include "debug/Writeback.hh" 52#include "params/DerivO3CPU.hh" 53 54using namespace std; 55 56template <class Impl> 57LSQ<Impl>::LSQ(O3CPU *cpu_ptr, IEW *iew_ptr, DerivO3CPUParams *params) 58 : cpu(cpu_ptr), iewStage(iew_ptr), 59 LQEntries(params->LQEntries), 60 SQEntries(params->SQEntries), 61 numThreads(params->numThreads), 62 retryTid(-1) 63{ 64 assert(numThreads > 0 && numThreads <= Impl::MaxThreads); 65 66 //**********************************************/ 67 //************ Handle SMT Parameters ***********/ 68 //**********************************************/ 69 std::string policy = params->smtLSQPolicy; 70 71 //Convert string to lowercase 72 std::transform(policy.begin(), policy.end(), policy.begin(), 73 (int(*)(int)) tolower); 74 75 //Figure out fetch policy 76 if (policy == "dynamic") { 77 lsqPolicy = Dynamic; 78 79 maxLQEntries = LQEntries; 80 maxSQEntries = SQEntries; 81 82 DPRINTF(LSQ, "LSQ sharing policy set to Dynamic\n"); 83 } else if (policy == "partitioned") { 84 lsqPolicy = Partitioned; 85 86 //@todo:make work if part_amt doesnt divide evenly. 87 maxLQEntries = LQEntries / numThreads; 88 maxSQEntries = SQEntries / numThreads; 89 90 DPRINTF(Fetch, "LSQ sharing policy set to Partitioned: " 91 "%i entries per LQ | %i entries per SQ\n", 92 maxLQEntries,maxSQEntries); 93 } else if (policy == "threshold") { 94 lsqPolicy = Threshold; 95 96 assert(params->smtLSQThreshold > LQEntries); 97 assert(params->smtLSQThreshold > SQEntries); 98 99 //Divide up by threshold amount 100 //@todo: Should threads check the max and the total 101 //amount of the LSQ 102 maxLQEntries = params->smtLSQThreshold; 103 maxSQEntries = params->smtLSQThreshold; 104 105 DPRINTF(LSQ, "LSQ sharing policy set to Threshold: " 106 "%i entries per LQ | %i entries per SQ\n", 107 maxLQEntries,maxSQEntries); 108 } else { 109 assert(0 && "Invalid LSQ Sharing Policy.Options Are:{Dynamic," 110 "Partitioned, Threshold}"); 111 } 112 113 //Initialize LSQs 114 thread = new LSQUnit[numThreads]; 115 for (ThreadID tid = 0; tid < numThreads; tid++) { 116 thread[tid].init(cpu, iew_ptr, params, this, 117 maxLQEntries, maxSQEntries, tid); 118 thread[tid].setDcachePort(&cpu_ptr->getDataPort()); 119 } 120} 121 122 123template<class Impl> 124std::string 125LSQ<Impl>::name() const 126{ 127 return iewStage->name() + ".lsq"; 128} 129 130template<class Impl> 131void 132LSQ<Impl>::regStats() 133{ 134 //Initialize LSQs 135 for (ThreadID tid = 0; tid < numThreads; tid++) { 136 thread[tid].regStats(); 137 } 138} 139 140template<class Impl> 141void 142LSQ<Impl>::setActiveThreads(list<ThreadID> *at_ptr) 143{ 144 activeThreads = at_ptr; 145 assert(activeThreads != 0); 146} 147 148template <class Impl> 149void 150LSQ<Impl>::drainSanityCheck() const 151{ 152 assert(isDrained()); 153 154 for (ThreadID tid = 0; tid < numThreads; tid++) 155 thread[tid].drainSanityCheck(); 156} 157 158template <class Impl> 159bool 160LSQ<Impl>::isDrained() const 161{ 162 bool drained(true); 163 164 if (!lqEmpty()) { 165 DPRINTF(Drain, "Not drained, LQ not empty.\n"); 166 drained = false; 167 } 168 169 if (!sqEmpty()) { 170 DPRINTF(Drain, "Not drained, SQ not empty.\n"); 171 drained = false; 172 } 173 174 if (retryTid != InvalidThreadID) { 175 DPRINTF(Drain, "Not drained, the LSQ has blocked the caches.\n"); 176 drained = false; 177 } 178 179 return drained; 180} 181 182template <class Impl> 183void 184LSQ<Impl>::takeOverFrom() 185{ 186 for (ThreadID tid = 0; tid < numThreads; tid++) { 187 thread[tid].takeOverFrom(); 188 } 189} 190 191template <class Impl> 192int 193LSQ<Impl>::entryAmount(ThreadID num_threads) 194{ 195 if (lsqPolicy == Partitioned) { 196 return LQEntries / num_threads; 197 } else { 198 return 0; 199 } 200} 201 202template <class Impl> 203void 204LSQ<Impl>::resetEntries() 205{ 206 if (lsqPolicy != Dynamic || numThreads > 1) { 207 int active_threads = activeThreads->size(); 208 209 int maxEntries; 210 211 if (lsqPolicy == Partitioned) { 212 maxEntries = LQEntries / active_threads; 213 } else if (lsqPolicy == Threshold && active_threads == 1) { 214 maxEntries = LQEntries; 215 } else { 216 maxEntries = LQEntries; 217 } 218 219 list<ThreadID>::iterator threads = activeThreads->begin(); 220 list<ThreadID>::iterator end = activeThreads->end(); 221 222 while (threads != end) { 223 ThreadID tid = *threads++; 224 225 resizeEntries(maxEntries, tid); 226 } 227 } 228} 229 230template<class Impl> 231void 232LSQ<Impl>::removeEntries(ThreadID tid) 233{ 234 thread[tid].clearLQ(); 235 thread[tid].clearSQ(); 236} 237 238template<class Impl> 239void 240LSQ<Impl>::resizeEntries(unsigned size, ThreadID tid) 241{ 242 thread[tid].resizeLQ(size); 243 thread[tid].resizeSQ(size); 244} 245 246template<class Impl> 247void 248LSQ<Impl>::tick() 249{ 250 list<ThreadID>::iterator threads = activeThreads->begin(); 251 list<ThreadID>::iterator end = activeThreads->end(); 252 253 while (threads != end) { 254 ThreadID tid = *threads++; 255 256 thread[tid].tick(); 257 } 258} 259 260template<class Impl> 261void 262LSQ<Impl>::insertLoad(DynInstPtr &load_inst) 263{ 264 ThreadID tid = load_inst->threadNumber; 265 266 thread[tid].insertLoad(load_inst); 267} 268 269template<class Impl> 270void 271LSQ<Impl>::insertStore(DynInstPtr &store_inst) 272{ 273 ThreadID tid = store_inst->threadNumber; 274 275 thread[tid].insertStore(store_inst); 276} 277 278template<class Impl> 279Fault 280LSQ<Impl>::executeLoad(DynInstPtr &inst) 281{ 282 ThreadID tid = inst->threadNumber; 283 284 return thread[tid].executeLoad(inst); 285} 286 287template<class Impl> 288Fault 289LSQ<Impl>::executeStore(DynInstPtr &inst) 290{ 291 ThreadID tid = inst->threadNumber; 292 293 return thread[tid].executeStore(inst); 294} 295 296template<class Impl> 297void 298LSQ<Impl>::writebackStores() 299{ 300 list<ThreadID>::iterator threads = activeThreads->begin(); 301 list<ThreadID>::iterator end = activeThreads->end(); 302 303 while (threads != end) { 304 ThreadID tid = *threads++; 305 306 if (numStoresToWB(tid) > 0) { 307 DPRINTF(Writeback,"[tid:%i] Writing back stores. %i stores " 308 "available for Writeback.\n", tid, numStoresToWB(tid)); 309 } 310 311 thread[tid].writebackStores(); 312 } 313} 314 315template<class Impl> 316bool 317LSQ<Impl>::violation() 318{ 319 /* Answers: Does Anybody Have a Violation?*/ 320 list<ThreadID>::iterator threads = activeThreads->begin(); 321 list<ThreadID>::iterator end = activeThreads->end(); 322 323 while (threads != end) { 324 ThreadID tid = *threads++; 325 326 if (thread[tid].violation()) 327 return true; 328 } 329 330 return false; 331} 332 333template <class Impl> 334void 335LSQ<Impl>::recvRetry() 336{ 337 if (retryTid == InvalidThreadID) 338 { 339 //Squashed, so drop it 340 return; 341 } 342 int curr_retry_tid = retryTid; 343 // Speculatively clear the retry Tid. This will get set again if 344 // the LSQUnit was unable to complete its access. 345 retryTid = -1; 346 thread[curr_retry_tid].recvRetry(); 347} 348 349template <class Impl> 350bool 351LSQ<Impl>::recvTimingResp(PacketPtr pkt) 352{ 353 if (pkt->isError()) 354 DPRINTF(LSQ, "Got error packet back for address: %#X\n", 355 pkt->getAddr()); 356 thread[pkt->req->threadId()].completeDataAccess(pkt); 357 return true; 358} 359 360template <class Impl> 361void 362LSQ<Impl>::recvTimingSnoopReq(PacketPtr pkt) 363{ 364 DPRINTF(LSQ, "received pkt for addr:%#x %s\n", pkt->getAddr(), 365 pkt->cmdString()); 366 367 // must be a snoop 368 if (pkt->isInvalidate()) { 369 DPRINTF(LSQ, "received invalidation for addr:%#x\n", 370 pkt->getAddr()); 371 for (ThreadID tid = 0; tid < numThreads; tid++) { 372 thread[tid].checkSnoop(pkt); 373 } 374 } 375} 376 377template<class Impl> 378int 379LSQ<Impl>::getCount() 380{ 381 unsigned total = 0; 382 383 list<ThreadID>::iterator threads = activeThreads->begin(); 384 list<ThreadID>::iterator end = activeThreads->end(); 385 386 while (threads != end) { 387 ThreadID tid = *threads++; 388 389 total += getCount(tid); 390 } 391 392 return total; 393} 394 395template<class Impl> 396int 397LSQ<Impl>::numLoads() 398{ 399 unsigned total = 0; 400 401 list<ThreadID>::iterator threads = activeThreads->begin(); 402 list<ThreadID>::iterator end = activeThreads->end(); 403 404 while (threads != end) { 405 ThreadID tid = *threads++; 406 407 total += numLoads(tid); 408 } 409 410 return total; 411} 412 413template<class Impl> 414int 415LSQ<Impl>::numStores() 416{ 417 unsigned total = 0; 418 419 list<ThreadID>::iterator threads = activeThreads->begin(); 420 list<ThreadID>::iterator end = activeThreads->end(); 421 422 while (threads != end) { 423 ThreadID tid = *threads++; 424 425 total += thread[tid].numStores(); 426 } 427 428 return total; 429} 430 431template<class Impl> 432unsigned 433LSQ<Impl>::numFreeEntries() 434{ 435 unsigned total = 0; 436 437 list<ThreadID>::iterator threads = activeThreads->begin(); 438 list<ThreadID>::iterator end = activeThreads->end(); 439 440 while (threads != end) { 441 ThreadID tid = *threads++; 442 443 total += thread[tid].numFreeEntries(); 444 } 445 446 return total; 447} 448 449template<class Impl> 450unsigned 451LSQ<Impl>::numFreeEntries(ThreadID tid) 452{ 453 //if (lsqPolicy == Dynamic) 454 //return numFreeEntries(); 455 //else 456 return thread[tid].numFreeEntries(); 457} 458 459template<class Impl> 460bool 461LSQ<Impl>::isFull() 462{ 463 list<ThreadID>::iterator threads = activeThreads->begin(); 464 list<ThreadID>::iterator end = activeThreads->end(); 465 466 while (threads != end) { 467 ThreadID tid = *threads++; 468 469 if (!(thread[tid].lqFull() || thread[tid].sqFull())) 470 return false; 471 } 472 473 return true; 474} 475 476template<class Impl> 477bool 478LSQ<Impl>::isFull(ThreadID tid) 479{ 480 //@todo: Change to Calculate All Entries for 481 //Dynamic Policy 482 if (lsqPolicy == Dynamic) 483 return isFull(); 484 else 485 return thread[tid].lqFull() || thread[tid].sqFull(); 486} 487 488template<class Impl> 489bool 490LSQ<Impl>::isEmpty() const 491{ 492 return lqEmpty() && sqEmpty(); 493} 494 495template<class Impl> 496bool 497LSQ<Impl>::lqEmpty() const 498{ 499 list<ThreadID>::const_iterator threads = activeThreads->begin(); 500 list<ThreadID>::const_iterator end = activeThreads->end(); 501 502 while (threads != end) { 503 ThreadID tid = *threads++; 504 505 if (!thread[tid].lqEmpty()) 506 return false; 507 } 508 509 return true; 510} 511 512template<class Impl> 513bool 514LSQ<Impl>::sqEmpty() const 515{ 516 list<ThreadID>::const_iterator threads = activeThreads->begin(); 517 list<ThreadID>::const_iterator end = activeThreads->end(); 518 519 while (threads != end) { 520 ThreadID tid = *threads++; 521 522 if (!thread[tid].sqEmpty()) 523 return false; 524 } 525 526 return true; 527} 528 529template<class Impl> 530bool 531LSQ<Impl>::lqFull() 532{ 533 list<ThreadID>::iterator threads = activeThreads->begin(); 534 list<ThreadID>::iterator end = activeThreads->end(); 535 536 while (threads != end) { 537 ThreadID tid = *threads++; 538 539 if (!thread[tid].lqFull()) 540 return false; 541 } 542 543 return true; 544} 545 546template<class Impl> 547bool 548LSQ<Impl>::lqFull(ThreadID tid) 549{ 550 //@todo: Change to Calculate All Entries for 551 //Dynamic Policy 552 if (lsqPolicy == Dynamic) 553 return lqFull(); 554 else 555 return thread[tid].lqFull(); 556} 557 558template<class Impl> 559bool 560LSQ<Impl>::sqFull() 561{ 562 list<ThreadID>::iterator threads = activeThreads->begin(); 563 list<ThreadID>::iterator end = activeThreads->end(); 564 565 while (threads != end) { 566 ThreadID tid = *threads++; 567 568 if (!sqFull(tid)) 569 return false; 570 } 571 572 return true; 573} 574 575template<class Impl> 576bool 577LSQ<Impl>::sqFull(ThreadID tid) 578{ 579 //@todo: Change to Calculate All Entries for 580 //Dynamic Policy 581 if (lsqPolicy == Dynamic) 582 return sqFull(); 583 else 584 return thread[tid].sqFull(); 585} 586 587template<class Impl> 588bool 589LSQ<Impl>::isStalled() 590{ 591 list<ThreadID>::iterator threads = activeThreads->begin(); 592 list<ThreadID>::iterator end = activeThreads->end(); 593 594 while (threads != end) { 595 ThreadID tid = *threads++; 596 597 if (!thread[tid].isStalled()) 598 return false; 599 } 600 601 return true; 602} 603 604template<class Impl> 605bool 606LSQ<Impl>::isStalled(ThreadID tid) 607{ 608 if (lsqPolicy == Dynamic) 609 return isStalled(); 610 else 611 return thread[tid].isStalled(); 612} 613 614template<class Impl> 615bool 616LSQ<Impl>::hasStoresToWB() 617{ 618 list<ThreadID>::iterator threads = activeThreads->begin(); 619 list<ThreadID>::iterator end = activeThreads->end(); 620 621 while (threads != end) { 622 ThreadID tid = *threads++; 623 624 if (hasStoresToWB(tid)) 625 return true; 626 } 627 628 return false; 629} 630 631template<class Impl> 632bool 633LSQ<Impl>::willWB() 634{ 635 list<ThreadID>::iterator threads = activeThreads->begin(); 636 list<ThreadID>::iterator end = activeThreads->end(); 637 638 while (threads != end) { 639 ThreadID tid = *threads++; 640 641 if (willWB(tid)) 642 return true; 643 } 644 645 return false; 646} 647 648template<class Impl> 649void 650LSQ<Impl>::dumpInsts() const 651{ 652 list<ThreadID>::const_iterator threads = activeThreads->begin(); 653 list<ThreadID>::const_iterator end = activeThreads->end(); 654 655 while (threads != end) { 656 ThreadID tid = *threads++; 657 658 thread[tid].dumpInsts(); 659 } 660}
| 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 436LSQ<Impl>::numFreeEntries() 437{ 438 unsigned total = 0; 439 440 list<ThreadID>::iterator threads = activeThreads->begin(); 441 list<ThreadID>::iterator end = activeThreads->end(); 442 443 while (threads != end) { 444 ThreadID tid = *threads++; 445 446 total += thread[tid].numFreeEntries(); 447 } 448 449 return total; 450} 451 452template<class Impl> 453unsigned 454LSQ<Impl>::numFreeEntries(ThreadID tid) 455{ 456 //if (lsqPolicy == Dynamic) 457 //return numFreeEntries(); 458 //else 459 return thread[tid].numFreeEntries(); 460} 461 462template<class Impl> 463bool 464LSQ<Impl>::isFull() 465{ 466 list<ThreadID>::iterator threads = activeThreads->begin(); 467 list<ThreadID>::iterator end = activeThreads->end(); 468 469 while (threads != end) { 470 ThreadID tid = *threads++; 471 472 if (!(thread[tid].lqFull() || thread[tid].sqFull())) 473 return false; 474 } 475 476 return true; 477} 478 479template<class Impl> 480bool 481LSQ<Impl>::isFull(ThreadID tid) 482{ 483 //@todo: Change to Calculate All Entries for 484 //Dynamic Policy 485 if (lsqPolicy == Dynamic) 486 return isFull(); 487 else 488 return thread[tid].lqFull() || thread[tid].sqFull(); 489} 490 491template<class Impl> 492bool 493LSQ<Impl>::isEmpty() const 494{ 495 return lqEmpty() && sqEmpty(); 496} 497 498template<class Impl> 499bool 500LSQ<Impl>::lqEmpty() const 501{ 502 list<ThreadID>::const_iterator threads = activeThreads->begin(); 503 list<ThreadID>::const_iterator end = activeThreads->end(); 504 505 while (threads != end) { 506 ThreadID tid = *threads++; 507 508 if (!thread[tid].lqEmpty()) 509 return false; 510 } 511 512 return true; 513} 514 515template<class Impl> 516bool 517LSQ<Impl>::sqEmpty() const 518{ 519 list<ThreadID>::const_iterator threads = activeThreads->begin(); 520 list<ThreadID>::const_iterator end = activeThreads->end(); 521 522 while (threads != end) { 523 ThreadID tid = *threads++; 524 525 if (!thread[tid].sqEmpty()) 526 return false; 527 } 528 529 return true; 530} 531 532template<class Impl> 533bool 534LSQ<Impl>::lqFull() 535{ 536 list<ThreadID>::iterator threads = activeThreads->begin(); 537 list<ThreadID>::iterator end = activeThreads->end(); 538 539 while (threads != end) { 540 ThreadID tid = *threads++; 541 542 if (!thread[tid].lqFull()) 543 return false; 544 } 545 546 return true; 547} 548 549template<class Impl> 550bool 551LSQ<Impl>::lqFull(ThreadID tid) 552{ 553 //@todo: Change to Calculate All Entries for 554 //Dynamic Policy 555 if (lsqPolicy == Dynamic) 556 return lqFull(); 557 else 558 return thread[tid].lqFull(); 559} 560 561template<class Impl> 562bool 563LSQ<Impl>::sqFull() 564{ 565 list<ThreadID>::iterator threads = activeThreads->begin(); 566 list<ThreadID>::iterator end = activeThreads->end(); 567 568 while (threads != end) { 569 ThreadID tid = *threads++; 570 571 if (!sqFull(tid)) 572 return false; 573 } 574 575 return true; 576} 577 578template<class Impl> 579bool 580LSQ<Impl>::sqFull(ThreadID tid) 581{ 582 //@todo: Change to Calculate All Entries for 583 //Dynamic Policy 584 if (lsqPolicy == Dynamic) 585 return sqFull(); 586 else 587 return thread[tid].sqFull(); 588} 589 590template<class Impl> 591bool 592LSQ<Impl>::isStalled() 593{ 594 list<ThreadID>::iterator threads = activeThreads->begin(); 595 list<ThreadID>::iterator end = activeThreads->end(); 596 597 while (threads != end) { 598 ThreadID tid = *threads++; 599 600 if (!thread[tid].isStalled()) 601 return false; 602 } 603 604 return true; 605} 606 607template<class Impl> 608bool 609LSQ<Impl>::isStalled(ThreadID tid) 610{ 611 if (lsqPolicy == Dynamic) 612 return isStalled(); 613 else 614 return thread[tid].isStalled(); 615} 616 617template<class Impl> 618bool 619LSQ<Impl>::hasStoresToWB() 620{ 621 list<ThreadID>::iterator threads = activeThreads->begin(); 622 list<ThreadID>::iterator end = activeThreads->end(); 623 624 while (threads != end) { 625 ThreadID tid = *threads++; 626 627 if (hasStoresToWB(tid)) 628 return true; 629 } 630 631 return false; 632} 633 634template<class Impl> 635bool 636LSQ<Impl>::willWB() 637{ 638 list<ThreadID>::iterator threads = activeThreads->begin(); 639 list<ThreadID>::iterator end = activeThreads->end(); 640 641 while (threads != end) { 642 ThreadID tid = *threads++; 643 644 if (willWB(tid)) 645 return true; 646 } 647 648 return false; 649} 650 651template<class Impl> 652void 653LSQ<Impl>::dumpInsts() const 654{ 655 list<ThreadID>::const_iterator threads = activeThreads->begin(); 656 list<ThreadID>::const_iterator end = activeThreads->end(); 657 658 while (threads != end) { 659 ThreadID tid = *threads++; 660 661 thread[tid].dumpInsts(); 662 } 663}
|