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