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