rob_impl.hh revision 2731
112065Snikos.nikoleris@arm.com/*
28706Sandreas.hansson@arm.com * Copyright (c) 2004-2006 The Regents of The University of Michigan
38706Sandreas.hansson@arm.com * All rights reserved.
48706Sandreas.hansson@arm.com *
58706Sandreas.hansson@arm.com * Redistribution and use in source and binary forms, with or without
68706Sandreas.hansson@arm.com * modification, are permitted provided that the following conditions are
78706Sandreas.hansson@arm.com * met: redistributions of source code must retain the above copyright
88706Sandreas.hansson@arm.com * notice, this list of conditions and the following disclaimer;
98706Sandreas.hansson@arm.com * redistributions in binary form must reproduce the above copyright
108706Sandreas.hansson@arm.com * notice, this list of conditions and the following disclaimer in the
118706Sandreas.hansson@arm.com * documentation and/or other materials provided with the distribution;
128706Sandreas.hansson@arm.com * neither the name of the copyright holders nor the names of its
136892SBrad.Beckmann@amd.com * contributors may be used to endorse or promote products derived from
146892SBrad.Beckmann@amd.com * this software without specific prior written permission.
156892SBrad.Beckmann@amd.com *
166892SBrad.Beckmann@amd.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
176892SBrad.Beckmann@amd.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
186892SBrad.Beckmann@amd.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
196892SBrad.Beckmann@amd.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
206892SBrad.Beckmann@amd.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
216892SBrad.Beckmann@amd.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
226892SBrad.Beckmann@amd.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
236892SBrad.Beckmann@amd.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
246892SBrad.Beckmann@amd.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
256892SBrad.Beckmann@amd.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
266892SBrad.Beckmann@amd.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
276892SBrad.Beckmann@amd.com *
286892SBrad.Beckmann@amd.com * Authors: Kevin Lim
296892SBrad.Beckmann@amd.com */
306892SBrad.Beckmann@amd.com
316892SBrad.Beckmann@amd.com#include "config/full_system.hh"
326892SBrad.Beckmann@amd.com#include "cpu/o3/rob.hh"
336892SBrad.Beckmann@amd.com
346892SBrad.Beckmann@amd.comusing namespace std;
356892SBrad.Beckmann@amd.com
366892SBrad.Beckmann@amd.comtemplate <class Impl>
376892SBrad.Beckmann@amd.comROB<Impl>::ROB(unsigned _numEntries, unsigned _squashWidth,
386892SBrad.Beckmann@amd.com               string _smtROBPolicy, unsigned _smtROBThreshold,
396892SBrad.Beckmann@amd.com               unsigned _numThreads)
406892SBrad.Beckmann@amd.com    : numEntries(_numEntries),
416892SBrad.Beckmann@amd.com      squashWidth(_squashWidth),
427563SBrad.Beckmann@amd.com      numInstsInROB(0),
436892SBrad.Beckmann@amd.com      squashedSeqNum(0),
446892SBrad.Beckmann@amd.com      numThreads(_numThreads)
456892SBrad.Beckmann@amd.com{
4610118Snilay@cs.wisc.edu    for (int tid=0; tid  < numThreads; tid++) {
4710118Snilay@cs.wisc.edu        doneSquashing[tid] = true;
4811682Sandreas.hansson@arm.com        threadEntries[tid] = 0;
4911662Stushar@ece.gatech.edu    }
5011670Sandreas.hansson@arm.com
5111670Sandreas.hansson@arm.com    string policy = _smtROBPolicy;
526892SBrad.Beckmann@amd.com
537538SBrad.Beckmann@amd.com    //Convert string to lowercase
548939SBrad.Beckmann@amd.com    std::transform(policy.begin(), policy.end(), policy.begin(),
5512014Sgabeblack@google.com                   (int(*)(int)) tolower);
568939SBrad.Beckmann@amd.com
579791Sakash.bagdia@arm.com    //Figure out rob policy
589791Sakash.bagdia@arm.com    if (policy == "dynamic") {
599791Sakash.bagdia@arm.com        robPolicy = Dynamic;
609791Sakash.bagdia@arm.com
6110525Snilay@cs.wisc.edu        //Set Max Entries to Total ROB Capacity
6210525Snilay@cs.wisc.edu        for (int i = 0; i < numThreads; i++) {
6310525Snilay@cs.wisc.edu            maxEntries[i]=numEntries;
649841Snilay@cs.wisc.edu        }
659841Snilay@cs.wisc.edu
669841Snilay@cs.wisc.edu    } else if (policy == "partitioned") {
679841Snilay@cs.wisc.edu        robPolicy = Partitioned;
689841Snilay@cs.wisc.edu        DPRINTF(Fetch, "ROB sharing policy set to Partitioned\n");
6911662Stushar@ece.gatech.edu
707538SBrad.Beckmann@amd.com        //@todo:make work if part_amt doesnt divide evenly.
717538SBrad.Beckmann@amd.com        int part_amt = numEntries / numThreads;
727917SBrad.Beckmann@amd.com
737563SBrad.Beckmann@amd.com        //Divide ROB up evenly
747563SBrad.Beckmann@amd.com        for (int i = 0; i < numThreads; i++) {
757538SBrad.Beckmann@amd.com            maxEntries[i]=part_amt;
767566SBrad.Beckmann@amd.com        }
777566SBrad.Beckmann@amd.com
787809Snilay@cs.wisc.edu    } else if (policy == "threshold") {
797538SBrad.Beckmann@amd.com        robPolicy = Threshold;
807538SBrad.Beckmann@amd.com        DPRINTF(Fetch, "ROB sharing policy set to Threshold\n");
817538SBrad.Beckmann@amd.com
8211670Sandreas.hansson@arm.com        int threshold =  _smtROBThreshold;;
837538SBrad.Beckmann@amd.com
8410524Snilay@cs.wisc.edu        //Divide up by threshold amount
8510524Snilay@cs.wisc.edu        for (int i = 0; i < numThreads; i++) {
8610524Snilay@cs.wisc.edu            maxEntries[i]=threshold;
8710524Snilay@cs.wisc.edu        }
8810524Snilay@cs.wisc.edu    } else {
8910524Snilay@cs.wisc.edu        assert(0 && "Invalid ROB Sharing Policy.Options Are:{Dynamic,"
9010524Snilay@cs.wisc.edu                    "Partitioned, Threshold}");
9110524Snilay@cs.wisc.edu    }
9210524Snilay@cs.wisc.edu}
9310524Snilay@cs.wisc.edu
9410524Snilay@cs.wisc.edutemplate <class Impl>
9510524Snilay@cs.wisc.edustd::string
9610524Snilay@cs.wisc.eduROB<Impl>::name() const
9710524Snilay@cs.wisc.edu{
9810524Snilay@cs.wisc.edu    return cpu->name() + ".rob";
9910720Sandreas.hansson@arm.com}
10010524Snilay@cs.wisc.edu
10110524Snilay@cs.wisc.edutemplate <class Impl>
10210524Snilay@cs.wisc.eduvoid
10310524Snilay@cs.wisc.eduROB<Impl>::setCPU(FullCPU *cpu_ptr)
10410524Snilay@cs.wisc.edu{
10510524Snilay@cs.wisc.edu    cpu = cpu_ptr;
10610524Snilay@cs.wisc.edu
10710524Snilay@cs.wisc.edu    // Set the per-thread iterators to the end of the instruction list.
10811616Sdavid.j.hashe@gmail.com    for (int i=0; i < numThreads;i++) {
10911616Sdavid.j.hashe@gmail.com        squashIt[i] = instList[i].end();
11011616Sdavid.j.hashe@gmail.com    }
11110524Snilay@cs.wisc.edu
11210524Snilay@cs.wisc.edu    // Initialize the "universal" ROB head & tail point to invalid
11310524Snilay@cs.wisc.edu    // pointers
11410524Snilay@cs.wisc.edu    head = instList[0].end();
11510524Snilay@cs.wisc.edu    tail = instList[0].end();
11610524Snilay@cs.wisc.edu}
11710524Snilay@cs.wisc.edu
11810524Snilay@cs.wisc.edutemplate <class Impl>
11910524Snilay@cs.wisc.eduvoid
12010524Snilay@cs.wisc.eduROB<Impl>::setActiveThreads(list<unsigned> *at_ptr)
12110524Snilay@cs.wisc.edu{
12210524Snilay@cs.wisc.edu    DPRINTF(ROB, "Setting active threads list pointer.\n");
12310524Snilay@cs.wisc.edu    activeThreads = at_ptr;
12410524Snilay@cs.wisc.edu}
12510524Snilay@cs.wisc.edu
1269100SBrad.Beckmann@amd.comtemplate <class Impl>
1279100SBrad.Beckmann@amd.comvoid
1289100SBrad.Beckmann@amd.comROB<Impl>::switchOut()
1299100SBrad.Beckmann@amd.com{
1309100SBrad.Beckmann@amd.com    for (int tid = 0; tid < numThreads; tid++) {
1319100SBrad.Beckmann@amd.com        instList[tid].clear();
13211670Sandreas.hansson@arm.com    }
1339100SBrad.Beckmann@amd.com}
1349100SBrad.Beckmann@amd.com
1359100SBrad.Beckmann@amd.comtemplate <class Impl>
13610519Snilay@cs.wisc.eduvoid
1376892SBrad.Beckmann@amd.comROB<Impl>::takeOverFrom()
13810524Snilay@cs.wisc.edu{
1398436SBrad.Beckmann@amd.com    for (int tid=0; tid  < numThreads; tid++) {
1408436SBrad.Beckmann@amd.com        doneSquashing[tid] = true;
14111662Stushar@ece.gatech.edu        threadEntries[tid] = 0;
14211662Stushar@ece.gatech.edu        squashIt[tid] = instList[tid].end();
14311662Stushar@ece.gatech.edu    }
14410311Snilay@cs.wisc.edu    numInstsInROB = 0;
14510311Snilay@cs.wisc.edu
14610551Ssteve.reinhardt@amd.com    // Initialize the "universal" ROB head & tail point to invalid
14710551Ssteve.reinhardt@amd.com    // pointers
14810311Snilay@cs.wisc.edu    head = instList[0].end();
14910311Snilay@cs.wisc.edu    tail = instList[0].end();
15010551Ssteve.reinhardt@amd.com}
15110551Ssteve.reinhardt@amd.com
15210551Ssteve.reinhardt@amd.comtemplate <class Impl>
15310311Snilay@cs.wisc.eduvoid
15410551Ssteve.reinhardt@amd.comROB<Impl>::resetEntries()
15510311Snilay@cs.wisc.edu{
15610311Snilay@cs.wisc.edu    if (robPolicy != Dynamic || numThreads > 1) {
15711662Stushar@ece.gatech.edu        int active_threads = (*activeThreads).size();
15811662Stushar@ece.gatech.edu
15911662Stushar@ece.gatech.edu        list<unsigned>::iterator threads  = (*activeThreads).begin();
16011662Stushar@ece.gatech.edu        list<unsigned>::iterator list_end = (*activeThreads).end();
16111662Stushar@ece.gatech.edu
16211662Stushar@ece.gatech.edu        while (threads != list_end) {
16311662Stushar@ece.gatech.edu            if (robPolicy == Partitioned) {
16410311Snilay@cs.wisc.edu                maxEntries[*threads++] = numEntries / active_threads;
16510311Snilay@cs.wisc.edu            } else if (robPolicy == Threshold && active_threads == 1) {
16610311Snilay@cs.wisc.edu                maxEntries[*threads++] = numEntries;
16710311Snilay@cs.wisc.edu            }
16811596Sandreas.sandberg@arm.com        }
16911596Sandreas.sandberg@arm.com    }
17010311Snilay@cs.wisc.edu}
17110311Snilay@cs.wisc.edu
17210311Snilay@cs.wisc.edutemplate <class Impl>
17310311Snilay@cs.wisc.eduint
17410311Snilay@cs.wisc.eduROB<Impl>::entryAmount(int num_threads)
17510311Snilay@cs.wisc.edu{
17610311Snilay@cs.wisc.edu    if (robPolicy == Partitioned) {
1779148Spowerjg@cs.wisc.edu        return numEntries / num_threads;
17810524Snilay@cs.wisc.edu    } else {
17910116Snilay@cs.wisc.edu        return 0;
18010116Snilay@cs.wisc.edu    }
18110116Snilay@cs.wisc.edu}
18210116Snilay@cs.wisc.edu
18310116Snilay@cs.wisc.edutemplate <class Impl>
18410116Snilay@cs.wisc.eduint
18510116Snilay@cs.wisc.eduROB<Impl>::countInsts()
18610116Snilay@cs.wisc.edu{
18710116Snilay@cs.wisc.edu    int total=0;
18810116Snilay@cs.wisc.edu
18911172Snilay@cs.wisc.edu    for (int i=0;i < numThreads;i++)
19010120Snilay@cs.wisc.edu        total += countInsts(i);
19110012Snilay@cs.wisc.edu
19210525Snilay@cs.wisc.edu    return total;
19310630Snilay@cs.wisc.edu}
19410630Snilay@cs.wisc.edu
19510706Spower.jg@gmail.comtemplate <class Impl>
19610706Spower.jg@gmail.comint
19710630Snilay@cs.wisc.eduROB<Impl>::countInsts(unsigned tid)
19810630Snilay@cs.wisc.edu{
19912065Snikos.nikoleris@arm.com    return instList[tid].size();
20012065Snikos.nikoleris@arm.com}
20112065Snikos.nikoleris@arm.com
20212065Snikos.nikoleris@arm.comtemplate <class Impl>
20312065Snikos.nikoleris@arm.comvoid
20412065Snikos.nikoleris@arm.comROB<Impl>::insertInst(DynInstPtr &inst)
20512065Snikos.nikoleris@arm.com{
20612065Snikos.nikoleris@arm.com    //assert(numInstsInROB == countInsts());
20712065Snikos.nikoleris@arm.com    assert(inst);
20812065Snikos.nikoleris@arm.com
20912065Snikos.nikoleris@arm.com    DPRINTF(ROB, "Adding inst PC %#x to the ROB.\n", inst->readPC());
21012065Snikos.nikoleris@arm.com
21112065Snikos.nikoleris@arm.com    assert(numInstsInROB != numEntries);
21212065Snikos.nikoleris@arm.com
21312065Snikos.nikoleris@arm.com    int tid = inst->threadNumber;
21412065Snikos.nikoleris@arm.com
21512065Snikos.nikoleris@arm.com    instList[tid].push_back(inst);
21612065Snikos.nikoleris@arm.com
21712065Snikos.nikoleris@arm.com    //Set Up head iterator if this is the 1st instruction in the ROB
21812065Snikos.nikoleris@arm.com    if (numInstsInROB == 0) {
21912065Snikos.nikoleris@arm.com        head = instList[tid].begin();
22012065Snikos.nikoleris@arm.com        assert((*head) == inst);
22112065Snikos.nikoleris@arm.com    }
22212065Snikos.nikoleris@arm.com
22312065Snikos.nikoleris@arm.com    //Must Decrement for iterator to actually be valid  since __.end()
22412065Snikos.nikoleris@arm.com    //actually points to 1 after the last inst
22512065Snikos.nikoleris@arm.com    tail = instList[tid].end();
22612065Snikos.nikoleris@arm.com    tail--;
22712065Snikos.nikoleris@arm.com
22812065Snikos.nikoleris@arm.com    inst->setInROB();
22912065Snikos.nikoleris@arm.com
23010529Smorr@cs.wisc.edu    ++numInstsInROB;
23110529Smorr@cs.wisc.edu    ++threadEntries[tid];
23210529Smorr@cs.wisc.edu
23310529Smorr@cs.wisc.edu    assert((*tail) == inst);
23412014Sgabeblack@google.com
23510529Smorr@cs.wisc.edu    DPRINTF(ROB, "[tid:%i] Now has %d instructions.\n", tid, threadEntries[tid]);
23610529Smorr@cs.wisc.edu}
237
238// Whatever calls this function needs to ensure that it properly frees up
239// registers prior to this function.
240/*
241template <class Impl>
242void
243ROB<Impl>::retireHead()
244{
245    //assert(numInstsInROB == countInsts());
246    assert(numInstsInROB > 0);
247
248    int tid = (*head)->threadNumber;
249
250    retireHead(tid);
251
252    if (numInstsInROB == 0) {
253        tail = instList[tid].end();
254    }
255}
256*/
257
258template <class Impl>
259void
260ROB<Impl>::retireHead(unsigned tid)
261{
262    //assert(numInstsInROB == countInsts());
263    assert(numInstsInROB > 0);
264
265    // Get the head ROB instruction.
266    InstIt head_it = instList[tid].begin();
267
268    DynInstPtr head_inst = (*head_it);
269
270    assert(head_inst->readyToCommit());
271
272    DPRINTF(ROB, "[tid:%u]: Retiring head instruction, "
273            "instruction PC %#x,[sn:%lli]\n", tid, head_inst->readPC(),
274            head_inst->seqNum);
275
276    --numInstsInROB;
277    --threadEntries[tid];
278
279    head_inst->clearInROB();
280    head_inst->setCommitted();
281
282    instList[tid].erase(head_it);
283
284    //Update "Global" Head of ROB
285    updateHead();
286
287    // @todo: A special case is needed if the instruction being
288    // retired is the only instruction in the ROB; otherwise the tail
289    // iterator will become invalidated.
290    cpu->removeFrontInst(head_inst);
291}
292/*
293template <class Impl>
294bool
295ROB<Impl>::isHeadReady()
296{
297    if (numInstsInROB != 0) {
298        return (*head)->readyToCommit();
299    }
300
301    return false;
302}
303*/
304template <class Impl>
305bool
306ROB<Impl>::isHeadReady(unsigned tid)
307{
308    if (threadEntries[tid] != 0) {
309        return instList[tid].front()->readyToCommit();
310    }
311
312    return false;
313}
314
315template <class Impl>
316bool
317ROB<Impl>::canCommit()
318{
319    //@todo: set ActiveThreads through ROB or CPU
320    list<unsigned>::iterator threads = (*activeThreads).begin();
321
322    while (threads != (*activeThreads).end()) {
323        unsigned tid = *threads++;
324
325        if (isHeadReady(tid)) {
326            return true;
327        }
328    }
329
330    return false;
331}
332
333template <class Impl>
334unsigned
335ROB<Impl>::numFreeEntries()
336{
337    //assert(numInstsInROB == countInsts());
338
339    return numEntries - numInstsInROB;
340}
341
342template <class Impl>
343unsigned
344ROB<Impl>::numFreeEntries(unsigned tid)
345{
346    return maxEntries[tid] - threadEntries[tid];
347}
348
349template <class Impl>
350void
351ROB<Impl>::doSquash(unsigned tid)
352{
353    DPRINTF(ROB, "[tid:%u]: Squashing instructions until [sn:%i].\n",
354            tid, squashedSeqNum);
355
356    assert(squashIt[tid] != instList[tid].end());
357
358    if ((*squashIt[tid])->seqNum < squashedSeqNum) {
359        DPRINTF(ROB, "[tid:%u]: Done squashing instructions.\n",
360                tid);
361
362        squashIt[tid] = instList[tid].end();
363
364        doneSquashing[tid] = true;
365        return;
366    }
367
368    bool robTailUpdate = false;
369
370    for (int numSquashed = 0;
371         numSquashed < squashWidth &&
372         squashIt[tid] != instList[tid].end() &&
373         (*squashIt[tid])->seqNum > squashedSeqNum;
374         ++numSquashed)
375    {
376        DPRINTF(ROB, "[tid:%u]: Squashing instruction PC %#x, seq num %i.\n",
377                (*squashIt[tid])->threadNumber,
378                (*squashIt[tid])->readPC(),
379                (*squashIt[tid])->seqNum);
380
381        // Mark the instruction as squashed, and ready to commit so that
382        // it can drain out of the pipeline.
383        (*squashIt[tid])->setSquashed();
384
385        (*squashIt[tid])->setCanCommit();
386
387
388        if (squashIt[tid] == instList[tid].begin()) {
389            DPRINTF(ROB, "Reached head of instruction list while "
390                    "squashing.\n");
391
392            squashIt[tid] = instList[tid].end();
393
394            doneSquashing[tid] = true;
395
396            return;
397        }
398
399        InstIt tail_thread = instList[tid].end();
400        tail_thread--;
401
402        if ((*squashIt[tid]) == (*tail_thread))
403            robTailUpdate = true;
404
405        squashIt[tid]--;
406    }
407
408
409    // Check if ROB is done squashing.
410    if ((*squashIt[tid])->seqNum <= squashedSeqNum) {
411        DPRINTF(ROB, "[tid:%u]: Done squashing instructions.\n",
412                tid);
413
414        squashIt[tid] = instList[tid].end();
415
416        doneSquashing[tid] = true;
417    }
418
419    if (robTailUpdate) {
420        updateTail();
421    }
422}
423
424
425template <class Impl>
426void
427ROB<Impl>::updateHead()
428{
429    DynInstPtr head_inst;
430    InstSeqNum lowest_num = 0;
431    bool first_valid = true;
432
433    // @todo: set ActiveThreads through ROB or CPU
434    list<unsigned>::iterator threads = (*activeThreads).begin();
435
436    while (threads != (*activeThreads).end()) {
437        unsigned thread_num = *threads++;
438
439        if (instList[thread_num].empty())
440            continue;
441
442        if (first_valid) {
443            head = instList[thread_num].begin();
444            lowest_num = (*head)->seqNum;
445            first_valid = false;
446            continue;
447        }
448
449        InstIt head_thread = instList[thread_num].begin();
450
451        DynInstPtr head_inst = (*head_thread);
452
453        assert(head_inst != 0);
454
455        if (head_inst->seqNum < lowest_num) {
456            head = head_thread;
457            lowest_num = head_inst->seqNum;
458        }
459    }
460
461    if (first_valid) {
462        head = instList[0].end();
463    }
464
465}
466
467template <class Impl>
468void
469ROB<Impl>::updateTail()
470{
471    tail = instList[0].end();
472    bool first_valid = true;
473
474    list<unsigned>::iterator threads = (*activeThreads).begin();
475
476    while (threads != (*activeThreads).end()) {
477        unsigned tid = *threads++;
478
479        if (instList[tid].empty()) {
480            continue;
481        }
482
483        // If this is the first valid then assign w/out
484        // comparison
485        if (first_valid) {
486            tail = instList[tid].end();
487            tail--;
488            first_valid = false;
489            continue;
490        }
491
492        // Assign new tail if this thread's tail is younger
493        // than our current "tail high"
494        InstIt tail_thread = instList[tid].end();
495        tail_thread--;
496
497        if ((*tail_thread)->seqNum > (*tail)->seqNum) {
498            tail = tail_thread;
499        }
500    }
501}
502
503
504template <class Impl>
505void
506ROB<Impl>::squash(InstSeqNum squash_num,unsigned tid)
507{
508    if (isEmpty()) {
509        DPRINTF(ROB, "Does not need to squash due to being empty "
510                "[sn:%i]\n",
511                squash_num);
512
513        return;
514    }
515
516    DPRINTF(ROB, "Starting to squash within the ROB.\n");
517
518    robStatus[tid] = ROBSquashing;
519
520    doneSquashing[tid] = false;
521
522    squashedSeqNum = squash_num;
523
524    if (!instList[tid].empty()) {
525        InstIt tail_thread = instList[tid].end();
526        tail_thread--;
527
528        squashIt[tid] = tail_thread;
529
530        doSquash(tid);
531    }
532}
533/*
534template <class Impl>
535typename Impl::DynInstPtr
536ROB<Impl>::readHeadInst()
537{
538    if (numInstsInROB != 0) {
539        assert((*head)->isInROB()==true);
540        return *head;
541    } else {
542        return dummyInst;
543    }
544}
545*/
546template <class Impl>
547typename Impl::DynInstPtr
548ROB<Impl>::readHeadInst(unsigned tid)
549{
550    if (threadEntries[tid] != 0) {
551        InstIt head_thread = instList[tid].begin();
552
553        assert((*head_thread)->isInROB()==true);
554
555        return *head_thread;
556    } else {
557        return dummyInst;
558    }
559}
560/*
561template <class Impl>
562uint64_t
563ROB<Impl>::readHeadPC()
564{
565    //assert(numInstsInROB == countInsts());
566
567    DynInstPtr head_inst = *head;
568
569    return head_inst->readPC();
570}
571
572template <class Impl>
573uint64_t
574ROB<Impl>::readHeadPC(unsigned tid)
575{
576    //assert(numInstsInROB == countInsts());
577    InstIt head_thread = instList[tid].begin();
578
579    return (*head_thread)->readPC();
580}
581
582
583template <class Impl>
584uint64_t
585ROB<Impl>::readHeadNextPC()
586{
587    //assert(numInstsInROB == countInsts());
588
589    DynInstPtr head_inst = *head;
590
591    return head_inst->readNextPC();
592}
593
594template <class Impl>
595uint64_t
596ROB<Impl>::readHeadNextPC(unsigned tid)
597{
598    //assert(numInstsInROB == countInsts());
599    InstIt head_thread = instList[tid].begin();
600
601    return (*head_thread)->readNextPC();
602}
603
604template <class Impl>
605InstSeqNum
606ROB<Impl>::readHeadSeqNum()
607{
608    //assert(numInstsInROB == countInsts());
609    DynInstPtr head_inst = *head;
610
611    return head_inst->seqNum;
612}
613
614template <class Impl>
615InstSeqNum
616ROB<Impl>::readHeadSeqNum(unsigned tid)
617{
618    InstIt head_thread = instList[tid].begin();
619
620    return ((*head_thread)->seqNum);
621}
622
623template <class Impl>
624typename Impl::DynInstPtr
625ROB<Impl>::readTailInst()
626{
627    //assert(numInstsInROB == countInsts());
628    //assert(tail != instList[0].end());
629
630    return (*tail);
631}
632*/
633template <class Impl>
634typename Impl::DynInstPtr
635ROB<Impl>::readTailInst(unsigned tid)
636{
637    //assert(tail_thread[tid] != instList[tid].end());
638
639    InstIt tail_thread = instList[tid].end();
640    tail_thread--;
641
642    return *tail_thread;
643}
644
645/*
646template <class Impl>
647uint64_t
648ROB<Impl>::readTailPC()
649{
650    //assert(numInstsInROB == countInsts());
651
652    //assert(tail != instList[0].end());
653
654    return (*tail)->readPC();
655}
656
657template <class Impl>
658uint64_t
659ROB<Impl>::readTailPC(unsigned tid)
660{
661    //assert(tail_thread[tid] != instList[tid].end());
662
663    InstIt tail_thread = instList[tid].end();
664    tail_thread--;
665
666    return (*tail_thread)->readPC();
667}
668
669template <class Impl>
670InstSeqNum
671ROB<Impl>::readTailSeqNum()
672{
673    // Return the last sequence number that has not been squashed.  Other
674    // stages can use it to squash any instructions younger than the current
675    // tail.
676    return (*tail)->seqNum;
677}
678
679template <class Impl>
680InstSeqNum
681ROB<Impl>::readTailSeqNum(unsigned tid)
682{
683    // Return the last sequence number that has not been squashed.  Other
684    // stages can use it to squash any instructions younger than the current
685    // tail.
686    //    assert(tail_thread[tid] != instList[tid].end());
687
688    InstIt tail_thread = instList[tid].end();
689    tail_thread--;
690
691    return (*tail_thread)->seqNum;
692}
693*/
694