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