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