rob_impl.hh revision 2292
12623SN/A/* 22623SN/A * Copyright (c) 2004-2005 The Regents of The University of Michigan 32623SN/A * All rights reserved. 42623SN/A * 52623SN/A * Redistribution and use in source and binary forms, with or without 62623SN/A * modification, are permitted provided that the following conditions are 72623SN/A * met: redistributions of source code must retain the above copyright 82623SN/A * notice, this list of conditions and the following disclaimer; 92623SN/A * redistributions in binary form must reproduce the above copyright 102623SN/A * notice, this list of conditions and the following disclaimer in the 112623SN/A * documentation and/or other materials provided with the distribution; 122623SN/A * neither the name of the copyright holders nor the names of its 132623SN/A * contributors may be used to endorse or promote products derived from 142623SN/A * this software without specific prior written permission. 152623SN/A * 162623SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 172623SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 182623SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 192623SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 202623SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 212623SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 222623SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 232623SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 242623SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 252623SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 262623SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 272665Ssaidi@eecs.umich.edu */ 282665Ssaidi@eecs.umich.edu 292623SN/A#include "config/full_system.hh" 302623SN/A#include "cpu/o3/rob.hh" 312623SN/A 322623SN/Ausing namespace std; 332623SN/A 342623SN/Atemplate <class Impl> 356973Stjones1@inf.ed.ac.ukROB<Impl>::ROB(unsigned _numEntries, unsigned _squashWidth, 365529Snate@binkert.org string _smtROBPolicy, unsigned _smtROBThreshold, 375529Snate@binkert.org unsigned _numThreads) 382623SN/A : numEntries(_numEntries), 392623SN/A squashWidth(_squashWidth), 402623SN/A numInstsInROB(0), 412623SN/A squashedSeqNum(0), 425529Snate@binkert.org numThreads(_numThreads) 432623SN/A{ 442623SN/A for (int tid=0; tid < numThreads; tid++) { 452623SN/A doneSquashing[tid] = true; 462623SN/A threadEntries[tid] = 0; 472623SN/A } 482839Sktlim@umich.edu 492798Sktlim@umich.edu string policy = _smtROBPolicy; 502623SN/A 512623SN/A //Convert string to lowercase 525728Sgblack@eecs.umich.edu std::transform(policy.begin(), policy.end(), policy.begin(), 535728Sgblack@eecs.umich.edu (int(*)(int)) tolower); 545728Sgblack@eecs.umich.edu 555728Sgblack@eecs.umich.edu //Figure out rob policy 565728Sgblack@eecs.umich.edu if (policy == "dynamic") { 575728Sgblack@eecs.umich.edu robPolicy = Dynamic; 585728Sgblack@eecs.umich.edu 595728Sgblack@eecs.umich.edu //Set Max Entries to Total ROB Capacity 605728Sgblack@eecs.umich.edu for (int i = 0; i < numThreads; i++) { 615728Sgblack@eecs.umich.edu maxEntries[i]=numEntries; 625728Sgblack@eecs.umich.edu } 635728Sgblack@eecs.umich.edu 645728Sgblack@eecs.umich.edu } else if (policy == "partitioned") { 655728Sgblack@eecs.umich.edu robPolicy = Partitioned; 665728Sgblack@eecs.umich.edu DPRINTF(Fetch, "ROB sharing policy set to Partitioned\n"); 675728Sgblack@eecs.umich.edu 685728Sgblack@eecs.umich.edu //@todo:make work if part_amt doesnt divide evenly. 695728Sgblack@eecs.umich.edu int part_amt = numEntries / numThreads; 705728Sgblack@eecs.umich.edu 715728Sgblack@eecs.umich.edu //Divide ROB up evenly 725728Sgblack@eecs.umich.edu for (int i = 0; i < numThreads; i++) { 735728Sgblack@eecs.umich.edu maxEntries[i]=part_amt; 745728Sgblack@eecs.umich.edu } 755728Sgblack@eecs.umich.edu 765728Sgblack@eecs.umich.edu } else if (policy == "threshold") { 775728Sgblack@eecs.umich.edu robPolicy = Threshold; 785728Sgblack@eecs.umich.edu DPRINTF(Fetch, "ROB sharing policy set to Threshold\n"); 795728Sgblack@eecs.umich.edu 805728Sgblack@eecs.umich.edu int threshold = _smtROBThreshold;; 815728Sgblack@eecs.umich.edu 825728Sgblack@eecs.umich.edu //Divide up by threshold amount 835728Sgblack@eecs.umich.edu for (int i = 0; i < numThreads; i++) { 845728Sgblack@eecs.umich.edu maxEntries[i]=threshold; 855728Sgblack@eecs.umich.edu } 865728Sgblack@eecs.umich.edu } else { 875728Sgblack@eecs.umich.edu assert(0 && "Invalid ROB Sharing Policy.Options Are:{Dynamic," 885728Sgblack@eecs.umich.edu "Partitioned, Threshold}"); 895728Sgblack@eecs.umich.edu } 905728Sgblack@eecs.umich.edu} 915728Sgblack@eecs.umich.edu 925728Sgblack@eecs.umich.edutemplate <class Impl> 935728Sgblack@eecs.umich.edustd::string 945728Sgblack@eecs.umich.eduROB<Impl>::name() const 955728Sgblack@eecs.umich.edu{ 965728Sgblack@eecs.umich.edu return cpu->name() + ".rob"; 975728Sgblack@eecs.umich.edu} 985728Sgblack@eecs.umich.edu 995894Sgblack@eecs.umich.edutemplate <class Impl> 1005894Sgblack@eecs.umich.eduvoid 1015894Sgblack@eecs.umich.eduROB<Impl>::setCPU(FullCPU *cpu_ptr) 1025894Sgblack@eecs.umich.edu{ 1035894Sgblack@eecs.umich.edu cpu = cpu_ptr; 1045894Sgblack@eecs.umich.edu 1056023Snate@binkert.org // Set the per-thread iterators to the end of the instruction list. 1066023Snate@binkert.org for (int i=0; i < numThreads;i++) { 1075894Sgblack@eecs.umich.edu squashIt[i] = instList[i].end(); 1085894Sgblack@eecs.umich.edu } 1096023Snate@binkert.org 1107944SGiacomo.Gabrielli@arm.com // Initialize the "universal" ROB head & tail point to invalid 1117945SAli.Saidi@ARM.com // pointers 1127945SAli.Saidi@ARM.com head = instList[0].end(); 1137945SAli.Saidi@ARM.com tail = instList[0].end(); 1147945SAli.Saidi@ARM.com} 1157944SGiacomo.Gabrielli@arm.com 1167944SGiacomo.Gabrielli@arm.comtemplate <class Impl> 1176023Snate@binkert.orgvoid 1186023Snate@binkert.orgROB<Impl>::setActiveThreads(list<unsigned> *at_ptr) 1195894Sgblack@eecs.umich.edu{ 1205894Sgblack@eecs.umich.edu DPRINTF(ROB, "Setting active threads list pointer.\n"); 1215894Sgblack@eecs.umich.edu activeThreads = at_ptr; 1225894Sgblack@eecs.umich.edu} 1235894Sgblack@eecs.umich.edu 1245894Sgblack@eecs.umich.edu 1256973Stjones1@inf.ed.ac.uktemplate <class Impl> 1266973Stjones1@inf.ed.ac.ukvoid 1276973Stjones1@inf.ed.ac.ukROB<Impl>::resetEntries() 1285894Sgblack@eecs.umich.edu{ 1295894Sgblack@eecs.umich.edu if (robPolicy != Dynamic || numThreads > 1) { 1305894Sgblack@eecs.umich.edu int active_threads = (*activeThreads).size(); 1315894Sgblack@eecs.umich.edu 1325894Sgblack@eecs.umich.edu list<unsigned>::iterator threads = (*activeThreads).begin(); 1335894Sgblack@eecs.umich.edu list<unsigned>::iterator list_end = (*activeThreads).end(); 1345894Sgblack@eecs.umich.edu 1355744Sgblack@eecs.umich.edu while (threads != list_end) { 1365728Sgblack@eecs.umich.edu if (robPolicy == Partitioned) { 1375728Sgblack@eecs.umich.edu maxEntries[*threads++] = numEntries / active_threads; 1385728Sgblack@eecs.umich.edu } else if (robPolicy == Threshold && active_threads == 1) { 1395728Sgblack@eecs.umich.edu maxEntries[*threads++] = numEntries; 1402623SN/A } 1412623SN/A } 1422623SN/A } 1432623SN/A} 1442948Ssaidi@eecs.umich.edu 1452623SN/Atemplate <class Impl> 1462623SN/Aint 1472623SN/AROB<Impl>::entryAmount(int num_threads) 1482948Ssaidi@eecs.umich.edu{ 1497745SAli.Saidi@ARM.com if (robPolicy == Partitioned) { 1502623SN/A return numEntries / num_threads; 1512623SN/A } else { 1523647Srdreslin@umich.edu return 0; 1533647Srdreslin@umich.edu } 1542623SN/A} 1552623SN/A 1563349Sbinkertn@umich.edutemplate <class Impl> 1572623SN/Aint 1583349Sbinkertn@umich.eduROB<Impl>::countInsts() 1592623SN/A{ 1602623SN/A int total=0; 1612623SN/A 1622623SN/A for (int i=0;i < numThreads;i++) 1634475Sstever@eecs.umich.edu total += countInsts(i); 1644475Sstever@eecs.umich.edu 1652948Ssaidi@eecs.umich.edu return total; 1662948Ssaidi@eecs.umich.edu} 1672948Ssaidi@eecs.umich.edu 1683349Sbinkertn@umich.edutemplate <class Impl> 1692948Ssaidi@eecs.umich.eduint 1707745SAli.Saidi@ARM.comROB<Impl>::countInsts(unsigned tid) 1712948Ssaidi@eecs.umich.edu{ 1725606Snate@binkert.org return instList[tid].size(); 1735336Shines@cs.fsu.edu} 1743349Sbinkertn@umich.edu 1752948Ssaidi@eecs.umich.edutemplate <class Impl> 1762948Ssaidi@eecs.umich.eduvoid 1777745SAli.Saidi@ARM.comROB<Impl>::insertInst(DynInstPtr &inst) 1782623SN/A{ 1792623SN/A // Make sure we have the right number of instructions. 1802623SN/A //assert(numInstsInROB == countInsts()); 1812623SN/A 1822623SN/A // Make sure the instruction is valid. 1832623SN/A assert(inst); 1842948Ssaidi@eecs.umich.edu 1852948Ssaidi@eecs.umich.edu DPRINTF(ROB, "Adding inst PC %#x to the ROB.\n", inst->readPC()); 1862623SN/A 1872623SN/A // If the ROB is full then exit. 1882623SN/A assert(numInstsInROB != numEntries); 1892623SN/A 1903349Sbinkertn@umich.edu int tid = inst->threadNumber; 1912623SN/A 1922657Ssaidi@eecs.umich.edu // Place into ROB 1932948Ssaidi@eecs.umich.edu instList[tid].push_back(inst); 1942948Ssaidi@eecs.umich.edu 1952948Ssaidi@eecs.umich.edu //Set Up head iterator if this is the 1st instruction in the ROB 1962948Ssaidi@eecs.umich.edu if (numInstsInROB == 0) { 1972948Ssaidi@eecs.umich.edu head = instList[tid].begin(); 1982948Ssaidi@eecs.umich.edu assert((*head) == inst); 1992948Ssaidi@eecs.umich.edu } 2005336Shines@cs.fsu.edu 2012948Ssaidi@eecs.umich.edu //Must Decrement for iterator to actually be valid since __.end() 2022948Ssaidi@eecs.umich.edu //actually points to 1 after the last inst 2032948Ssaidi@eecs.umich.edu tail = instList[tid].end(); 2042948Ssaidi@eecs.umich.edu tail--; 2052623SN/A 2062623SN/A // Mark as set in ROB 2072623SN/A inst->setInROB(); 2082623SN/A 2092623SN/A // Increment ROB count 2102623SN/A ++numInstsInROB; 2112948Ssaidi@eecs.umich.edu ++threadEntries[tid]; 2122948Ssaidi@eecs.umich.edu 2132623SN/A assert((*tail) == inst); 2142623SN/A 2154192Sktlim@umich.edu DPRINTF(ROB, "[tid:%i] Now has %d instructions.\n", tid, threadEntries[tid]); 2164192Sktlim@umich.edu} 2172623SN/A 2182623SN/A// Whatever calls this function needs to ensure that it properly frees up 2193349Sbinkertn@umich.edu// registers prior to this function. 2202623SN/Atemplate <class Impl> 2212657Ssaidi@eecs.umich.eduvoid 2222948Ssaidi@eecs.umich.eduROB<Impl>::retireHead() 2232948Ssaidi@eecs.umich.edu{ 2242948Ssaidi@eecs.umich.edu //assert(numInstsInROB == countInsts()); 2252948Ssaidi@eecs.umich.edu assert(numInstsInROB > 0); 2262948Ssaidi@eecs.umich.edu 2272948Ssaidi@eecs.umich.edu // Get the head ROB instruction's TID. 2285336Shines@cs.fsu.edu int tid = (*head)->threadNumber; 2292948Ssaidi@eecs.umich.edu 2302948Ssaidi@eecs.umich.edu retireHead(tid); 2312948Ssaidi@eecs.umich.edu 2322948Ssaidi@eecs.umich.edu if (numInstsInROB == 0) { 2332623SN/A tail = instList[tid].end(); 2342623SN/A } 2352623SN/A} 2362623SN/A 2372623SN/Atemplate <class Impl> 2383349Sbinkertn@umich.eduvoid 2393349Sbinkertn@umich.eduROB<Impl>::retireHead(unsigned tid) 2402623SN/A{ 2413222Sktlim@umich.edu //assert(numInstsInROB == countInsts()); 2423170Sstever@eecs.umich.edu assert(numInstsInROB > 0); 2432623SN/A 2442623SN/A // Get the head ROB instruction. 2452856Srdreslin@umich.edu InstIt head_it = instList[tid].begin(); 2462856Srdreslin@umich.edu 2472623SN/A DynInstPtr head_inst = (*head_it); 2482623SN/A 2492623SN/A // Make certain this can retire. 2502901Ssaidi@eecs.umich.edu assert(head_inst->readyToCommit()); 2512798Sktlim@umich.edu 2522798Sktlim@umich.edu DPRINTF(ROB, "[tid:%u]: Retiring head instruction, " 2532798Sktlim@umich.edu "instruction PC %#x,[sn:%lli]\n", tid, head_inst->readPC(), 2542623SN/A head_inst->seqNum); 2552623SN/A 2562623SN/A // Keep track of how many instructions are in the ROB. 2572623SN/A --numInstsInROB; 2582623SN/A --threadEntries[tid]; 2598444Sgblack@eecs.umich.edu 2607520Sgblack@eecs.umich.edu //Mark DynInstFlags 2618444Sgblack@eecs.umich.edu head_inst->removeInROB(); 2628444Sgblack@eecs.umich.edu head_inst->setCommitted(); 2637520Sgblack@eecs.umich.edu 2642623SN/A instList[tid].erase(head_it); 2655894Sgblack@eecs.umich.edu 2663349Sbinkertn@umich.edu //Update "Global" Head of ROB 2675894Sgblack@eecs.umich.edu updateHead(); 2682644Sstever@eecs.umich.edu 2694471Sstever@eecs.umich.edu // A special case is needed if the instruction being retired is the 2705315Sstever@gmail.com // only instruction in the ROB; otherwise the tail iterator will become 2715315Sstever@gmail.com // invalidated. 2725315Sstever@gmail.com cpu->removeFrontInst(head_inst); 2735315Sstever@gmail.com} 2745315Sstever@gmail.com 2755315Sstever@gmail.comtemplate <class Impl> 2766973Stjones1@inf.ed.ac.ukbool 2776973Stjones1@inf.ed.ac.ukROB<Impl>::isHeadReady() 2786973Stjones1@inf.ed.ac.uk{ 2796973Stjones1@inf.ed.ac.uk if (numInstsInROB != 0) { 2806973Stjones1@inf.ed.ac.uk return (*head)->readyToCommit(); 2816973Stjones1@inf.ed.ac.uk } 2822798Sktlim@umich.edu 2834471Sstever@eecs.umich.edu return false; 2844471Sstever@eecs.umich.edu} 2855710Scws3k@cs.virginia.edu 2864471Sstever@eecs.umich.edutemplate <class Impl> 2875103Ssaidi@eecs.umich.edubool 2885103Ssaidi@eecs.umich.eduROB<Impl>::isHeadReady(unsigned tid) 2895103Ssaidi@eecs.umich.edu{ 2905103Ssaidi@eecs.umich.edu if (threadEntries[tid] != 0) { 2915103Ssaidi@eecs.umich.edu return instList[tid].front()->readyToCommit(); 2925336Shines@cs.fsu.edu } 2935103Ssaidi@eecs.umich.edu 2945103Ssaidi@eecs.umich.edu return false; 2952839Sktlim@umich.edu} 2962623SN/A 2972623SN/Atemplate <class Impl> 2982623SN/Abool 299ROB<Impl>::canCommit() 300{ 301 //@todo: set ActiveThreads through ROB or CPU 302 list<unsigned>::iterator threads = (*activeThreads).begin(); 303 304 while (threads != (*activeThreads).end()) { 305 unsigned tid = *threads++; 306 307 if (isHeadReady(tid)) { 308 return true; 309 } 310 } 311 312 return false; 313} 314 315template <class Impl> 316unsigned 317ROB<Impl>::numFreeEntries() 318{ 319 //assert(numInstsInROB == countInsts()); 320 321 return numEntries - numInstsInROB; 322} 323 324template <class Impl> 325unsigned 326ROB<Impl>::numFreeEntries(unsigned tid) 327{ 328 return maxEntries[tid] - threadEntries[tid]; 329} 330 331template <class Impl> 332void 333ROB<Impl>::doSquash(unsigned tid) 334{ 335 DPRINTF(ROB, "[tid:%u]: Squashing instructions until [sn:%i].\n", 336 tid, squashedSeqNum); 337 338 assert(squashIt[tid] != instList[tid].end()); 339 340 if ((*squashIt[tid])->seqNum < squashedSeqNum) { 341 DPRINTF(ROB, "[tid:%u]: Done squashing instructions.\n", 342 tid); 343 344 squashIt[tid] = instList[tid].end(); 345 346 doneSquashing[tid] = true; 347 return; 348 } 349 350 bool robTailUpdate = false; 351 352 for (int numSquashed = 0; 353 numSquashed < squashWidth && 354 squashIt[tid] != instList[tid].end() && 355 (*squashIt[tid])->seqNum > squashedSeqNum; 356 ++numSquashed) 357 { 358 DPRINTF(ROB, "[tid:%u]: Squashing instruction PC %#x, seq num %i.\n", 359 (*squashIt[tid])->threadNumber, 360 (*squashIt[tid])->readPC(), 361 (*squashIt[tid])->seqNum); 362 363 // Mark the instruction as squashed, and ready to commit so that 364 // it can drain out of the pipeline. 365 (*squashIt[tid])->setSquashed(); 366 367 (*squashIt[tid])->setCanCommit(); 368 369 370 if (squashIt[tid] == instList[tid].begin()) { 371 DPRINTF(ROB, "Reached head of instruction list while " 372 "squashing.\n"); 373 374 squashIt[tid] = instList[tid].end(); 375 376 doneSquashing[tid] = true; 377 378 return; 379 } 380 381 InstIt tail_thread = instList[tid].end(); 382 tail_thread--; 383 384 if ((*squashIt[tid]) == (*tail_thread)) 385 robTailUpdate = true; 386 387 squashIt[tid]--; 388 } 389 390 391 // Check if ROB is done squashing. 392 if ((*squashIt[tid])->seqNum <= squashedSeqNum) { 393 DPRINTF(ROB, "[tid:%u]: Done squashing instructions.\n", 394 tid); 395 396 squashIt[tid] = instList[tid].end(); 397 398 doneSquashing[tid] = true; 399 } 400 401 if (robTailUpdate) { 402 updateTail(); 403 } 404} 405 406 407template <class Impl> 408void 409ROB<Impl>::updateHead() 410{ 411 DynInstPtr head_inst; 412 InstSeqNum lowest_num = 0; 413 bool first_valid = true; 414 415 // @todo: set ActiveThreads through ROB or CPU 416 list<unsigned>::iterator threads = (*activeThreads).begin(); 417 418 while (threads != (*activeThreads).end()) { 419 unsigned thread_num = *threads++; 420 421 if (instList[thread_num].empty()) 422 continue; 423 424 if (first_valid) { 425 head = instList[thread_num].begin(); 426 lowest_num = (*head)->seqNum; 427 first_valid = false; 428 continue; 429 } 430 431 InstIt head_thread = instList[thread_num].begin(); 432 433 DynInstPtr head_inst = (*head_thread); 434 435 assert(head_inst != 0); 436 437 if (head_inst->seqNum < lowest_num) { 438 head = head_thread; 439 lowest_num = head_inst->seqNum; 440 } 441 } 442 443 if (first_valid) { 444 head = instList[0].end(); 445 } 446 447} 448 449template <class Impl> 450void 451ROB<Impl>::updateTail() 452{ 453 tail = instList[0].end(); 454 bool first_valid = true; 455 456 list<unsigned>::iterator threads = (*activeThreads).begin(); 457 458 while (threads != (*activeThreads).end()) { 459 unsigned tid = *threads++; 460 461 if (instList[tid].empty()) { 462 continue; 463 } 464 465 // If this is the first valid then assign w/out 466 // comparison 467 if (first_valid) { 468 tail = instList[tid].end(); 469 tail--; 470 first_valid = false; 471 continue; 472 } 473 474 // Assign new tail if this thread's tail is younger 475 // than our current "tail high" 476 InstIt tail_thread = instList[tid].end(); 477 tail_thread--; 478 479 if ((*tail_thread)->seqNum > (*tail)->seqNum) { 480 tail = tail_thread; 481 } 482 } 483} 484 485 486template <class Impl> 487void 488ROB<Impl>::squash(InstSeqNum squash_num,unsigned tid) 489{ 490 if (isEmpty()) { 491 DPRINTF(ROB, "Does not need to squash due to being empty " 492 "[sn:%i]\n", 493 squash_num); 494 495 return; 496 } 497 498 DPRINTF(ROB, "Starting to squash within the ROB.\n"); 499 500 robStatus[tid] = ROBSquashing; 501 502 doneSquashing[tid] = false; 503 504 squashedSeqNum = squash_num; 505 506 if (!instList[tid].empty()) { 507 InstIt tail_thread = instList[tid].end(); 508 tail_thread--; 509 510 squashIt[tid] = tail_thread; 511 512 doSquash(tid); 513 } 514} 515 516template <class Impl> 517typename Impl::DynInstPtr 518ROB<Impl>::readHeadInst() 519{ 520 if (numInstsInROB != 0) { 521 assert((*head)->isInROB()==true); 522 return *head; 523 } else { 524 return dummyInst; 525 } 526} 527 528template <class Impl> 529typename Impl::DynInstPtr 530ROB<Impl>::readHeadInst(unsigned tid) 531{ 532 if (threadEntries[tid] != 0) { 533 InstIt head_thread = instList[tid].begin(); 534 535 assert((*head_thread)->isInROB()==true); 536 537 return *head_thread; 538 } else { 539 return dummyInst; 540 } 541} 542 543template <class Impl> 544uint64_t 545ROB<Impl>::readHeadPC() 546{ 547 //assert(numInstsInROB == countInsts()); 548 549 DynInstPtr head_inst = *head; 550 551 return head_inst->readPC(); 552} 553 554template <class Impl> 555uint64_t 556ROB<Impl>::readHeadPC(unsigned tid) 557{ 558 //assert(numInstsInROB == countInsts()); 559 InstIt head_thread = instList[tid].begin(); 560 561 return (*head_thread)->readPC(); 562} 563 564 565template <class Impl> 566uint64_t 567ROB<Impl>::readHeadNextPC() 568{ 569 //assert(numInstsInROB == countInsts()); 570 571 DynInstPtr head_inst = *head; 572 573 return head_inst->readNextPC(); 574} 575 576template <class Impl> 577uint64_t 578ROB<Impl>::readHeadNextPC(unsigned tid) 579{ 580 //assert(numInstsInROB == countInsts()); 581 InstIt head_thread = instList[tid].begin(); 582 583 return (*head_thread)->readNextPC(); 584} 585 586 587template <class Impl> 588InstSeqNum 589ROB<Impl>::readHeadSeqNum() 590{ 591 //assert(numInstsInROB == countInsts()); 592 DynInstPtr head_inst = *head; 593 594 return head_inst->seqNum; 595} 596 597template <class Impl> 598InstSeqNum 599ROB<Impl>::readHeadSeqNum(unsigned tid) 600{ 601 InstIt head_thread = instList[tid].begin(); 602 603 return ((*head_thread)->seqNum); 604} 605 606template <class Impl> 607typename Impl::DynInstPtr 608ROB<Impl>::readTailInst() 609{ 610 //assert(numInstsInROB == countInsts()); 611 //assert(tail != instList[0].end()); 612 613 return (*tail); 614} 615 616template <class Impl> 617typename Impl::DynInstPtr 618ROB<Impl>::readTailInst(unsigned tid) 619{ 620 //assert(tail_thread[tid] != instList[tid].end()); 621 622 InstIt tail_thread = instList[tid].end(); 623 tail_thread--; 624 625 return *tail_thread; 626} 627 628 629template <class Impl> 630uint64_t 631ROB<Impl>::readTailPC() 632{ 633 //assert(numInstsInROB == countInsts()); 634 635 //assert(tail != instList[0].end()); 636 637 return (*tail)->readPC(); 638} 639 640template <class Impl> 641uint64_t 642ROB<Impl>::readTailPC(unsigned tid) 643{ 644 //assert(tail_thread[tid] != instList[tid].end()); 645 646 InstIt tail_thread = instList[tid].end(); 647 tail_thread--; 648 649 return (*tail_thread)->readPC(); 650} 651 652template <class Impl> 653InstSeqNum 654ROB<Impl>::readTailSeqNum() 655{ 656 // Return the last sequence number that has not been squashed. Other 657 // stages can use it to squash any instructions younger than the current 658 // tail. 659 return (*tail)->seqNum; 660} 661 662template <class Impl> 663InstSeqNum 664ROB<Impl>::readTailSeqNum(unsigned tid) 665{ 666 // Return the last sequence number that has not been squashed. Other 667 // stages can use it to squash any instructions younger than the current 668 // tail. 669 // assert(tail_thread[tid] != instList[tid].end()); 670 671 InstIt tail_thread = instList[tid].end(); 672 tail_thread--; 673 674 return (*tail_thread)->seqNum; 675} 676 677