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