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