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