lsq_impl.hh revision 8975
1/* 2 * Copyright (c) 2011-2012 ARM Limited 3 * All rights reserved 4 * 5 * The license below extends only to copyright in the software and shall 6 * not be construed as granting a license to any other intellectual 7 * property including but not limited to intellectual property relating 8 * to a hardware implementation of the functionality of the software 9 * licensed hereunder. You may use the software subject to the license 10 * terms below provided that you ensure that this notice is replicated 11 * unmodified and in its entirety in all distributions of the software, 12 * modified or unmodified, in source code or in binary form. 13 * 14 * Copyright (c) 2005-2006 The Regents of The University of Michigan 15 * All rights reserved. 16 * 17 * Redistribution and use in source and binary forms, with or without 18 * modification, are permitted provided that the following conditions are 19 * met: redistributions of source code must retain the above copyright 20 * notice, this list of conditions and the following disclaimer; 21 * redistributions in binary form must reproduce the above copyright 22 * notice, this list of conditions and the following disclaimer in the 23 * documentation and/or other materials provided with the distribution; 24 * neither the name of the copyright holders nor the names of its 25 * contributors may be used to endorse or promote products derived from 26 * this software without specific prior written permission. 27 * 28 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 29 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 30 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 31 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 32 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 33 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 34 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 35 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 36 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 37 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 38 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 39 * 40 * Authors: Korey Sewell 41 */ 42 43#include <algorithm> 44#include <list> 45#include <string> 46 47#include "cpu/o3/lsq.hh" 48#include "debug/Fetch.hh" 49#include "debug/LSQ.hh" 50#include "debug/Writeback.hh" 51#include "params/DerivO3CPU.hh" 52 53using namespace std; 54 55template <class Impl> 56LSQ<Impl>::LSQ(O3CPU *cpu_ptr, IEW *iew_ptr, DerivO3CPUParams *params) 57 : cpu(cpu_ptr), iewStage(iew_ptr), 58 LQEntries(params->LQEntries), 59 SQEntries(params->SQEntries), 60 numThreads(params->numThreads), 61 retryTid(-1) 62{ 63 //**********************************************/ 64 //************ Handle SMT Parameters ***********/ 65 //**********************************************/ 66 std::string policy = params->smtLSQPolicy; 67 68 //Convert string to lowercase 69 std::transform(policy.begin(), policy.end(), policy.begin(), 70 (int(*)(int)) tolower); 71 72 //Figure out fetch policy 73 if (policy == "dynamic") { 74 lsqPolicy = Dynamic; 75 76 maxLQEntries = LQEntries; 77 maxSQEntries = SQEntries; 78 79 DPRINTF(LSQ, "LSQ sharing policy set to Dynamic\n"); 80 } else if (policy == "partitioned") { 81 lsqPolicy = Partitioned; 82 83 //@todo:make work if part_amt doesnt divide evenly. 84 maxLQEntries = LQEntries / numThreads; 85 maxSQEntries = SQEntries / numThreads; 86 87 DPRINTF(Fetch, "LSQ sharing policy set to Partitioned: " 88 "%i entries per LQ | %i entries per SQ\n", 89 maxLQEntries,maxSQEntries); 90 } else if (policy == "threshold") { 91 lsqPolicy = Threshold; 92 93 assert(params->smtLSQThreshold > LQEntries); 94 assert(params->smtLSQThreshold > SQEntries); 95 96 //Divide up by threshold amount 97 //@todo: Should threads check the max and the total 98 //amount of the LSQ 99 maxLQEntries = params->smtLSQThreshold; 100 maxSQEntries = params->smtLSQThreshold; 101 102 DPRINTF(LSQ, "LSQ sharing policy set to Threshold: " 103 "%i entries per LQ | %i entries per SQ\n", 104 maxLQEntries,maxSQEntries); 105 } else { 106 assert(0 && "Invalid LSQ Sharing Policy.Options Are:{Dynamic," 107 "Partitioned, Threshold}"); 108 } 109 110 //Initialize LSQs 111 for (ThreadID tid = 0; tid < numThreads; tid++) { 112 thread[tid].init(cpu, iew_ptr, params, this, 113 maxLQEntries, maxSQEntries, tid); 114 thread[tid].setDcachePort(&cpu_ptr->getDataPort()); 115 } 116} 117 118 119template<class Impl> 120std::string 121LSQ<Impl>::name() const 122{ 123 return iewStage->name() + ".lsq"; 124} 125 126template<class Impl> 127void 128LSQ<Impl>::regStats() 129{ 130 //Initialize LSQs 131 for (ThreadID tid = 0; tid < numThreads; tid++) { 132 thread[tid].regStats(); 133 } 134} 135 136template<class Impl> 137void 138LSQ<Impl>::setActiveThreads(list<ThreadID> *at_ptr) 139{ 140 activeThreads = at_ptr; 141 assert(activeThreads != 0); 142} 143 144template <class Impl> 145void 146LSQ<Impl>::switchOut() 147{ 148 for (ThreadID tid = 0; tid < numThreads; tid++) { 149 thread[tid].switchOut(); 150 } 151} 152 153template <class Impl> 154void 155LSQ<Impl>::takeOverFrom() 156{ 157 for (ThreadID tid = 0; tid < numThreads; tid++) { 158 thread[tid].takeOverFrom(); 159 } 160} 161 162template <class Impl> 163int 164LSQ<Impl>::entryAmount(ThreadID num_threads) 165{ 166 if (lsqPolicy == Partitioned) { 167 return LQEntries / num_threads; 168 } else { 169 return 0; 170 } 171} 172 173template <class Impl> 174void 175LSQ<Impl>::resetEntries() 176{ 177 if (lsqPolicy != Dynamic || numThreads > 1) { 178 int active_threads = activeThreads->size(); 179 180 int maxEntries; 181 182 if (lsqPolicy == Partitioned) { 183 maxEntries = LQEntries / active_threads; 184 } else if (lsqPolicy == Threshold && active_threads == 1) { 185 maxEntries = LQEntries; 186 } else { 187 maxEntries = LQEntries; 188 } 189 190 list<ThreadID>::iterator threads = activeThreads->begin(); 191 list<ThreadID>::iterator end = activeThreads->end(); 192 193 while (threads != end) { 194 ThreadID tid = *threads++; 195 196 resizeEntries(maxEntries, tid); 197 } 198 } 199} 200 201template<class Impl> 202void 203LSQ<Impl>::removeEntries(ThreadID tid) 204{ 205 thread[tid].clearLQ(); 206 thread[tid].clearSQ(); 207} 208 209template<class Impl> 210void 211LSQ<Impl>::resizeEntries(unsigned size, ThreadID tid) 212{ 213 thread[tid].resizeLQ(size); 214 thread[tid].resizeSQ(size); 215} 216 217template<class Impl> 218void 219LSQ<Impl>::tick() 220{ 221 list<ThreadID>::iterator threads = activeThreads->begin(); 222 list<ThreadID>::iterator end = activeThreads->end(); 223 224 while (threads != end) { 225 ThreadID tid = *threads++; 226 227 thread[tid].tick(); 228 } 229} 230 231template<class Impl> 232void 233LSQ<Impl>::insertLoad(DynInstPtr &load_inst) 234{ 235 ThreadID tid = load_inst->threadNumber; 236 237 thread[tid].insertLoad(load_inst); 238} 239 240template<class Impl> 241void 242LSQ<Impl>::insertStore(DynInstPtr &store_inst) 243{ 244 ThreadID tid = store_inst->threadNumber; 245 246 thread[tid].insertStore(store_inst); 247} 248 249template<class Impl> 250Fault 251LSQ<Impl>::executeLoad(DynInstPtr &inst) 252{ 253 ThreadID tid = inst->threadNumber; 254 255 return thread[tid].executeLoad(inst); 256} 257 258template<class Impl> 259Fault 260LSQ<Impl>::executeStore(DynInstPtr &inst) 261{ 262 ThreadID tid = inst->threadNumber; 263 264 return thread[tid].executeStore(inst); 265} 266 267template<class Impl> 268void 269LSQ<Impl>::writebackStores() 270{ 271 list<ThreadID>::iterator threads = activeThreads->begin(); 272 list<ThreadID>::iterator end = activeThreads->end(); 273 274 while (threads != end) { 275 ThreadID tid = *threads++; 276 277 if (numStoresToWB(tid) > 0) { 278 DPRINTF(Writeback,"[tid:%i] Writing back stores. %i stores " 279 "available for Writeback.\n", tid, numStoresToWB(tid)); 280 } 281 282 thread[tid].writebackStores(); 283 } 284} 285 286template<class Impl> 287bool 288LSQ<Impl>::violation() 289{ 290 /* Answers: Does Anybody Have a Violation?*/ 291 list<ThreadID>::iterator threads = activeThreads->begin(); 292 list<ThreadID>::iterator end = activeThreads->end(); 293 294 while (threads != end) { 295 ThreadID tid = *threads++; 296 297 if (thread[tid].violation()) 298 return true; 299 } 300 301 return false; 302} 303 304template <class Impl> 305void 306LSQ<Impl>::recvRetry() 307{ 308 if (retryTid == InvalidThreadID) 309 { 310 //Squashed, so drop it 311 return; 312 } 313 int curr_retry_tid = retryTid; 314 // Speculatively clear the retry Tid. This will get set again if 315 // the LSQUnit was unable to complete its access. 316 retryTid = -1; 317 thread[curr_retry_tid].recvRetry(); 318} 319 320template <class Impl> 321bool 322LSQ<Impl>::recvTimingResp(PacketPtr pkt) 323{ 324 if (pkt->isError()) 325 DPRINTF(LSQ, "Got error packet back for address: %#X\n", 326 pkt->getAddr()); 327 thread[pkt->req->threadId()].completeDataAccess(pkt); 328 return true; 329} 330 331template <class Impl> 332void 333LSQ<Impl>::recvTimingSnoopReq(PacketPtr pkt) 334{ 335 DPRINTF(LSQ, "received pkt for addr:%#x %s\n", pkt->getAddr(), 336 pkt->cmdString()); 337 338 // must be a snoop 339 if (pkt->isInvalidate()) { 340 DPRINTF(LSQ, "received invalidation for addr:%#x\n", 341 pkt->getAddr()); 342 for (ThreadID tid = 0; tid < numThreads; tid++) { 343 thread[tid].checkSnoop(pkt); 344 } 345 } 346} 347 348template<class Impl> 349int 350LSQ<Impl>::getCount() 351{ 352 unsigned total = 0; 353 354 list<ThreadID>::iterator threads = activeThreads->begin(); 355 list<ThreadID>::iterator end = activeThreads->end(); 356 357 while (threads != end) { 358 ThreadID tid = *threads++; 359 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<ThreadID>::iterator threads = activeThreads->begin(); 373 list<ThreadID>::iterator end = activeThreads->end(); 374 375 while (threads != end) { 376 ThreadID tid = *threads++; 377 378 total += numLoads(tid); 379 } 380 381 return total; 382} 383 384template<class Impl> 385int 386LSQ<Impl>::numStores() 387{ 388 unsigned total = 0; 389 390 list<ThreadID>::iterator threads = activeThreads->begin(); 391 list<ThreadID>::iterator end = activeThreads->end(); 392 393 while (threads != end) { 394 ThreadID tid = *threads++; 395 396 total += thread[tid].numStores(); 397 } 398 399 return total; 400} 401 402template<class Impl> 403int 404LSQ<Impl>::numLoadsReady() 405{ 406 unsigned total = 0; 407 408 list<ThreadID>::iterator threads = activeThreads->begin(); 409 list<ThreadID>::iterator end = activeThreads->end(); 410 411 while (threads != end) { 412 ThreadID tid = *threads++; 413 414 total += thread[tid].numLoadsReady(); 415 } 416 417 return total; 418} 419 420template<class Impl> 421unsigned 422LSQ<Impl>::numFreeEntries() 423{ 424 unsigned total = 0; 425 426 list<ThreadID>::iterator threads = activeThreads->begin(); 427 list<ThreadID>::iterator end = activeThreads->end(); 428 429 while (threads != end) { 430 ThreadID tid = *threads++; 431 432 total += thread[tid].numFreeEntries(); 433 } 434 435 return total; 436} 437 438template<class Impl> 439unsigned 440LSQ<Impl>::numFreeEntries(ThreadID tid) 441{ 442 //if (lsqPolicy == Dynamic) 443 //return numFreeEntries(); 444 //else 445 return thread[tid].numFreeEntries(); 446} 447 448template<class Impl> 449bool 450LSQ<Impl>::isFull() 451{ 452 list<ThreadID>::iterator threads = activeThreads->begin(); 453 list<ThreadID>::iterator end = activeThreads->end(); 454 455 while (threads != end) { 456 ThreadID tid = *threads++; 457 458 if (!(thread[tid].lqFull() || thread[tid].sqFull())) 459 return false; 460 } 461 462 return true; 463} 464 465template<class Impl> 466bool 467LSQ<Impl>::isFull(ThreadID tid) 468{ 469 //@todo: Change to Calculate All Entries for 470 //Dynamic Policy 471 if (lsqPolicy == Dynamic) 472 return isFull(); 473 else 474 return thread[tid].lqFull() || thread[tid].sqFull(); 475} 476 477template<class Impl> 478bool 479LSQ<Impl>::lqFull() 480{ 481 list<ThreadID>::iterator threads = activeThreads->begin(); 482 list<ThreadID>::iterator end = activeThreads->end(); 483 484 while (threads != end) { 485 ThreadID tid = *threads++; 486 487 if (!thread[tid].lqFull()) 488 return false; 489 } 490 491 return true; 492} 493 494template<class Impl> 495bool 496LSQ<Impl>::lqFull(ThreadID tid) 497{ 498 //@todo: Change to Calculate All Entries for 499 //Dynamic Policy 500 if (lsqPolicy == Dynamic) 501 return lqFull(); 502 else 503 return thread[tid].lqFull(); 504} 505 506template<class Impl> 507bool 508LSQ<Impl>::sqFull() 509{ 510 list<ThreadID>::iterator threads = activeThreads->begin(); 511 list<ThreadID>::iterator end = activeThreads->end(); 512 513 while (threads != end) { 514 ThreadID tid = *threads++; 515 516 if (!sqFull(tid)) 517 return false; 518 } 519 520 return true; 521} 522 523template<class Impl> 524bool 525LSQ<Impl>::sqFull(ThreadID tid) 526{ 527 //@todo: Change to Calculate All Entries for 528 //Dynamic Policy 529 if (lsqPolicy == Dynamic) 530 return sqFull(); 531 else 532 return thread[tid].sqFull(); 533} 534 535template<class Impl> 536bool 537LSQ<Impl>::isStalled() 538{ 539 list<ThreadID>::iterator threads = activeThreads->begin(); 540 list<ThreadID>::iterator end = activeThreads->end(); 541 542 while (threads != end) { 543 ThreadID tid = *threads++; 544 545 if (!thread[tid].isStalled()) 546 return false; 547 } 548 549 return true; 550} 551 552template<class Impl> 553bool 554LSQ<Impl>::isStalled(ThreadID tid) 555{ 556 if (lsqPolicy == Dynamic) 557 return isStalled(); 558 else 559 return thread[tid].isStalled(); 560} 561 562template<class Impl> 563bool 564LSQ<Impl>::hasStoresToWB() 565{ 566 list<ThreadID>::iterator threads = activeThreads->begin(); 567 list<ThreadID>::iterator end = activeThreads->end(); 568 569 while (threads != end) { 570 ThreadID tid = *threads++; 571 572 if (hasStoresToWB(tid)) 573 return true; 574 } 575 576 return false; 577} 578 579template<class Impl> 580bool 581LSQ<Impl>::willWB() 582{ 583 list<ThreadID>::iterator threads = activeThreads->begin(); 584 list<ThreadID>::iterator end = activeThreads->end(); 585 586 while (threads != end) { 587 ThreadID tid = *threads++; 588 589 if (willWB(tid)) 590 return true; 591 } 592 593 return false; 594} 595 596template<class Impl> 597void 598LSQ<Impl>::dumpInsts() 599{ 600 list<ThreadID>::iterator threads = activeThreads->begin(); 601 list<ThreadID>::iterator end = activeThreads->end(); 602 603 while (threads != end) { 604 ThreadID tid = *threads++; 605 606 thread[tid].dumpInsts(); 607 } 608} 609