lsq_impl.hh revision 9440
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> 403unsigned 404LSQ<Impl>::numFreeEntries() 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].numFreeEntries(); 415 } 416 417 return total; 418} 419 420template<class Impl> 421unsigned 422LSQ<Impl>::numFreeEntries(ThreadID tid) 423{ 424 //if (lsqPolicy == Dynamic) 425 //return numFreeEntries(); 426 //else 427 return thread[tid].numFreeEntries(); 428} 429 430template<class Impl> 431bool 432LSQ<Impl>::isFull() 433{ 434 list<ThreadID>::iterator threads = activeThreads->begin(); 435 list<ThreadID>::iterator end = activeThreads->end(); 436 437 while (threads != end) { 438 ThreadID tid = *threads++; 439 440 if (!(thread[tid].lqFull() || thread[tid].sqFull())) 441 return false; 442 } 443 444 return true; 445} 446 447template<class Impl> 448bool 449LSQ<Impl>::isFull(ThreadID tid) 450{ 451 //@todo: Change to Calculate All Entries for 452 //Dynamic Policy 453 if (lsqPolicy == Dynamic) 454 return isFull(); 455 else 456 return thread[tid].lqFull() || thread[tid].sqFull(); 457} 458 459template<class Impl> 460bool 461LSQ<Impl>::lqFull() 462{ 463 list<ThreadID>::iterator threads = activeThreads->begin(); 464 list<ThreadID>::iterator end = activeThreads->end(); 465 466 while (threads != end) { 467 ThreadID tid = *threads++; 468 469 if (!thread[tid].lqFull()) 470 return false; 471 } 472 473 return true; 474} 475 476template<class Impl> 477bool 478LSQ<Impl>::lqFull(ThreadID tid) 479{ 480 //@todo: Change to Calculate All Entries for 481 //Dynamic Policy 482 if (lsqPolicy == Dynamic) 483 return lqFull(); 484 else 485 return thread[tid].lqFull(); 486} 487 488template<class Impl> 489bool 490LSQ<Impl>::sqFull() 491{ 492 list<ThreadID>::iterator threads = activeThreads->begin(); 493 list<ThreadID>::iterator end = activeThreads->end(); 494 495 while (threads != end) { 496 ThreadID tid = *threads++; 497 498 if (!sqFull(tid)) 499 return false; 500 } 501 502 return true; 503} 504 505template<class Impl> 506bool 507LSQ<Impl>::sqFull(ThreadID tid) 508{ 509 //@todo: Change to Calculate All Entries for 510 //Dynamic Policy 511 if (lsqPolicy == Dynamic) 512 return sqFull(); 513 else 514 return thread[tid].sqFull(); 515} 516 517template<class Impl> 518bool 519LSQ<Impl>::isStalled() 520{ 521 list<ThreadID>::iterator threads = activeThreads->begin(); 522 list<ThreadID>::iterator end = activeThreads->end(); 523 524 while (threads != end) { 525 ThreadID tid = *threads++; 526 527 if (!thread[tid].isStalled()) 528 return false; 529 } 530 531 return true; 532} 533 534template<class Impl> 535bool 536LSQ<Impl>::isStalled(ThreadID tid) 537{ 538 if (lsqPolicy == Dynamic) 539 return isStalled(); 540 else 541 return thread[tid].isStalled(); 542} 543 544template<class Impl> 545bool 546LSQ<Impl>::hasStoresToWB() 547{ 548 list<ThreadID>::iterator threads = activeThreads->begin(); 549 list<ThreadID>::iterator end = activeThreads->end(); 550 551 while (threads != end) { 552 ThreadID tid = *threads++; 553 554 if (hasStoresToWB(tid)) 555 return true; 556 } 557 558 return false; 559} 560 561template<class Impl> 562bool 563LSQ<Impl>::willWB() 564{ 565 list<ThreadID>::iterator threads = activeThreads->begin(); 566 list<ThreadID>::iterator end = activeThreads->end(); 567 568 while (threads != end) { 569 ThreadID tid = *threads++; 570 571 if (willWB(tid)) 572 return true; 573 } 574 575 return false; 576} 577 578template<class Impl> 579void 580LSQ<Impl>::dumpInsts() const 581{ 582 list<ThreadID>::const_iterator threads = activeThreads->begin(); 583 list<ThreadID>::const_iterator end = activeThreads->end(); 584 585 while (threads != end) { 586 ThreadID tid = *threads++; 587 588 thread[tid].dumpInsts(); 589 } 590} 591