rob_impl.hh revision 13449
18706Sandreas.hansson@arm.com/* 28706Sandreas.hansson@arm.com * Copyright (c) 2012 ARM Limited 38706Sandreas.hansson@arm.com * All rights reserved 48706Sandreas.hansson@arm.com * 58706Sandreas.hansson@arm.com * The license below extends only to copyright in the software and shall 68706Sandreas.hansson@arm.com * not be construed as granting a license to any other intellectual 78706Sandreas.hansson@arm.com * property including but not limited to intellectual property relating 88706Sandreas.hansson@arm.com * to a hardware implementation of the functionality of the software 98706Sandreas.hansson@arm.com * licensed hereunder. You may use the software subject to the license 108706Sandreas.hansson@arm.com * terms below provided that you ensure that this notice is replicated 118706Sandreas.hansson@arm.com * unmodified and in its entirety in all distributions of the software, 128706Sandreas.hansson@arm.com * modified or unmodified, in source code or in binary form. 136892SBrad.Beckmann@amd.com * 146892SBrad.Beckmann@amd.com * Copyright (c) 2004-2006 The Regents of The University of Michigan 156892SBrad.Beckmann@amd.com * All rights reserved. 166892SBrad.Beckmann@amd.com * 176892SBrad.Beckmann@amd.com * Redistribution and use in source and binary forms, with or without 186892SBrad.Beckmann@amd.com * modification, are permitted provided that the following conditions are 196892SBrad.Beckmann@amd.com * met: redistributions of source code must retain the above copyright 206892SBrad.Beckmann@amd.com * notice, this list of conditions and the following disclaimer; 216892SBrad.Beckmann@amd.com * redistributions in binary form must reproduce the above copyright 226892SBrad.Beckmann@amd.com * notice, this list of conditions and the following disclaimer in the 236892SBrad.Beckmann@amd.com * documentation and/or other materials provided with the distribution; 246892SBrad.Beckmann@amd.com * neither the name of the copyright holders nor the names of its 256892SBrad.Beckmann@amd.com * contributors may be used to endorse or promote products derived from 266892SBrad.Beckmann@amd.com * this software without specific prior written permission. 276892SBrad.Beckmann@amd.com * 286892SBrad.Beckmann@amd.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 296892SBrad.Beckmann@amd.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 306892SBrad.Beckmann@amd.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 316892SBrad.Beckmann@amd.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 326892SBrad.Beckmann@amd.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 336892SBrad.Beckmann@amd.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 346892SBrad.Beckmann@amd.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 356892SBrad.Beckmann@amd.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 366892SBrad.Beckmann@amd.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 376892SBrad.Beckmann@amd.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 386892SBrad.Beckmann@amd.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 396892SBrad.Beckmann@amd.com * 406892SBrad.Beckmann@amd.com * Authors: Kevin Lim 416892SBrad.Beckmann@amd.com * Korey Sewell 427563SBrad.Beckmann@amd.com */ 436892SBrad.Beckmann@amd.com 446892SBrad.Beckmann@amd.com#ifndef __CPU_O3_ROB_IMPL_HH__ 456892SBrad.Beckmann@amd.com#define __CPU_O3_ROB_IMPL_HH__ 4610118Snilay@cs.wisc.edu 4710118Snilay@cs.wisc.edu#include <list> 4810524Snilay@cs.wisc.edu 4910118Snilay@cs.wisc.edu#include "base/logging.hh" 506892SBrad.Beckmann@amd.com#include "cpu/o3/rob.hh" 517538SBrad.Beckmann@amd.com#include "debug/Fetch.hh" 528939SBrad.Beckmann@amd.com#include "debug/ROB.hh" 538939SBrad.Beckmann@amd.com#include "params/DerivO3CPU.hh" 548939SBrad.Beckmann@amd.com 559791Sakash.bagdia@arm.comusing namespace std; 569791Sakash.bagdia@arm.com 579791Sakash.bagdia@arm.comtemplate <class Impl> 589791Sakash.bagdia@arm.comROB<Impl>::ROB(O3CPU *_cpu, DerivO3CPUParams *params) 5910525Snilay@cs.wisc.edu : cpu(_cpu), 6010525Snilay@cs.wisc.edu numEntries(params->numROBEntries), 6110525Snilay@cs.wisc.edu squashWidth(params->squashWidth), 629841Snilay@cs.wisc.edu numInstsInROB(0), 639841Snilay@cs.wisc.edu numThreads(params->numThreads) 649841Snilay@cs.wisc.edu{ 659841Snilay@cs.wisc.edu std::string policy = params->smtROBPolicy; 669841Snilay@cs.wisc.edu 677538SBrad.Beckmann@amd.com //Convert string to lowercase 687538SBrad.Beckmann@amd.com std::transform(policy.begin(), policy.end(), policy.begin(), 697538SBrad.Beckmann@amd.com (int(*)(int)) tolower); 707538SBrad.Beckmann@amd.com 717538SBrad.Beckmann@amd.com //Figure out rob policy 729576Snilay@cs.wisc.edu if (policy == "dynamic") { 739576Snilay@cs.wisc.edu robPolicy = Dynamic; 748612Stushar@csail.mit.edu 758612Stushar@csail.mit.edu //Set Max Entries to Total ROB Capacity 767538SBrad.Beckmann@amd.com for (ThreadID tid = 0; tid < numThreads; tid++) { 777538SBrad.Beckmann@amd.com maxEntries[tid] = numEntries; 787917SBrad.Beckmann@amd.com } 797563SBrad.Beckmann@amd.com 807563SBrad.Beckmann@amd.com } else if (policy == "partitioned") { 817538SBrad.Beckmann@amd.com robPolicy = Partitioned; 827566SBrad.Beckmann@amd.com DPRINTF(Fetch, "ROB sharing policy set to Partitioned\n"); 837566SBrad.Beckmann@amd.com 847809Snilay@cs.wisc.edu //@todo:make work if part_amt doesnt divide evenly. 857809Snilay@cs.wisc.edu int part_amt = numEntries / numThreads; 867809Snilay@cs.wisc.edu 877809Snilay@cs.wisc.edu //Divide ROB up evenly 887538SBrad.Beckmann@amd.com for (ThreadID tid = 0; tid < numThreads; tid++) { 897538SBrad.Beckmann@amd.com maxEntries[tid] = part_amt; 907538SBrad.Beckmann@amd.com } 917538SBrad.Beckmann@amd.com 9210524Snilay@cs.wisc.edu } else if (policy == "threshold") { 9310524Snilay@cs.wisc.edu robPolicy = Threshold; 9410524Snilay@cs.wisc.edu DPRINTF(Fetch, "ROB sharing policy set to Threshold\n"); 9510524Snilay@cs.wisc.edu 9610524Snilay@cs.wisc.edu int threshold = params->smtROBThreshold;; 9710524Snilay@cs.wisc.edu 9810524Snilay@cs.wisc.edu //Divide up by threshold amount 9910524Snilay@cs.wisc.edu for (ThreadID tid = 0; tid < numThreads; tid++) { 10010524Snilay@cs.wisc.edu maxEntries[tid] = threshold; 10110524Snilay@cs.wisc.edu } 10210524Snilay@cs.wisc.edu } else { 10310524Snilay@cs.wisc.edu panic("Invalid ROB sharing policy. Options are: Dynamic, " 10410524Snilay@cs.wisc.edu "Partitioned, Threshold"); 10510524Snilay@cs.wisc.edu } 10610524Snilay@cs.wisc.edu 10710524Snilay@cs.wisc.edu resetState(); 10810524Snilay@cs.wisc.edu} 10910524Snilay@cs.wisc.edu 11010524Snilay@cs.wisc.edutemplate <class Impl> 11110524Snilay@cs.wisc.eduvoid 11210524Snilay@cs.wisc.eduROB<Impl>::resetState() 11310524Snilay@cs.wisc.edu{ 11410524Snilay@cs.wisc.edu for (ThreadID tid = 0; tid < numThreads; tid++) { 11510524Snilay@cs.wisc.edu doneSquashing[tid] = true; 11610524Snilay@cs.wisc.edu threadEntries[tid] = 0; 11710524Snilay@cs.wisc.edu squashIt[tid] = instList[tid].end(); 11810524Snilay@cs.wisc.edu squashedSeqNum[tid] = 0; 11910524Snilay@cs.wisc.edu } 12010524Snilay@cs.wisc.edu numInstsInROB = 0; 12110524Snilay@cs.wisc.edu 12210524Snilay@cs.wisc.edu // Initialize the "universal" ROB head & tail point to invalid 12310524Snilay@cs.wisc.edu // pointers 12410524Snilay@cs.wisc.edu head = instList[0].end(); 12510524Snilay@cs.wisc.edu tail = instList[0].end(); 12610524Snilay@cs.wisc.edu} 12710524Snilay@cs.wisc.edu 12810524Snilay@cs.wisc.edutemplate <class Impl> 12910524Snilay@cs.wisc.edustd::string 13010524Snilay@cs.wisc.eduROB<Impl>::name() const 13110524Snilay@cs.wisc.edu{ 13210524Snilay@cs.wisc.edu return cpu->name() + ".rob"; 13310524Snilay@cs.wisc.edu} 13410524Snilay@cs.wisc.edu 13510524Snilay@cs.wisc.edutemplate <class Impl> 13610524Snilay@cs.wisc.eduvoid 13710524Snilay@cs.wisc.eduROB<Impl>::setActiveThreads(list<ThreadID> *at_ptr) 13810524Snilay@cs.wisc.edu{ 13910524Snilay@cs.wisc.edu DPRINTF(ROB, "Setting active threads list pointer.\n"); 14010524Snilay@cs.wisc.edu activeThreads = at_ptr; 14110524Snilay@cs.wisc.edu} 14210524Snilay@cs.wisc.edu 1439100SBrad.Beckmann@amd.comtemplate <class Impl> 1449100SBrad.Beckmann@amd.comvoid 1459100SBrad.Beckmann@amd.comROB<Impl>::drainSanityCheck() const 1469100SBrad.Beckmann@amd.com{ 1479100SBrad.Beckmann@amd.com for (ThreadID tid = 0; tid < numThreads; tid++) 1489100SBrad.Beckmann@amd.com assert(instList[tid].empty()); 1499100SBrad.Beckmann@amd.com assert(isEmpty()); 1509100SBrad.Beckmann@amd.com} 1519100SBrad.Beckmann@amd.com 1529100SBrad.Beckmann@amd.comtemplate <class Impl> 15310519Snilay@cs.wisc.eduvoid 1546892SBrad.Beckmann@amd.comROB<Impl>::takeOverFrom() 15510524Snilay@cs.wisc.edu{ 1568436SBrad.Beckmann@amd.com resetState(); 1578436SBrad.Beckmann@amd.com} 1588257SBrad.Beckmann@amd.com 1598257SBrad.Beckmann@amd.comtemplate <class Impl> 16010122Snilay@cs.wisc.eduvoid 16110122Snilay@cs.wisc.eduROB<Impl>::resetEntries() 16210122Snilay@cs.wisc.edu{ 16310122Snilay@cs.wisc.edu if (robPolicy != Dynamic || numThreads > 1) { 16410122Snilay@cs.wisc.edu int active_threads = activeThreads->size(); 16510122Snilay@cs.wisc.edu 1668257SBrad.Beckmann@amd.com list<ThreadID>::iterator threads = activeThreads->begin(); 16710122Snilay@cs.wisc.edu list<ThreadID>::iterator end = activeThreads->end(); 16810122Snilay@cs.wisc.edu 16910122Snilay@cs.wisc.edu while (threads != end) { 17010122Snilay@cs.wisc.edu ThreadID tid = *threads++; 17110122Snilay@cs.wisc.edu 17210122Snilay@cs.wisc.edu if (robPolicy == Partitioned) { 1738257SBrad.Beckmann@amd.com maxEntries[tid] = numEntries / active_threads; 17410122Snilay@cs.wisc.edu } else if (robPolicy == Threshold && active_threads == 1) { 17510122Snilay@cs.wisc.edu maxEntries[tid] = numEntries; 17610122Snilay@cs.wisc.edu } 17710122Snilay@cs.wisc.edu } 17810122Snilay@cs.wisc.edu } 1799148Spowerjg@cs.wisc.edu} 18010311Snilay@cs.wisc.edu 18110311Snilay@cs.wisc.edutemplate <class Impl> 18210311Snilay@cs.wisc.eduint 18310311Snilay@cs.wisc.eduROB<Impl>::entryAmount(ThreadID num_threads) 18410311Snilay@cs.wisc.edu{ 18510551Ssteve.reinhardt@amd.com if (robPolicy == Partitioned) { 18610551Ssteve.reinhardt@amd.com return numEntries / num_threads; 18710311Snilay@cs.wisc.edu } else { 18810311Snilay@cs.wisc.edu return 0; 18910551Ssteve.reinhardt@amd.com } 19010551Ssteve.reinhardt@amd.com} 19110551Ssteve.reinhardt@amd.com 19210311Snilay@cs.wisc.edutemplate <class Impl> 19310551Ssteve.reinhardt@amd.comint 19410311Snilay@cs.wisc.eduROB<Impl>::countInsts() 19510311Snilay@cs.wisc.edu{ 19610311Snilay@cs.wisc.edu int total = 0; 19710311Snilay@cs.wisc.edu 19810311Snilay@cs.wisc.edu for (ThreadID tid = 0; tid < numThreads; tid++) 19910311Snilay@cs.wisc.edu total += countInsts(tid); 20010311Snilay@cs.wisc.edu 20110311Snilay@cs.wisc.edu return total; 20210311Snilay@cs.wisc.edu} 20310311Snilay@cs.wisc.edu 20410311Snilay@cs.wisc.edutemplate <class Impl> 20510311Snilay@cs.wisc.eduint 20610311Snilay@cs.wisc.eduROB<Impl>::countInsts(ThreadID tid) 2079148Spowerjg@cs.wisc.edu{ 2089862Snilay@cs.wisc.edu return instList[tid].size(); 2099862Snilay@cs.wisc.edu} 21010122Snilay@cs.wisc.edu 21110122Snilay@cs.wisc.edutemplate <class Impl> 21210122Snilay@cs.wisc.eduvoid 21310122Snilay@cs.wisc.eduROB<Impl>::insertInst(const DynInstPtr &inst) 21410122Snilay@cs.wisc.edu{ 2158257SBrad.Beckmann@amd.com assert(inst); 2168612Stushar@csail.mit.edu 2178612Stushar@csail.mit.edu robWrites++; 2189593Snilay@cs.wisc.edu 2199593Snilay@cs.wisc.edu DPRINTF(ROB, "Adding inst PC %s to the ROB.\n", inst->pcState()); 2206892SBrad.Beckmann@amd.com 22110524Snilay@cs.wisc.edu assert(numInstsInROB != numEntries); 22210116Snilay@cs.wisc.edu 22310116Snilay@cs.wisc.edu ThreadID tid = inst->threadNumber; 22410116Snilay@cs.wisc.edu 22510116Snilay@cs.wisc.edu instList[tid].push_back(inst); 22610116Snilay@cs.wisc.edu 22710116Snilay@cs.wisc.edu //Set Up head iterator if this is the 1st instruction in the ROB 22810116Snilay@cs.wisc.edu if (numInstsInROB == 0) { 22910116Snilay@cs.wisc.edu head = instList[tid].begin(); 23010116Snilay@cs.wisc.edu assert((*head) == inst); 23110116Snilay@cs.wisc.edu } 23210120Snilay@cs.wisc.edu 23310012Snilay@cs.wisc.edu //Must Decrement for iterator to actually be valid since __.end() 2347809Snilay@cs.wisc.edu //actually points to 1 after the last inst 23510525Snilay@cs.wisc.edu tail = instList[tid].end(); 23610630Snilay@cs.wisc.edu tail--; 23710630Snilay@cs.wisc.edu 23810706Spower.jg@gmail.com inst->setInROB(); 23910706Spower.jg@gmail.com 24010630Snilay@cs.wisc.edu ++numInstsInROB; 24110630Snilay@cs.wisc.edu ++threadEntries[tid]; 24210529Smorr@cs.wisc.edu 24310529Smorr@cs.wisc.edu assert((*tail) == inst); 24410529Smorr@cs.wisc.edu 24510529Smorr@cs.wisc.edu DPRINTF(ROB, "[tid:%i] Now has %d instructions.\n", tid, threadEntries[tid]); 24610529Smorr@cs.wisc.edu} 24710529Smorr@cs.wisc.edu 24810529Smorr@cs.wisc.edutemplate <class Impl> 249void 250ROB<Impl>::retireHead(ThreadID tid) 251{ 252 robWrites++; 253 254 assert(numInstsInROB > 0); 255 256 // Get the head ROB instruction by copying it and remove it from the list 257 InstIt head_it = instList[tid].begin(); 258 259 DynInstPtr head_inst = std::move(*head_it); 260 instList[tid].erase(head_it); 261 262 assert(head_inst->readyToCommit()); 263 264 DPRINTF(ROB, "[tid:%u]: Retiring head instruction, " 265 "instruction PC %s, [sn:%lli]\n", tid, head_inst->pcState(), 266 head_inst->seqNum); 267 268 --numInstsInROB; 269 --threadEntries[tid]; 270 271 head_inst->clearInROB(); 272 head_inst->setCommitted(); 273 274 //Update "Global" Head of ROB 275 updateHead(); 276 277 // @todo: A special case is needed if the instruction being 278 // retired is the only instruction in the ROB; otherwise the tail 279 // iterator will become invalidated. 280 cpu->removeFrontInst(head_inst); 281} 282 283template <class Impl> 284bool 285ROB<Impl>::isHeadReady(ThreadID tid) 286{ 287 robReads++; 288 if (threadEntries[tid] != 0) { 289 return instList[tid].front()->readyToCommit(); 290 } 291 292 return false; 293} 294 295template <class Impl> 296bool 297ROB<Impl>::canCommit() 298{ 299 //@todo: set ActiveThreads through ROB or CPU 300 list<ThreadID>::iterator threads = activeThreads->begin(); 301 list<ThreadID>::iterator end = activeThreads->end(); 302 303 while (threads != end) { 304 ThreadID tid = *threads++; 305 306 if (isHeadReady(tid)) { 307 return true; 308 } 309 } 310 311 return false; 312} 313 314template <class Impl> 315unsigned 316ROB<Impl>::numFreeEntries() 317{ 318 return numEntries - numInstsInROB; 319} 320 321template <class Impl> 322unsigned 323ROB<Impl>::numFreeEntries(ThreadID tid) 324{ 325 return maxEntries[tid] - threadEntries[tid]; 326} 327 328template <class Impl> 329void 330ROB<Impl>::doSquash(ThreadID tid) 331{ 332 robWrites++; 333 DPRINTF(ROB, "[tid:%u]: Squashing instructions until [sn:%i].\n", 334 tid, squashedSeqNum[tid]); 335 336 assert(squashIt[tid] != instList[tid].end()); 337 338 if ((*squashIt[tid])->seqNum < squashedSeqNum[tid]) { 339 DPRINTF(ROB, "[tid:%u]: Done squashing instructions.\n", 340 tid); 341 342 squashIt[tid] = instList[tid].end(); 343 344 doneSquashing[tid] = true; 345 return; 346 } 347 348 bool robTailUpdate = false; 349 350 for (int numSquashed = 0; 351 numSquashed < squashWidth && 352 squashIt[tid] != instList[tid].end() && 353 (*squashIt[tid])->seqNum > squashedSeqNum[tid]; 354 ++numSquashed) 355 { 356 DPRINTF(ROB, "[tid:%u]: Squashing instruction PC %s, seq num %i.\n", 357 (*squashIt[tid])->threadNumber, 358 (*squashIt[tid])->pcState(), 359 (*squashIt[tid])->seqNum); 360 361 // Mark the instruction as squashed, and ready to commit so that 362 // it can drain out of the pipeline. 363 (*squashIt[tid])->setSquashed(); 364 365 (*squashIt[tid])->setCanCommit(); 366 367 368 if (squashIt[tid] == instList[tid].begin()) { 369 DPRINTF(ROB, "Reached head of instruction list while " 370 "squashing.\n"); 371 372 squashIt[tid] = instList[tid].end(); 373 374 doneSquashing[tid] = true; 375 376 return; 377 } 378 379 InstIt tail_thread = instList[tid].end(); 380 tail_thread--; 381 382 if ((*squashIt[tid]) == (*tail_thread)) 383 robTailUpdate = true; 384 385 squashIt[tid]--; 386 } 387 388 389 // Check if ROB is done squashing. 390 if ((*squashIt[tid])->seqNum <= squashedSeqNum[tid]) { 391 DPRINTF(ROB, "[tid:%u]: Done squashing instructions.\n", 392 tid); 393 394 squashIt[tid] = instList[tid].end(); 395 396 doneSquashing[tid] = true; 397 } 398 399 if (robTailUpdate) { 400 updateTail(); 401 } 402} 403 404 405template <class Impl> 406void 407ROB<Impl>::updateHead() 408{ 409 InstSeqNum lowest_num = 0; 410 bool first_valid = true; 411 412 // @todo: set ActiveThreads through ROB or CPU 413 list<ThreadID>::iterator threads = activeThreads->begin(); 414 list<ThreadID>::iterator end = activeThreads->end(); 415 416 while (threads != end) { 417 ThreadID tid = *threads++; 418 419 if (instList[tid].empty()) 420 continue; 421 422 if (first_valid) { 423 head = instList[tid].begin(); 424 lowest_num = (*head)->seqNum; 425 first_valid = false; 426 continue; 427 } 428 429 InstIt head_thread = instList[tid].begin(); 430 431 DynInstPtr head_inst = (*head_thread); 432 433 assert(head_inst != 0); 434 435 if (head_inst->seqNum < lowest_num) { 436 head = head_thread; 437 lowest_num = head_inst->seqNum; 438 } 439 } 440 441 if (first_valid) { 442 head = instList[0].end(); 443 } 444 445} 446 447template <class Impl> 448void 449ROB<Impl>::updateTail() 450{ 451 tail = instList[0].end(); 452 bool first_valid = true; 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 if (instList[tid].empty()) { 461 continue; 462 } 463 464 // If this is the first valid then assign w/out 465 // comparison 466 if (first_valid) { 467 tail = instList[tid].end(); 468 tail--; 469 first_valid = false; 470 continue; 471 } 472 473 // Assign new tail if this thread's tail is younger 474 // than our current "tail high" 475 InstIt tail_thread = instList[tid].end(); 476 tail_thread--; 477 478 if ((*tail_thread)->seqNum > (*tail)->seqNum) { 479 tail = tail_thread; 480 } 481 } 482} 483 484 485template <class Impl> 486void 487ROB<Impl>::squash(InstSeqNum squash_num, ThreadID tid) 488{ 489 if (isEmpty(tid)) { 490 DPRINTF(ROB, "Does not need to squash due to being empty " 491 "[sn:%i]\n", 492 squash_num); 493 494 return; 495 } 496 497 DPRINTF(ROB, "Starting to squash within the ROB.\n"); 498 499 robStatus[tid] = ROBSquashing; 500 501 doneSquashing[tid] = false; 502 503 squashedSeqNum[tid] = squash_num; 504 505 if (!instList[tid].empty()) { 506 InstIt tail_thread = instList[tid].end(); 507 tail_thread--; 508 509 squashIt[tid] = tail_thread; 510 511 doSquash(tid); 512 } 513} 514 515template <class Impl> 516const typename Impl::DynInstPtr& 517ROB<Impl>::readHeadInst(ThreadID tid) 518{ 519 if (threadEntries[tid] != 0) { 520 InstIt head_thread = instList[tid].begin(); 521 522 assert((*head_thread)->isInROB()); 523 524 return *head_thread; 525 } else { 526 return dummyInst; 527 } 528} 529 530template <class Impl> 531typename Impl::DynInstPtr 532ROB<Impl>::readTailInst(ThreadID tid) 533{ 534 InstIt tail_thread = instList[tid].end(); 535 tail_thread--; 536 537 return *tail_thread; 538} 539 540template <class Impl> 541void 542ROB<Impl>::regStats() 543{ 544 using namespace Stats; 545 robReads 546 .name(name() + ".rob_reads") 547 .desc("The number of ROB reads"); 548 549 robWrites 550 .name(name() + ".rob_writes") 551 .desc("The number of ROB writes"); 552} 553 554template <class Impl> 555typename Impl::DynInstPtr 556ROB<Impl>::findInst(ThreadID tid, InstSeqNum squash_inst) 557{ 558 for (InstIt it = instList[tid].begin(); it != instList[tid].end(); it++) { 559 if ((*it)->seqNum == squash_inst) { 560 return *it; 561 } 562 } 563 return NULL; 564} 565 566#endif//__CPU_O3_ROB_IMPL_HH__ 567