lsq_impl.hh revision 8850
1/* 2 * Copyright (c) 2011 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>::recvTiming(PacketPtr pkt) 323{ 324 if (pkt->isError()) 325 DPRINTF(LSQ, "Got error packet back for address: %#X\n", 326 pkt->getAddr()); 327 if (pkt->isResponse()) { 328 thread[pkt->req->threadId()].completeDataAccess(pkt); 329 } else { 330 DPRINTF(LSQ, "received pkt for addr:%#x %s\n", pkt->getAddr(), 331 pkt->cmdString()); 332 333 // must be a snoop 334 if (pkt->isInvalidate()) { 335 DPRINTF(LSQ, "received invalidation for addr:%#x\n", 336 pkt->getAddr()); 337 for (ThreadID tid = 0; tid < numThreads; tid++) { 338 thread[tid].checkSnoop(pkt); 339 } 340 } 341 // to provide stronger consistency model 342 } 343 return true; 344} 345 346template<class Impl> 347int 348LSQ<Impl>::getCount() 349{ 350 unsigned total = 0; 351 352 list<ThreadID>::iterator threads = activeThreads->begin(); 353 list<ThreadID>::iterator end = activeThreads->end(); 354 355 while (threads != end) { 356 ThreadID tid = *threads++; 357 358 total += getCount(tid); 359 } 360 361 return total; 362} 363 364template<class Impl> 365int 366LSQ<Impl>::numLoads() 367{ 368 unsigned total = 0; 369 370 list<ThreadID>::iterator threads = activeThreads->begin(); 371 list<ThreadID>::iterator end = activeThreads->end(); 372 373 while (threads != end) { 374 ThreadID tid = *threads++; 375 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<ThreadID>::iterator threads = activeThreads->begin(); 389 list<ThreadID>::iterator end = activeThreads->end(); 390 391 while (threads != end) { 392 ThreadID tid = *threads++; 393 394 total += thread[tid].numStores(); 395 } 396 397 return total; 398} 399 400template<class Impl> 401int 402LSQ<Impl>::numLoadsReady() 403{ 404 unsigned total = 0; 405 406 list<ThreadID>::iterator threads = activeThreads->begin(); 407 list<ThreadID>::iterator end = activeThreads->end(); 408 409 while (threads != end) { 410 ThreadID tid = *threads++; 411 412 total += thread[tid].numLoadsReady(); 413 } 414 415 return total; 416} 417 418template<class Impl> 419unsigned 420LSQ<Impl>::numFreeEntries() 421{ 422 unsigned total = 0; 423 424 list<ThreadID>::iterator threads = activeThreads->begin(); 425 list<ThreadID>::iterator end = activeThreads->end(); 426 427 while (threads != end) { 428 ThreadID tid = *threads++; 429 430 total += thread[tid].numFreeEntries(); 431 } 432 433 return total; 434} 435 436template<class Impl> 437unsigned 438LSQ<Impl>::numFreeEntries(ThreadID tid) 439{ 440 //if (lsqPolicy == Dynamic) 441 //return numFreeEntries(); 442 //else 443 return thread[tid].numFreeEntries(); 444} 445 446template<class Impl> 447bool 448LSQ<Impl>::isFull() 449{ 450 list<ThreadID>::iterator threads = activeThreads->begin(); 451 list<ThreadID>::iterator end = activeThreads->end(); 452 453 while (threads != end) { 454 ThreadID tid = *threads++; 455 456 if (!(thread[tid].lqFull() || thread[tid].sqFull())) 457 return false; 458 } 459 460 return true; 461} 462 463template<class Impl> 464bool 465LSQ<Impl>::isFull(ThreadID tid) 466{ 467 //@todo: Change to Calculate All Entries for 468 //Dynamic Policy 469 if (lsqPolicy == Dynamic) 470 return isFull(); 471 else 472 return thread[tid].lqFull() || thread[tid].sqFull(); 473} 474 475template<class Impl> 476bool 477LSQ<Impl>::lqFull() 478{ 479 list<ThreadID>::iterator threads = activeThreads->begin(); 480 list<ThreadID>::iterator end = activeThreads->end(); 481 482 while (threads != end) { 483 ThreadID tid = *threads++; 484 485 if (!thread[tid].lqFull()) 486 return false; 487 } 488 489 return true; 490} 491 492template<class Impl> 493bool 494LSQ<Impl>::lqFull(ThreadID tid) 495{ 496 //@todo: Change to Calculate All Entries for 497 //Dynamic Policy 498 if (lsqPolicy == Dynamic) 499 return lqFull(); 500 else 501 return thread[tid].lqFull(); 502} 503 504template<class Impl> 505bool 506LSQ<Impl>::sqFull() 507{ 508 list<ThreadID>::iterator threads = activeThreads->begin(); 509 list<ThreadID>::iterator end = activeThreads->end(); 510 511 while (threads != end) { 512 ThreadID tid = *threads++; 513 514 if (!sqFull(tid)) 515 return false; 516 } 517 518 return true; 519} 520 521template<class Impl> 522bool 523LSQ<Impl>::sqFull(ThreadID tid) 524{ 525 //@todo: Change to Calculate All Entries for 526 //Dynamic Policy 527 if (lsqPolicy == Dynamic) 528 return sqFull(); 529 else 530 return thread[tid].sqFull(); 531} 532 533template<class Impl> 534bool 535LSQ<Impl>::isStalled() 536{ 537 list<ThreadID>::iterator threads = activeThreads->begin(); 538 list<ThreadID>::iterator end = activeThreads->end(); 539 540 while (threads != end) { 541 ThreadID tid = *threads++; 542 543 if (!thread[tid].isStalled()) 544 return false; 545 } 546 547 return true; 548} 549 550template<class Impl> 551bool 552LSQ<Impl>::isStalled(ThreadID tid) 553{ 554 if (lsqPolicy == Dynamic) 555 return isStalled(); 556 else 557 return thread[tid].isStalled(); 558} 559 560template<class Impl> 561bool 562LSQ<Impl>::hasStoresToWB() 563{ 564 list<ThreadID>::iterator threads = activeThreads->begin(); 565 list<ThreadID>::iterator end = activeThreads->end(); 566 567 while (threads != end) { 568 ThreadID tid = *threads++; 569 570 if (hasStoresToWB(tid)) 571 return true; 572 } 573 574 return false; 575} 576 577template<class Impl> 578bool 579LSQ<Impl>::willWB() 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 (willWB(tid)) 588 return true; 589 } 590 591 return false; 592} 593 594template<class Impl> 595void 596LSQ<Impl>::dumpInsts() 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 thread[tid].dumpInsts(); 605 } 606} 607