rob_impl.hh revision 14016
12623SN/A/* 22623SN/A * Copyright (c) 2012 ARM Limited 32623SN/A * All rights reserved 42623SN/A * 52623SN/A * The license below extends only to copyright in the software and shall 62623SN/A * not be construed as granting a license to any other intellectual 72623SN/A * property including but not limited to intellectual property relating 82623SN/A * to a hardware implementation of the functionality of the software 92623SN/A * licensed hereunder. You may use the software subject to the license 102623SN/A * terms below provided that you ensure that this notice is replicated 112623SN/A * unmodified and in its entirety in all distributions of the software, 122623SN/A * modified or unmodified, in source code or in binary form. 132623SN/A * 142623SN/A * Copyright (c) 2004-2006 The Regents of The University of Michigan 152623SN/A * All rights reserved. 162623SN/A * 172623SN/A * Redistribution and use in source and binary forms, with or without 182623SN/A * modification, are permitted provided that the following conditions are 192623SN/A * met: redistributions of source code must retain the above copyright 202623SN/A * notice, this list of conditions and the following disclaimer; 212623SN/A * redistributions in binary form must reproduce the above copyright 222623SN/A * notice, this list of conditions and the following disclaimer in the 232623SN/A * documentation and/or other materials provided with the distribution; 242623SN/A * neither the name of the copyright holders nor the names of its 252623SN/A * contributors may be used to endorse or promote products derived from 262623SN/A * this software without specific prior written permission. 272665Ssaidi@eecs.umich.edu * 282665Ssaidi@eecs.umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 292623SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 302623SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 312623SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 322623SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 332623SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 342623SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 356973Stjones1@inf.ed.ac.uk * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 365529Snate@binkert.org * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 375529Snate@binkert.org * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 382623SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 392623SN/A * 402623SN/A * Authors: Kevin Lim 412623SN/A * Korey Sewell 425529Snate@binkert.org */ 432623SN/A 442623SN/A#ifndef __CPU_O3_ROB_IMPL_HH__ 452623SN/A#define __CPU_O3_ROB_IMPL_HH__ 462623SN/A 472623SN/A#include <list> 482839Sktlim@umich.edu 492798Sktlim@umich.edu#include "base/logging.hh" 502623SN/A#include "cpu/o3/rob.hh" 512623SN/A#include "debug/Fetch.hh" 525728Sgblack@eecs.umich.edu#include "debug/ROB.hh" 535728Sgblack@eecs.umich.edu#include "params/DerivO3CPU.hh" 545728Sgblack@eecs.umich.edu 555728Sgblack@eecs.umich.eduusing namespace std; 565728Sgblack@eecs.umich.edu 575728Sgblack@eecs.umich.edutemplate <class Impl> 585728Sgblack@eecs.umich.eduROB<Impl>::ROB(O3CPU *_cpu, DerivO3CPUParams *params) 595728Sgblack@eecs.umich.edu : robPolicy(params->smtROBPolicy), 605728Sgblack@eecs.umich.edu cpu(_cpu), 615728Sgblack@eecs.umich.edu numEntries(params->numROBEntries), 625728Sgblack@eecs.umich.edu squashWidth(params->squashWidth), 635728Sgblack@eecs.umich.edu numInstsInROB(0), 645728Sgblack@eecs.umich.edu numThreads(params->numThreads) 655728Sgblack@eecs.umich.edu{ 665728Sgblack@eecs.umich.edu //Figure out rob policy 675728Sgblack@eecs.umich.edu if (robPolicy == SMTQueuePolicy::Dynamic) { 685728Sgblack@eecs.umich.edu //Set Max Entries to Total ROB Capacity 695728Sgblack@eecs.umich.edu for (ThreadID tid = 0; tid < numThreads; tid++) { 705728Sgblack@eecs.umich.edu maxEntries[tid] = numEntries; 715728Sgblack@eecs.umich.edu } 725728Sgblack@eecs.umich.edu 735728Sgblack@eecs.umich.edu } else if (robPolicy == SMTQueuePolicy::Partitioned) { 745728Sgblack@eecs.umich.edu DPRINTF(Fetch, "ROB sharing policy set to Partitioned\n"); 755728Sgblack@eecs.umich.edu 765728Sgblack@eecs.umich.edu //@todo:make work if part_amt doesnt divide evenly. 775728Sgblack@eecs.umich.edu int part_amt = numEntries / numThreads; 785728Sgblack@eecs.umich.edu 795728Sgblack@eecs.umich.edu //Divide ROB up evenly 805728Sgblack@eecs.umich.edu for (ThreadID tid = 0; tid < numThreads; tid++) { 815728Sgblack@eecs.umich.edu maxEntries[tid] = part_amt; 825728Sgblack@eecs.umich.edu } 835728Sgblack@eecs.umich.edu 845728Sgblack@eecs.umich.edu } else if (robPolicy == SMTQueuePolicy::Threshold) { 855728Sgblack@eecs.umich.edu DPRINTF(Fetch, "ROB sharing policy set to Threshold\n"); 865728Sgblack@eecs.umich.edu 875728Sgblack@eecs.umich.edu int threshold = params->smtROBThreshold;; 885728Sgblack@eecs.umich.edu 895728Sgblack@eecs.umich.edu //Divide up by threshold amount 905728Sgblack@eecs.umich.edu for (ThreadID tid = 0; tid < numThreads; tid++) { 915728Sgblack@eecs.umich.edu maxEntries[tid] = threshold; 925728Sgblack@eecs.umich.edu } 935728Sgblack@eecs.umich.edu } 945728Sgblack@eecs.umich.edu 955728Sgblack@eecs.umich.edu for (ThreadID tid = numThreads; tid < Impl::MaxThreads; tid++) { 965728Sgblack@eecs.umich.edu maxEntries[tid] = 0; 975728Sgblack@eecs.umich.edu } 985728Sgblack@eecs.umich.edu 995894Sgblack@eecs.umich.edu resetState(); 1005894Sgblack@eecs.umich.edu} 1015894Sgblack@eecs.umich.edu 1025894Sgblack@eecs.umich.edutemplate <class Impl> 1035894Sgblack@eecs.umich.eduvoid 1045894Sgblack@eecs.umich.eduROB<Impl>::resetState() 1056023Snate@binkert.org{ 1066023Snate@binkert.org for (ThreadID tid = 0; tid < Impl::MaxThreads; tid++) { 1075894Sgblack@eecs.umich.edu threadEntries[tid] = 0; 1085894Sgblack@eecs.umich.edu squashIt[tid] = instList[tid].end(); 1096023Snate@binkert.org squashedSeqNum[tid] = 0; 1107944SGiacomo.Gabrielli@arm.com doneSquashing[tid] = true; 1117945SAli.Saidi@ARM.com } 1127945SAli.Saidi@ARM.com numInstsInROB = 0; 1137945SAli.Saidi@ARM.com 1147945SAli.Saidi@ARM.com // Initialize the "universal" ROB head & tail point to invalid 1157944SGiacomo.Gabrielli@arm.com // pointers 1167944SGiacomo.Gabrielli@arm.com head = instList[0].end(); 1176023Snate@binkert.org tail = instList[0].end(); 1186023Snate@binkert.org} 1195894Sgblack@eecs.umich.edu 1205894Sgblack@eecs.umich.edutemplate <class Impl> 1215894Sgblack@eecs.umich.edustd::string 1225894Sgblack@eecs.umich.eduROB<Impl>::name() const 1235894Sgblack@eecs.umich.edu{ 1245894Sgblack@eecs.umich.edu return cpu->name() + ".rob"; 1256973Stjones1@inf.ed.ac.uk} 1266973Stjones1@inf.ed.ac.uk 1276973Stjones1@inf.ed.ac.uktemplate <class Impl> 1285894Sgblack@eecs.umich.eduvoid 1295894Sgblack@eecs.umich.eduROB<Impl>::setActiveThreads(list<ThreadID> *at_ptr) 1305894Sgblack@eecs.umich.edu{ 1315894Sgblack@eecs.umich.edu DPRINTF(ROB, "Setting active threads list pointer.\n"); 1325894Sgblack@eecs.umich.edu activeThreads = at_ptr; 1335894Sgblack@eecs.umich.edu} 1345894Sgblack@eecs.umich.edu 1355744Sgblack@eecs.umich.edutemplate <class Impl> 1365728Sgblack@eecs.umich.eduvoid 1375728Sgblack@eecs.umich.eduROB<Impl>::drainSanityCheck() const 1385728Sgblack@eecs.umich.edu{ 1395728Sgblack@eecs.umich.edu for (ThreadID tid = 0; tid < numThreads; tid++) 1408707Sandreas.hansson@arm.com assert(instList[tid].empty()); 1418707Sandreas.hansson@arm.com assert(isEmpty()); 1428707Sandreas.hansson@arm.com} 1438707Sandreas.hansson@arm.com 1448707Sandreas.hansson@arm.comtemplate <class Impl> 1458707Sandreas.hansson@arm.comvoid 1468707Sandreas.hansson@arm.comROB<Impl>::takeOverFrom() 1472623SN/A{ 1482623SN/A resetState(); 1492623SN/A} 1508707Sandreas.hansson@arm.com 1518707Sandreas.hansson@arm.comtemplate <class Impl> 1522623SN/Avoid 1532623SN/AROB<Impl>::resetEntries() 1542623SN/A{ 1552623SN/A if (robPolicy != SMTQueuePolicy::Dynamic || numThreads > 1) { 1568948Sandreas.hansson@arm.com auto active_threads = activeThreads->size(); 1578948Sandreas.hansson@arm.com 1588948Sandreas.hansson@arm.com list<ThreadID>::iterator threads = activeThreads->begin(); 1598975Sandreas.hansson@arm.com list<ThreadID>::iterator end = activeThreads->end(); 1608948Sandreas.hansson@arm.com 1618707Sandreas.hansson@arm.com while (threads != end) { 1622948Ssaidi@eecs.umich.edu ThreadID tid = *threads++; 1632948Ssaidi@eecs.umich.edu 1642948Ssaidi@eecs.umich.edu if (robPolicy == SMTQueuePolicy::Partitioned) { 1653349Sbinkertn@umich.edu maxEntries[tid] = numEntries / active_threads; 1662948Ssaidi@eecs.umich.edu } else if (robPolicy == SMTQueuePolicy::Threshold && 1672948Ssaidi@eecs.umich.edu active_threads == 1) { 1688707Sandreas.hansson@arm.com maxEntries[tid] = numEntries; 1695336Shines@cs.fsu.edu } 1703349Sbinkertn@umich.edu } 1712948Ssaidi@eecs.umich.edu } 1722948Ssaidi@eecs.umich.edu} 1739087Sandreas.hansson@arm.com 1742623SN/Atemplate <class Impl> 1752623SN/Aint 1768707Sandreas.hansson@arm.comROB<Impl>::entryAmount(ThreadID num_threads) 1772623SN/A{ 1782623SN/A if (robPolicy == SMTQueuePolicy::Partitioned) { 1792623SN/A return numEntries / num_threads; 1808707Sandreas.hansson@arm.com } else { 1819095Sandreas.hansson@arm.com return 0; 1828707Sandreas.hansson@arm.com } 1832623SN/A} 1842623SN/A 1852623SN/Atemplate <class Impl> 1862623SN/Aint 1878975Sandreas.hansson@arm.comROB<Impl>::countInsts() 1882623SN/A{ 1892657Ssaidi@eecs.umich.edu int total = 0; 1902948Ssaidi@eecs.umich.edu 1912948Ssaidi@eecs.umich.edu for (ThreadID tid = 0; tid < numThreads; tid++) 1922948Ssaidi@eecs.umich.edu total += countInsts(tid); 1932948Ssaidi@eecs.umich.edu 1942948Ssaidi@eecs.umich.edu return total; 1952948Ssaidi@eecs.umich.edu} 1962948Ssaidi@eecs.umich.edu 1975336Shines@cs.fsu.edutemplate <class Impl> 1982948Ssaidi@eecs.umich.edusize_t 1992948Ssaidi@eecs.umich.eduROB<Impl>::countInsts(ThreadID tid) 2002948Ssaidi@eecs.umich.edu{ 2012948Ssaidi@eecs.umich.edu return instList[tid].size(); 2022623SN/A} 2032623SN/A 2048707Sandreas.hansson@arm.comtemplate <class Impl> 2052623SN/Avoid 2062623SN/AROB<Impl>::insertInst(const DynInstPtr &inst) 2072623SN/A{ 2088707Sandreas.hansson@arm.com assert(inst); 2099095Sandreas.hansson@arm.com 2109095Sandreas.hansson@arm.com robWrites++; 2112623SN/A 2122623SN/A DPRINTF(ROB, "Adding inst PC %s to the ROB.\n", inst->pcState()); 2132623SN/A 2142623SN/A assert(numInstsInROB != numEntries); 2158975Sandreas.hansson@arm.com 2162623SN/A ThreadID tid = inst->threadNumber; 2172657Ssaidi@eecs.umich.edu 2182948Ssaidi@eecs.umich.edu instList[tid].push_back(inst); 2192948Ssaidi@eecs.umich.edu 2202948Ssaidi@eecs.umich.edu //Set Up head iterator if this is the 1st instruction in the ROB 2212948Ssaidi@eecs.umich.edu if (numInstsInROB == 0) { 2222948Ssaidi@eecs.umich.edu head = instList[tid].begin(); 2232948Ssaidi@eecs.umich.edu assert((*head) == inst); 2245336Shines@cs.fsu.edu } 2252948Ssaidi@eecs.umich.edu 2262948Ssaidi@eecs.umich.edu //Must Decrement for iterator to actually be valid since __.end() 2272948Ssaidi@eecs.umich.edu //actually points to 1 after the last inst 2282948Ssaidi@eecs.umich.edu tail = instList[tid].end(); 2292623SN/A tail--; 2302623SN/A 2312623SN/A inst->setInROB(); 2322623SN/A 2332623SN/A ++numInstsInROB; 2343349Sbinkertn@umich.edu ++threadEntries[tid]; 2353349Sbinkertn@umich.edu 2362623SN/A assert((*tail) == inst); 2373222Sktlim@umich.edu 2383170Sstever@eecs.umich.edu DPRINTF(ROB, "[tid:%i] Now has %d instructions.\n", tid, threadEntries[tid]); 2398850Sandreas.hansson@arm.com} 2408850Sandreas.hansson@arm.com 2418850Sandreas.hansson@arm.comtemplate <class Impl> 2428850Sandreas.hansson@arm.comvoid 2438850Sandreas.hansson@arm.comROB<Impl>::retireHead(ThreadID tid) 2448850Sandreas.hansson@arm.com{ 2458850Sandreas.hansson@arm.com robWrites++; 2468850Sandreas.hansson@arm.com 2472623SN/A assert(numInstsInROB > 0); 2482623SN/A 2492623SN/A // Get the head ROB instruction by copying it and remove it from the list 2502623SN/A InstIt head_it = instList[tid].begin(); 2512623SN/A 2522901Ssaidi@eecs.umich.edu DynInstPtr head_inst = std::move(*head_it); 2532798Sktlim@umich.edu instList[tid].erase(head_it); 2542798Sktlim@umich.edu 2552798Sktlim@umich.edu assert(head_inst->readyToCommit()); 2562623SN/A 2572623SN/A DPRINTF(ROB, "[tid:%i] Retiring head instruction, " 2588737Skoansin.tan@gmail.com "instruction PC %s, [sn:%llu]\n", tid, head_inst->pcState(), 2598737Skoansin.tan@gmail.com head_inst->seqNum); 2602623SN/A 2618444Sgblack@eecs.umich.edu --numInstsInROB; 2627520Sgblack@eecs.umich.edu --threadEntries[tid]; 2638444Sgblack@eecs.umich.edu 2648444Sgblack@eecs.umich.edu head_inst->clearInROB(); 2657520Sgblack@eecs.umich.edu head_inst->setCommitted(); 2662623SN/A 2675894Sgblack@eecs.umich.edu //Update "Global" Head of ROB 2683349Sbinkertn@umich.edu updateHead(); 2695894Sgblack@eecs.umich.edu 2702644Sstever@eecs.umich.edu // @todo: A special case is needed if the instruction being 2714471Sstever@eecs.umich.edu // retired is the only instruction in the ROB; otherwise the tail 2725315Sstever@gmail.com // iterator will become invalidated. 2735315Sstever@gmail.com cpu->removeFrontInst(head_inst); 2745315Sstever@gmail.com} 2755315Sstever@gmail.com 2765315Sstever@gmail.comtemplate <class Impl> 2775315Sstever@gmail.combool 2786973Stjones1@inf.ed.ac.ukROB<Impl>::isHeadReady(ThreadID tid) 2796973Stjones1@inf.ed.ac.uk{ 2806973Stjones1@inf.ed.ac.uk robReads++; 2816973Stjones1@inf.ed.ac.uk if (threadEntries[tid] != 0) { 2826973Stjones1@inf.ed.ac.uk return instList[tid].front()->readyToCommit(); 2836973Stjones1@inf.ed.ac.uk } 2842798Sktlim@umich.edu 2854471Sstever@eecs.umich.edu return false; 2864471Sstever@eecs.umich.edu} 2875710Scws3k@cs.virginia.edu 2884471Sstever@eecs.umich.edutemplate <class Impl> 2895103Ssaidi@eecs.umich.edubool 2905103Ssaidi@eecs.umich.eduROB<Impl>::canCommit() 2915103Ssaidi@eecs.umich.edu{ 2925103Ssaidi@eecs.umich.edu //@todo: set ActiveThreads through ROB or CPU 2935103Ssaidi@eecs.umich.edu list<ThreadID>::iterator threads = activeThreads->begin(); 2945336Shines@cs.fsu.edu list<ThreadID>::iterator end = activeThreads->end(); 2955103Ssaidi@eecs.umich.edu 2965103Ssaidi@eecs.umich.edu while (threads != end) { 2972839Sktlim@umich.edu ThreadID tid = *threads++; 2982623SN/A 2992623SN/A if (isHeadReady(tid)) { 3002623SN/A return true; 301 } 302 } 303 304 return false; 305} 306 307template <class Impl> 308unsigned 309ROB<Impl>::numFreeEntries() 310{ 311 return numEntries - numInstsInROB; 312} 313 314template <class Impl> 315unsigned 316ROB<Impl>::numFreeEntries(ThreadID tid) 317{ 318 return maxEntries[tid] - threadEntries[tid]; 319} 320 321template <class Impl> 322void 323ROB<Impl>::doSquash(ThreadID tid) 324{ 325 robWrites++; 326 DPRINTF(ROB, "[tid:%i] Squashing instructions until [sn:%llu].\n", 327 tid, squashedSeqNum[tid]); 328 329 assert(squashIt[tid] != instList[tid].end()); 330 331 if ((*squashIt[tid])->seqNum < squashedSeqNum[tid]) { 332 DPRINTF(ROB, "[tid:%i] Done squashing instructions.\n", 333 tid); 334 335 squashIt[tid] = instList[tid].end(); 336 337 doneSquashing[tid] = true; 338 return; 339 } 340 341 bool robTailUpdate = false; 342 343 for (int numSquashed = 0; 344 numSquashed < squashWidth && 345 squashIt[tid] != instList[tid].end() && 346 (*squashIt[tid])->seqNum > squashedSeqNum[tid]; 347 ++numSquashed) 348 { 349 DPRINTF(ROB, "[tid:%i] Squashing instruction PC %s, seq num %i.\n", 350 (*squashIt[tid])->threadNumber, 351 (*squashIt[tid])->pcState(), 352 (*squashIt[tid])->seqNum); 353 354 // Mark the instruction as squashed, and ready to commit so that 355 // it can drain out of the pipeline. 356 (*squashIt[tid])->setSquashed(); 357 358 (*squashIt[tid])->setCanCommit(); 359 360 361 if (squashIt[tid] == instList[tid].begin()) { 362 DPRINTF(ROB, "Reached head of instruction list while " 363 "squashing.\n"); 364 365 squashIt[tid] = instList[tid].end(); 366 367 doneSquashing[tid] = true; 368 369 return; 370 } 371 372 InstIt tail_thread = instList[tid].end(); 373 tail_thread--; 374 375 if ((*squashIt[tid]) == (*tail_thread)) 376 robTailUpdate = true; 377 378 squashIt[tid]--; 379 } 380 381 382 // Check if ROB is done squashing. 383 if ((*squashIt[tid])->seqNum <= squashedSeqNum[tid]) { 384 DPRINTF(ROB, "[tid:%i] Done squashing instructions.\n", 385 tid); 386 387 squashIt[tid] = instList[tid].end(); 388 389 doneSquashing[tid] = true; 390 } 391 392 if (robTailUpdate) { 393 updateTail(); 394 } 395} 396 397 398template <class Impl> 399void 400ROB<Impl>::updateHead() 401{ 402 InstSeqNum lowest_num = 0; 403 bool first_valid = true; 404 405 // @todo: set ActiveThreads through ROB or CPU 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 if (instList[tid].empty()) 413 continue; 414 415 if (first_valid) { 416 head = instList[tid].begin(); 417 lowest_num = (*head)->seqNum; 418 first_valid = false; 419 continue; 420 } 421 422 InstIt head_thread = instList[tid].begin(); 423 424 DynInstPtr head_inst = (*head_thread); 425 426 assert(head_inst != 0); 427 428 if (head_inst->seqNum < lowest_num) { 429 head = head_thread; 430 lowest_num = head_inst->seqNum; 431 } 432 } 433 434 if (first_valid) { 435 head = instList[0].end(); 436 } 437 438} 439 440template <class Impl> 441void 442ROB<Impl>::updateTail() 443{ 444 tail = instList[0].end(); 445 bool first_valid = true; 446 447 list<ThreadID>::iterator threads = activeThreads->begin(); 448 list<ThreadID>::iterator end = activeThreads->end(); 449 450 while (threads != end) { 451 ThreadID tid = *threads++; 452 453 if (instList[tid].empty()) { 454 continue; 455 } 456 457 // If this is the first valid then assign w/out 458 // comparison 459 if (first_valid) { 460 tail = instList[tid].end(); 461 tail--; 462 first_valid = false; 463 continue; 464 } 465 466 // Assign new tail if this thread's tail is younger 467 // than our current "tail high" 468 InstIt tail_thread = instList[tid].end(); 469 tail_thread--; 470 471 if ((*tail_thread)->seqNum > (*tail)->seqNum) { 472 tail = tail_thread; 473 } 474 } 475} 476 477 478template <class Impl> 479void 480ROB<Impl>::squash(InstSeqNum squash_num, ThreadID tid) 481{ 482 if (isEmpty(tid)) { 483 DPRINTF(ROB, "Does not need to squash due to being empty " 484 "[sn:%llu]\n", 485 squash_num); 486 487 return; 488 } 489 490 DPRINTF(ROB, "Starting to squash within the ROB.\n"); 491 492 robStatus[tid] = ROBSquashing; 493 494 doneSquashing[tid] = false; 495 496 squashedSeqNum[tid] = squash_num; 497 498 if (!instList[tid].empty()) { 499 InstIt tail_thread = instList[tid].end(); 500 tail_thread--; 501 502 squashIt[tid] = tail_thread; 503 504 doSquash(tid); 505 } 506} 507 508template <class Impl> 509const typename Impl::DynInstPtr& 510ROB<Impl>::readHeadInst(ThreadID tid) 511{ 512 if (threadEntries[tid] != 0) { 513 InstIt head_thread = instList[tid].begin(); 514 515 assert((*head_thread)->isInROB()); 516 517 return *head_thread; 518 } else { 519 return dummyInst; 520 } 521} 522 523template <class Impl> 524typename Impl::DynInstPtr 525ROB<Impl>::readTailInst(ThreadID tid) 526{ 527 InstIt tail_thread = instList[tid].end(); 528 tail_thread--; 529 530 return *tail_thread; 531} 532 533template <class Impl> 534void 535ROB<Impl>::regStats() 536{ 537 using namespace Stats; 538 robReads 539 .name(name() + ".rob_reads") 540 .desc("The number of ROB reads"); 541 542 robWrites 543 .name(name() + ".rob_writes") 544 .desc("The number of ROB writes"); 545} 546 547template <class Impl> 548typename Impl::DynInstPtr 549ROB<Impl>::findInst(ThreadID tid, InstSeqNum squash_inst) 550{ 551 for (InstIt it = instList[tid].begin(); it != instList[tid].end(); it++) { 552 if ((*it)->seqNum == squash_inst) { 553 return *it; 554 } 555 } 556 return NULL; 557} 558 559#endif//__CPU_O3_ROB_IMPL_HH__ 560