lsq_impl.hh revision 12749:223c83ed9979
12SN/A/* 211856Sbrandon.potter@amd.com * Copyright (c) 2011-2012, 2014 ARM Limited 31762SN/A * Copyright (c) 2013 Advanced Micro Devices, Inc. 42SN/A * All rights reserved 52SN/A * 62SN/A * The license below extends only to copyright in the software and shall 72SN/A * not be construed as granting a license to any other intellectual 82SN/A * property including but not limited to intellectual property relating 92SN/A * to a hardware implementation of the functionality of the software 102SN/A * licensed hereunder. You may use the software subject to the license 112SN/A * terms below provided that you ensure that this notice is replicated 122SN/A * unmodified and in its entirety in all distributions of the software, 132SN/A * modified or unmodified, in source code or in binary form. 142SN/A * 152SN/A * Copyright (c) 2005-2006 The Regents of The University of Michigan 162SN/A * All rights reserved. 172SN/A * 182SN/A * Redistribution and use in source and binary forms, with or without 192SN/A * modification, are permitted provided that the following conditions are 202SN/A * met: redistributions of source code must retain the above copyright 212SN/A * notice, this list of conditions and the following disclaimer; 222SN/A * redistributions in binary form must reproduce the above copyright 232SN/A * notice, this list of conditions and the following disclaimer in the 242SN/A * documentation and/or other materials provided with the distribution; 252SN/A * neither the name of the copyright holders nor the names of its 262SN/A * contributors may be used to endorse or promote products derived from 272SN/A * this software without specific prior written permission. 282665Ssaidi@eecs.umich.edu * 292665Ssaidi@eecs.umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 302665Ssaidi@eecs.umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 3111856Sbrandon.potter@amd.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 322SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 332SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 34360SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 35360SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 362SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 3711854Sbrandon.potter@amd.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 3811854Sbrandon.potter@amd.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 3911800Sbrandon.potter@amd.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 404117Sgblack@eecs.umich.edu * 41180SN/A * Authors: Korey Sewell 422SN/A */ 436329Sgblack@eecs.umich.edu 442378SN/A#ifndef __CPU_O3_LSQ_IMPL_HH__ 456214Snate@binkert.org#define __CPU_O3_LSQ_IMPL_HH__ 466658Snate@binkert.org 478852Sandreas.hansson@arm.com#include <algorithm> 4811856Sbrandon.potter@amd.com#include <list> 4910930Sbrandon.potter@amd.com#include <string> 5056SN/A 512SN/A#include "cpu/o3/lsq.hh" 528737Skoansin.tan@gmail.com#include "debug/Drain.hh" 5311800Sbrandon.potter@amd.com#include "debug/Fetch.hh" 5411800Sbrandon.potter@amd.com#include "debug/LSQ.hh" 5511851Sbrandon.potter@amd.com#include "debug/Writeback.hh" 5611800Sbrandon.potter@amd.com#include "params/DerivO3CPU.hh" 575154Sgblack@eecs.umich.edu 5811800Sbrandon.potter@amd.comusing namespace std; 595154Sgblack@eecs.umich.edu 602680Sktlim@umich.edutemplate <class Impl> 612378SN/ALSQ<Impl>::LSQ(O3CPU *cpu_ptr, IEW *iew_ptr, DerivO3CPUParams *params) 622SN/A : cpu(cpu_ptr), iewStage(iew_ptr), 632SN/A LQEntries(params->LQEntries), 642SN/A SQEntries(params->SQEntries), 652SN/A numThreads(params->numThreads) 662SN/A{ 672SN/A assert(numThreads > 0 && numThreads <= Impl::MaxThreads); 682680Sktlim@umich.edu 692SN/A //**********************************************/ 702680Sktlim@umich.edu //************ Handle SMT Parameters ***********/ 712SN/A //**********************************************/ 7211854Sbrandon.potter@amd.com std::string policy = params->smtLSQPolicy; 732SN/A 742SN/A //Convert string to lowercase 7511854Sbrandon.potter@amd.com std::transform(policy.begin(), policy.end(), policy.begin(), 762SN/A (int(*)(int)) tolower); 7711854Sbrandon.potter@amd.com 7811854Sbrandon.potter@amd.com //Figure out fetch policy 792SN/A if (policy == "dynamic") { 8011169Sandreas.hansson@arm.com lsqPolicy = Dynamic; 8111168Sandreas.hansson@arm.com 8210905Sandreas.sandberg@arm.com maxLQEntries = LQEntries; 8311877Sbrandon.potter@amd.com maxSQEntries = SQEntries; 8411854Sbrandon.potter@amd.com 8511854Sbrandon.potter@amd.com DPRINTF(LSQ, "LSQ sharing policy set to Dynamic\n"); 8611854Sbrandon.potter@amd.com } else if (policy == "partitioned") { 8711854Sbrandon.potter@amd.com lsqPolicy = Partitioned; 8811854Sbrandon.potter@amd.com 8911854Sbrandon.potter@amd.com //@todo:make work if part_amt doesnt divide evenly. 9011854Sbrandon.potter@amd.com maxLQEntries = LQEntries / numThreads; 912SN/A maxSQEntries = SQEntries / numThreads; 9211854Sbrandon.potter@amd.com 9311854Sbrandon.potter@amd.com DPRINTF(Fetch, "LSQ sharing policy set to Partitioned: " 9411854Sbrandon.potter@amd.com "%i entries per LQ | %i entries per SQ\n", 9511854Sbrandon.potter@amd.com maxLQEntries,maxSQEntries); 9611854Sbrandon.potter@amd.com } else if (policy == "threshold") { 9711854Sbrandon.potter@amd.com lsqPolicy = Threshold; 9810554Salexandru.dutu@amd.com 9911854Sbrandon.potter@amd.com assert(params->smtLSQThreshold > LQEntries); 10011854Sbrandon.potter@amd.com assert(params->smtLSQThreshold > SQEntries); 10111854Sbrandon.potter@amd.com 1028852Sandreas.hansson@arm.com //Divide up by threshold amount 10311854Sbrandon.potter@amd.com //@todo: Should threads check the max and the total 10411854Sbrandon.potter@amd.com //amount of the LSQ 10511854Sbrandon.potter@amd.com maxLQEntries = params->smtLSQThreshold; 10611854Sbrandon.potter@amd.com maxSQEntries = params->smtLSQThreshold; 10711854Sbrandon.potter@amd.com 10811854Sbrandon.potter@amd.com DPRINTF(LSQ, "LSQ sharing policy set to Threshold: " 10911854Sbrandon.potter@amd.com "%i entries per LQ | %i entries per SQ\n", 1108852Sandreas.hansson@arm.com maxLQEntries,maxSQEntries); 11111854Sbrandon.potter@amd.com } else { 11211854Sbrandon.potter@amd.com assert(0 && "Invalid LSQ Sharing Policy.Options Are:{Dynamic," 11311854Sbrandon.potter@amd.com "Partitioned, Threshold}"); 11411854Sbrandon.potter@amd.com } 11511854Sbrandon.potter@amd.com 11611854Sbrandon.potter@amd.com //Initialize LSQs 11711854Sbrandon.potter@amd.com thread = new LSQUnit[numThreads]; 1185282Srstrong@cs.ucsd.edu for (ThreadID tid = 0; tid < numThreads; tid++) { 1192SN/A thread[tid].init(cpu, iew_ptr, params, this, 12011169Sandreas.hansson@arm.com maxLQEntries, maxSQEntries, tid); 1212SN/A thread[tid].setDcachePort(&cpu_ptr->getDataPort()); 1228601Ssteve.reinhardt@amd.com } 1238601Ssteve.reinhardt@amd.com} 1248539Sgblack@eecs.umich.edu 1258539Sgblack@eecs.umich.edu 1268539Sgblack@eecs.umich.edutemplate<class Impl> 1274434Ssaidi@eecs.umich.edustd::string 12811854Sbrandon.potter@amd.comLSQ<Impl>::name() const 12911854Sbrandon.potter@amd.com{ 13011854Sbrandon.potter@amd.com return iewStage->name() + ".lsq"; 13111854Sbrandon.potter@amd.com} 13211854Sbrandon.potter@amd.com 13311854Sbrandon.potter@amd.comtemplate<class Impl> 13411854Sbrandon.potter@amd.comvoid 13511854Sbrandon.potter@amd.comLSQ<Impl>::regStats() 13611854Sbrandon.potter@amd.com{ 13711854Sbrandon.potter@amd.com //Initialize LSQs 13811854Sbrandon.potter@amd.com for (ThreadID tid = 0; tid < numThreads; tid++) { 13911854Sbrandon.potter@amd.com thread[tid].regStats(); 14011854Sbrandon.potter@amd.com } 14111854Sbrandon.potter@amd.com} 14211854Sbrandon.potter@amd.com 14311854Sbrandon.potter@amd.comtemplate<class Impl> 14411854Sbrandon.potter@amd.comvoid 14511854Sbrandon.potter@amd.comLSQ<Impl>::setActiveThreads(list<ThreadID> *at_ptr) 1469110Ssteve.reinhardt@amd.com{ 14710558Salexandru.dutu@amd.com activeThreads = at_ptr; 1489110Ssteve.reinhardt@amd.com assert(activeThreads != 0); 14910558Salexandru.dutu@amd.com} 15010558Salexandru.dutu@amd.com 1519110Ssteve.reinhardt@amd.comtemplate <class Impl> 1529110Ssteve.reinhardt@amd.comvoid 1539110Ssteve.reinhardt@amd.comLSQ<Impl>::drainSanityCheck() const 1549110Ssteve.reinhardt@amd.com{ 15510558Salexandru.dutu@amd.com assert(isDrained()); 1569110Ssteve.reinhardt@amd.com 1579110Ssteve.reinhardt@amd.com for (ThreadID tid = 0; tid < numThreads; tid++) 1589110Ssteve.reinhardt@amd.com thread[tid].drainSanityCheck(); 15910558Salexandru.dutu@amd.com} 1609110Ssteve.reinhardt@amd.com 16111854Sbrandon.potter@amd.comtemplate <class Impl> 16211854Sbrandon.potter@amd.combool 16311801Sbrandon.potter@amd.comLSQ<Impl>::isDrained() const 16411854Sbrandon.potter@amd.com{ 16511854Sbrandon.potter@amd.com bool drained(true); 16611854Sbrandon.potter@amd.com 16711854Sbrandon.potter@amd.com if (!lqEmpty()) { 16811854Sbrandon.potter@amd.com DPRINTF(Drain, "Not drained, LQ not empty.\n"); 16911854Sbrandon.potter@amd.com drained = false; 17011854Sbrandon.potter@amd.com } 17111854Sbrandon.potter@amd.com 17211854Sbrandon.potter@amd.com if (!sqEmpty()) { 17311854Sbrandon.potter@amd.com DPRINTF(Drain, "Not drained, SQ not empty.\n"); 17411854Sbrandon.potter@amd.com drained = false; 17511854Sbrandon.potter@amd.com } 17611854Sbrandon.potter@amd.com 17711854Sbrandon.potter@amd.com return drained; 17811854Sbrandon.potter@amd.com} 17911854Sbrandon.potter@amd.com 18011854Sbrandon.potter@amd.comtemplate <class Impl> 18111854Sbrandon.potter@amd.comvoid 18211854Sbrandon.potter@amd.comLSQ<Impl>::takeOverFrom() 18311854Sbrandon.potter@amd.com{ 18411854Sbrandon.potter@amd.com for (ThreadID tid = 0; tid < numThreads; tid++) { 18511854Sbrandon.potter@amd.com thread[tid].takeOverFrom(); 18611854Sbrandon.potter@amd.com } 18711851Sbrandon.potter@amd.com} 18811851Sbrandon.potter@amd.com 18911851Sbrandon.potter@amd.comtemplate <class Impl> 19011851Sbrandon.potter@amd.comint 19111851Sbrandon.potter@amd.comLSQ<Impl>::entryAmount(ThreadID num_threads) 19211851Sbrandon.potter@amd.com{ 19311801Sbrandon.potter@amd.com if (lsqPolicy == Partitioned) { 19411801Sbrandon.potter@amd.com return LQEntries / num_threads; 19511801Sbrandon.potter@amd.com } else { 19611801Sbrandon.potter@amd.com return 0; 19711801Sbrandon.potter@amd.com } 19811801Sbrandon.potter@amd.com} 19911801Sbrandon.potter@amd.com 20011801Sbrandon.potter@amd.comtemplate <class Impl> 20111801Sbrandon.potter@amd.comvoid 20211801Sbrandon.potter@amd.comLSQ<Impl>::resetEntries() 20310496Ssteve.reinhardt@amd.com{ 20410496Ssteve.reinhardt@amd.com if (lsqPolicy != Dynamic || numThreads > 1) { 20511856Sbrandon.potter@amd.com int active_threads = activeThreads->size(); 20611856Sbrandon.potter@amd.com 2072SN/A int maxEntries; 2082SN/A 209360SN/A if (lsqPolicy == Partitioned) { 210 maxEntries = LQEntries / active_threads; 211 } else if (lsqPolicy == Threshold && active_threads == 1) { 212 maxEntries = LQEntries; 213 } else { 214 maxEntries = LQEntries; 215 } 216 217 list<ThreadID>::iterator threads = activeThreads->begin(); 218 list<ThreadID>::iterator end = activeThreads->end(); 219 220 while (threads != end) { 221 ThreadID tid = *threads++; 222 223 resizeEntries(maxEntries, tid); 224 } 225 } 226} 227 228template<class Impl> 229void 230LSQ<Impl>::removeEntries(ThreadID tid) 231{ 232 thread[tid].clearLQ(); 233 thread[tid].clearSQ(); 234} 235 236template<class Impl> 237void 238LSQ<Impl>::resizeEntries(unsigned size, ThreadID tid) 239{ 240 thread[tid].resizeLQ(size); 241 thread[tid].resizeSQ(size); 242} 243 244template<class Impl> 245void 246LSQ<Impl>::tick() 247{ 248 list<ThreadID>::iterator threads = activeThreads->begin(); 249 list<ThreadID>::iterator end = activeThreads->end(); 250 251 while (threads != end) { 252 ThreadID tid = *threads++; 253 254 thread[tid].tick(); 255 } 256} 257 258template<class Impl> 259void 260LSQ<Impl>::insertLoad(DynInstPtr &load_inst) 261{ 262 ThreadID tid = load_inst->threadNumber; 263 264 thread[tid].insertLoad(load_inst); 265} 266 267template<class Impl> 268void 269LSQ<Impl>::insertStore(DynInstPtr &store_inst) 270{ 271 ThreadID tid = store_inst->threadNumber; 272 273 thread[tid].insertStore(store_inst); 274} 275 276template<class Impl> 277Fault 278LSQ<Impl>::executeLoad(DynInstPtr &inst) 279{ 280 ThreadID tid = inst->threadNumber; 281 282 return thread[tid].executeLoad(inst); 283} 284 285template<class Impl> 286Fault 287LSQ<Impl>::executeStore(DynInstPtr &inst) 288{ 289 ThreadID tid = inst->threadNumber; 290 291 return thread[tid].executeStore(inst); 292} 293 294template<class Impl> 295void 296LSQ<Impl>::writebackStores() 297{ 298 list<ThreadID>::iterator threads = activeThreads->begin(); 299 list<ThreadID>::iterator end = activeThreads->end(); 300 301 while (threads != end) { 302 ThreadID tid = *threads++; 303 304 if (numStoresToWB(tid) > 0) { 305 DPRINTF(Writeback,"[tid:%i] Writing back stores. %i stores " 306 "available for Writeback.\n", tid, numStoresToWB(tid)); 307 } 308 309 thread[tid].writebackStores(); 310 } 311} 312 313template<class Impl> 314bool 315LSQ<Impl>::violation() 316{ 317 /* Answers: Does Anybody Have a Violation?*/ 318 list<ThreadID>::iterator threads = activeThreads->begin(); 319 list<ThreadID>::iterator end = activeThreads->end(); 320 321 while (threads != end) { 322 ThreadID tid = *threads++; 323 324 if (thread[tid].violation()) 325 return true; 326 } 327 328 return false; 329} 330 331template <class Impl> 332void 333LSQ<Impl>::recvReqRetry() 334{ 335 iewStage->cacheUnblocked(); 336 337 for (ThreadID tid : *activeThreads) { 338 thread[tid].recvRetry(); 339 } 340} 341 342template <class Impl> 343bool 344LSQ<Impl>::recvTimingResp(PacketPtr pkt) 345{ 346 if (pkt->isError()) 347 DPRINTF(LSQ, "Got error packet back for address: %#X\n", 348 pkt->getAddr()); 349 350 thread[cpu->contextToThread(pkt->req->contextId())] 351 .completeDataAccess(pkt); 352 353 if (pkt->isInvalidate()) { 354 // This response also contains an invalidate; e.g. this can be the case 355 // if cmd is ReadRespWithInvalidate. 356 // 357 // The calling order between completeDataAccess and checkSnoop matters. 358 // By calling checkSnoop after completeDataAccess, we ensure that the 359 // fault set by checkSnoop is not lost. Calling writeback (more 360 // specifically inst->completeAcc) in completeDataAccess overwrites 361 // fault, and in case this instruction requires squashing (as 362 // determined by checkSnoop), the ReExec fault set by checkSnoop would 363 // be lost otherwise. 364 365 DPRINTF(LSQ, "received invalidation with response for addr:%#x\n", 366 pkt->getAddr()); 367 368 for (ThreadID tid = 0; tid < numThreads; tid++) { 369 thread[tid].checkSnoop(pkt); 370 } 371 } 372 373 delete pkt; 374 return true; 375} 376 377template <class Impl> 378void 379LSQ<Impl>::recvTimingSnoopReq(PacketPtr pkt) 380{ 381 DPRINTF(LSQ, "received pkt for addr:%#x %s\n", pkt->getAddr(), 382 pkt->cmdString()); 383 384 // must be a snoop 385 if (pkt->isInvalidate()) { 386 DPRINTF(LSQ, "received invalidation for addr:%#x\n", 387 pkt->getAddr()); 388 for (ThreadID tid = 0; tid < numThreads; tid++) { 389 thread[tid].checkSnoop(pkt); 390 } 391 } 392} 393 394template<class Impl> 395int 396LSQ<Impl>::getCount() 397{ 398 unsigned total = 0; 399 400 list<ThreadID>::iterator threads = activeThreads->begin(); 401 list<ThreadID>::iterator end = activeThreads->end(); 402 403 while (threads != end) { 404 ThreadID tid = *threads++; 405 406 total += getCount(tid); 407 } 408 409 return total; 410} 411 412template<class Impl> 413int 414LSQ<Impl>::numLoads() 415{ 416 unsigned total = 0; 417 418 list<ThreadID>::iterator threads = activeThreads->begin(); 419 list<ThreadID>::iterator end = activeThreads->end(); 420 421 while (threads != end) { 422 ThreadID tid = *threads++; 423 424 total += numLoads(tid); 425 } 426 427 return total; 428} 429 430template<class Impl> 431int 432LSQ<Impl>::numStores() 433{ 434 unsigned total = 0; 435 436 list<ThreadID>::iterator threads = activeThreads->begin(); 437 list<ThreadID>::iterator end = activeThreads->end(); 438 439 while (threads != end) { 440 ThreadID tid = *threads++; 441 442 total += thread[tid].numStores(); 443 } 444 445 return total; 446} 447 448template<class Impl> 449unsigned 450LSQ<Impl>::numFreeLoadEntries() 451{ 452 unsigned total = 0; 453 454 list<ThreadID>::iterator threads = activeThreads->begin(); 455 list<ThreadID>::iterator end = activeThreads->end(); 456 457 while (threads != end) { 458 ThreadID tid = *threads++; 459 460 total += thread[tid].numFreeLoadEntries(); 461 } 462 463 return total; 464} 465 466template<class Impl> 467unsigned 468LSQ<Impl>::numFreeStoreEntries() 469{ 470 unsigned total = 0; 471 472 list<ThreadID>::iterator threads = activeThreads->begin(); 473 list<ThreadID>::iterator end = activeThreads->end(); 474 475 while (threads != end) { 476 ThreadID tid = *threads++; 477 478 total += thread[tid].numFreeStoreEntries(); 479 } 480 481 return total; 482} 483 484template<class Impl> 485unsigned 486LSQ<Impl>::numFreeLoadEntries(ThreadID tid) 487{ 488 return thread[tid].numFreeLoadEntries(); 489} 490 491template<class Impl> 492unsigned 493LSQ<Impl>::numFreeStoreEntries(ThreadID tid) 494{ 495 return thread[tid].numFreeStoreEntries(); 496} 497 498template<class Impl> 499bool 500LSQ<Impl>::isFull() 501{ 502 list<ThreadID>::iterator threads = activeThreads->begin(); 503 list<ThreadID>::iterator end = activeThreads->end(); 504 505 while (threads != end) { 506 ThreadID tid = *threads++; 507 508 if (!(thread[tid].lqFull() || thread[tid].sqFull())) 509 return false; 510 } 511 512 return true; 513} 514 515template<class Impl> 516bool 517LSQ<Impl>::isFull(ThreadID tid) 518{ 519 //@todo: Change to Calculate All Entries for 520 //Dynamic Policy 521 if (lsqPolicy == Dynamic) 522 return isFull(); 523 else 524 return thread[tid].lqFull() || thread[tid].sqFull(); 525} 526 527template<class Impl> 528bool 529LSQ<Impl>::isEmpty() const 530{ 531 return lqEmpty() && sqEmpty(); 532} 533 534template<class Impl> 535bool 536LSQ<Impl>::lqEmpty() const 537{ 538 list<ThreadID>::const_iterator threads = activeThreads->begin(); 539 list<ThreadID>::const_iterator end = activeThreads->end(); 540 541 while (threads != end) { 542 ThreadID tid = *threads++; 543 544 if (!thread[tid].lqEmpty()) 545 return false; 546 } 547 548 return true; 549} 550 551template<class Impl> 552bool 553LSQ<Impl>::sqEmpty() const 554{ 555 list<ThreadID>::const_iterator threads = activeThreads->begin(); 556 list<ThreadID>::const_iterator end = activeThreads->end(); 557 558 while (threads != end) { 559 ThreadID tid = *threads++; 560 561 if (!thread[tid].sqEmpty()) 562 return false; 563 } 564 565 return true; 566} 567 568template<class Impl> 569bool 570LSQ<Impl>::lqFull() 571{ 572 list<ThreadID>::iterator threads = activeThreads->begin(); 573 list<ThreadID>::iterator end = activeThreads->end(); 574 575 while (threads != end) { 576 ThreadID tid = *threads++; 577 578 if (!thread[tid].lqFull()) 579 return false; 580 } 581 582 return true; 583} 584 585template<class Impl> 586bool 587LSQ<Impl>::lqFull(ThreadID tid) 588{ 589 //@todo: Change to Calculate All Entries for 590 //Dynamic Policy 591 if (lsqPolicy == Dynamic) 592 return lqFull(); 593 else 594 return thread[tid].lqFull(); 595} 596 597template<class Impl> 598bool 599LSQ<Impl>::sqFull() 600{ 601 list<ThreadID>::iterator threads = activeThreads->begin(); 602 list<ThreadID>::iterator end = activeThreads->end(); 603 604 while (threads != end) { 605 ThreadID tid = *threads++; 606 607 if (!sqFull(tid)) 608 return false; 609 } 610 611 return true; 612} 613 614template<class Impl> 615bool 616LSQ<Impl>::sqFull(ThreadID tid) 617{ 618 //@todo: Change to Calculate All Entries for 619 //Dynamic Policy 620 if (lsqPolicy == Dynamic) 621 return sqFull(); 622 else 623 return thread[tid].sqFull(); 624} 625 626template<class Impl> 627bool 628LSQ<Impl>::isStalled() 629{ 630 list<ThreadID>::iterator threads = activeThreads->begin(); 631 list<ThreadID>::iterator end = activeThreads->end(); 632 633 while (threads != end) { 634 ThreadID tid = *threads++; 635 636 if (!thread[tid].isStalled()) 637 return false; 638 } 639 640 return true; 641} 642 643template<class Impl> 644bool 645LSQ<Impl>::isStalled(ThreadID tid) 646{ 647 if (lsqPolicy == Dynamic) 648 return isStalled(); 649 else 650 return thread[tid].isStalled(); 651} 652 653template<class Impl> 654bool 655LSQ<Impl>::hasStoresToWB() 656{ 657 list<ThreadID>::iterator threads = activeThreads->begin(); 658 list<ThreadID>::iterator end = activeThreads->end(); 659 660 while (threads != end) { 661 ThreadID tid = *threads++; 662 663 if (hasStoresToWB(tid)) 664 return true; 665 } 666 667 return false; 668} 669 670template<class Impl> 671bool 672LSQ<Impl>::willWB() 673{ 674 list<ThreadID>::iterator threads = activeThreads->begin(); 675 list<ThreadID>::iterator end = activeThreads->end(); 676 677 while (threads != end) { 678 ThreadID tid = *threads++; 679 680 if (willWB(tid)) 681 return true; 682 } 683 684 return false; 685} 686 687template<class Impl> 688void 689LSQ<Impl>::dumpInsts() const 690{ 691 list<ThreadID>::const_iterator threads = activeThreads->begin(); 692 list<ThreadID>::const_iterator end = activeThreads->end(); 693 694 while (threads != end) { 695 ThreadID tid = *threads++; 696 697 thread[tid].dumpInsts(); 698 } 699} 700 701#endif//__CPU_O3_LSQ_IMPL_HH__ 702