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