cpu.cc revision 6032:e5c792a67b3d
1/*
2 * Copyright (c) 2004-2006 The Regents of The University of Michigan
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met: redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer;
9 * redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution;
12 * neither the name of the copyright holders nor the names of its
13 * contributors may be used to endorse or promote products derived from
14 * this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 *
28 * Authors: Kevin Lim
29 *          Korey Sewell
30 */
31
32#include "config/full_system.hh"
33#include "config/use_checker.hh"
34
35#include "cpu/activity.hh"
36#include "cpu/simple_thread.hh"
37#include "cpu/thread_context.hh"
38#include "cpu/o3/isa_specific.hh"
39#include "cpu/o3/cpu.hh"
40#include "cpu/o3/thread_context.hh"
41#include "enums/MemoryMode.hh"
42#include "sim/core.hh"
43#include "sim/stat_control.hh"
44
45#if FULL_SYSTEM
46#include "cpu/quiesce_event.hh"
47#include "sim/system.hh"
48#else
49#include "sim/process.hh"
50#endif
51
52#if USE_CHECKER
53#include "cpu/checker/cpu.hh"
54#endif
55
56#if THE_ISA == ALPHA_ISA
57#include "arch/alpha/osfpal.hh"
58#endif
59
60class BaseCPUParams;
61
62using namespace TheISA;
63
64BaseO3CPU::BaseO3CPU(BaseCPUParams *params)
65    : BaseCPU(params)
66{
67}
68
69void
70BaseO3CPU::regStats()
71{
72    BaseCPU::regStats();
73}
74
75template <class Impl>
76FullO3CPU<Impl>::TickEvent::TickEvent(FullO3CPU<Impl> *c)
77    : Event(CPU_Tick_Pri), cpu(c)
78{
79}
80
81template <class Impl>
82void
83FullO3CPU<Impl>::TickEvent::process()
84{
85    cpu->tick();
86}
87
88template <class Impl>
89const char *
90FullO3CPU<Impl>::TickEvent::description() const
91{
92    return "FullO3CPU tick";
93}
94
95template <class Impl>
96FullO3CPU<Impl>::ActivateThreadEvent::ActivateThreadEvent()
97    : Event(CPU_Switch_Pri)
98{
99}
100
101template <class Impl>
102void
103FullO3CPU<Impl>::ActivateThreadEvent::init(int thread_num,
104                                           FullO3CPU<Impl> *thread_cpu)
105{
106    tid = thread_num;
107    cpu = thread_cpu;
108}
109
110template <class Impl>
111void
112FullO3CPU<Impl>::ActivateThreadEvent::process()
113{
114    cpu->activateThread(tid);
115}
116
117template <class Impl>
118const char *
119FullO3CPU<Impl>::ActivateThreadEvent::description() const
120{
121    return "FullO3CPU \"Activate Thread\"";
122}
123
124template <class Impl>
125FullO3CPU<Impl>::DeallocateContextEvent::DeallocateContextEvent()
126    : Event(CPU_Tick_Pri), tid(0), remove(false), cpu(NULL)
127{
128}
129
130template <class Impl>
131void
132FullO3CPU<Impl>::DeallocateContextEvent::init(int thread_num,
133                                              FullO3CPU<Impl> *thread_cpu)
134{
135    tid = thread_num;
136    cpu = thread_cpu;
137    remove = false;
138}
139
140template <class Impl>
141void
142FullO3CPU<Impl>::DeallocateContextEvent::process()
143{
144    cpu->deactivateThread(tid);
145    if (remove)
146        cpu->removeThread(tid);
147}
148
149template <class Impl>
150const char *
151FullO3CPU<Impl>::DeallocateContextEvent::description() const
152{
153    return "FullO3CPU \"Deallocate Context\"";
154}
155
156template <class Impl>
157FullO3CPU<Impl>::FullO3CPU(DerivO3CPUParams *params)
158    : BaseO3CPU(params),
159      itb(params->itb),
160      dtb(params->dtb),
161      tickEvent(this),
162#ifndef NDEBUG
163      instcount(0),
164#endif
165      removeInstsThisCycle(false),
166      fetch(this, params),
167      decode(this, params),
168      rename(this, params),
169      iew(this, params),
170      commit(this, params),
171
172      regFile(this, params->numPhysIntRegs,
173              params->numPhysFloatRegs),
174
175      freeList(params->numThreads,
176               TheISA::NumIntRegs, params->numPhysIntRegs,
177               TheISA::NumFloatRegs, params->numPhysFloatRegs),
178
179      rob(this,
180          params->numROBEntries, params->squashWidth,
181          params->smtROBPolicy, params->smtROBThreshold,
182          params->numThreads),
183
184      scoreboard(params->numThreads,
185                 TheISA::NumIntRegs, params->numPhysIntRegs,
186                 TheISA::NumFloatRegs, params->numPhysFloatRegs,
187                 TheISA::NumMiscRegs * number_of_threads,
188                 TheISA::ZeroReg),
189
190      timeBuffer(params->backComSize, params->forwardComSize),
191      fetchQueue(params->backComSize, params->forwardComSize),
192      decodeQueue(params->backComSize, params->forwardComSize),
193      renameQueue(params->backComSize, params->forwardComSize),
194      iewQueue(params->backComSize, params->forwardComSize),
195      activityRec(name(), NumStages,
196                  params->backComSize + params->forwardComSize,
197                  params->activity),
198
199      globalSeqNum(1),
200#if FULL_SYSTEM
201      system(params->system),
202      physmem(system->physmem),
203#endif // FULL_SYSTEM
204      drainCount(0),
205      deferRegistration(params->defer_registration),
206      numThreads(number_of_threads)
207{
208    if (!deferRegistration) {
209        _status = Running;
210    } else {
211        _status = Idle;
212    }
213
214#if USE_CHECKER
215    if (params->checker) {
216        BaseCPU *temp_checker = params->checker;
217        checker = dynamic_cast<Checker<DynInstPtr> *>(temp_checker);
218#if FULL_SYSTEM
219        checker->setSystem(params->system);
220#endif
221    } else {
222        checker = NULL;
223    }
224#endif // USE_CHECKER
225
226#if !FULL_SYSTEM
227    thread.resize(number_of_threads);
228    tids.resize(number_of_threads);
229#endif
230
231    // The stages also need their CPU pointer setup.  However this
232    // must be done at the upper level CPU because they have pointers
233    // to the upper level CPU, and not this FullO3CPU.
234
235    // Set up Pointers to the activeThreads list for each stage
236    fetch.setActiveThreads(&activeThreads);
237    decode.setActiveThreads(&activeThreads);
238    rename.setActiveThreads(&activeThreads);
239    iew.setActiveThreads(&activeThreads);
240    commit.setActiveThreads(&activeThreads);
241
242    // Give each of the stages the time buffer they will use.
243    fetch.setTimeBuffer(&timeBuffer);
244    decode.setTimeBuffer(&timeBuffer);
245    rename.setTimeBuffer(&timeBuffer);
246    iew.setTimeBuffer(&timeBuffer);
247    commit.setTimeBuffer(&timeBuffer);
248
249    // Also setup each of the stages' queues.
250    fetch.setFetchQueue(&fetchQueue);
251    decode.setFetchQueue(&fetchQueue);
252    commit.setFetchQueue(&fetchQueue);
253    decode.setDecodeQueue(&decodeQueue);
254    rename.setDecodeQueue(&decodeQueue);
255    rename.setRenameQueue(&renameQueue);
256    iew.setRenameQueue(&renameQueue);
257    iew.setIEWQueue(&iewQueue);
258    commit.setIEWQueue(&iewQueue);
259    commit.setRenameQueue(&renameQueue);
260
261    commit.setIEWStage(&iew);
262    rename.setIEWStage(&iew);
263    rename.setCommitStage(&commit);
264
265#if !FULL_SYSTEM
266    int active_threads = params->workload.size();
267
268    if (active_threads > Impl::MaxThreads) {
269        panic("Workload Size too large. Increase the 'MaxThreads'"
270              "constant in your O3CPU impl. file (e.g. o3/alpha/impl.hh) or "
271              "edit your workload size.");
272    }
273#else
274    int active_threads = 1;
275#endif
276
277    //Make Sure That this a Valid Architeture
278    assert(params->numPhysIntRegs   >= numThreads * TheISA::NumIntRegs);
279    assert(params->numPhysFloatRegs >= numThreads * TheISA::NumFloatRegs);
280
281    rename.setScoreboard(&scoreboard);
282    iew.setScoreboard(&scoreboard);
283
284    // Setup the rename map for whichever stages need it.
285    PhysRegIndex lreg_idx = 0;
286    PhysRegIndex freg_idx = params->numPhysIntRegs; //Index to 1 after int regs
287
288    for (int tid=0; tid < numThreads; tid++) {
289        bool bindRegs = (tid <= active_threads - 1);
290
291        commitRenameMap[tid].init(TheISA::NumIntRegs,
292                                  params->numPhysIntRegs,
293                                  lreg_idx,            //Index for Logical. Regs
294
295                                  TheISA::NumFloatRegs,
296                                  params->numPhysFloatRegs,
297                                  freg_idx,            //Index for Float Regs
298
299                                  TheISA::NumMiscRegs,
300
301                                  TheISA::ZeroReg,
302                                  TheISA::ZeroReg,
303
304                                  tid,
305                                  false);
306
307        renameMap[tid].init(TheISA::NumIntRegs,
308                            params->numPhysIntRegs,
309                            lreg_idx,                  //Index for Logical. Regs
310
311                            TheISA::NumFloatRegs,
312                            params->numPhysFloatRegs,
313                            freg_idx,                  //Index for Float Regs
314
315                            TheISA::NumMiscRegs,
316
317                            TheISA::ZeroReg,
318                            TheISA::ZeroReg,
319
320                            tid,
321                            bindRegs);
322
323        activateThreadEvent[tid].init(tid, this);
324        deallocateContextEvent[tid].init(tid, this);
325    }
326
327    rename.setRenameMap(renameMap);
328    commit.setRenameMap(commitRenameMap);
329
330    // Give renameMap & rename stage access to the freeList;
331    for (int i=0; i < numThreads; i++) {
332        renameMap[i].setFreeList(&freeList);
333    }
334    rename.setFreeList(&freeList);
335
336    // Setup the ROB for whichever stages need it.
337    commit.setROB(&rob);
338
339    lastRunningCycle = curTick;
340
341    lastActivatedCycle = -1;
342
343    // Give renameMap & rename stage access to the freeList;
344    //for (int i=0; i < numThreads; i++) {
345        //globalSeqNum[i] = 1;
346        //}
347
348    contextSwitch = false;
349    DPRINTF(O3CPU, "Creating O3CPU object.\n");
350
351    // Setup any thread state.
352    this->thread.resize(this->numThreads);
353
354    for (int i = 0; i < this->numThreads; ++i) {
355#if FULL_SYSTEM
356        // SMT is not supported in FS mode yet.
357        assert(this->numThreads == 1);
358        this->thread[i] = new Thread(this, 0);
359#else
360        if (i < params->workload.size()) {
361            DPRINTF(O3CPU, "Workload[%i] process is %#x",
362                    i, this->thread[i]);
363            this->thread[i] = new typename FullO3CPU<Impl>::Thread(
364                    (typename Impl::O3CPU *)(this),
365                    i, params->workload[i], i);
366
367            //usedTids[i] = true;
368            //threadMap[i] = i;
369        } else {
370            //Allocate Empty thread so M5 can use later
371            //when scheduling threads to CPU
372            Process* dummy_proc = NULL;
373
374            this->thread[i] = new typename FullO3CPU<Impl>::Thread(
375                    (typename Impl::O3CPU *)(this),
376                    i, dummy_proc, i);
377            //usedTids[i] = false;
378        }
379#endif // !FULL_SYSTEM
380
381        ThreadContext *tc;
382
383        // Setup the TC that will serve as the interface to the threads/CPU.
384        O3ThreadContext<Impl> *o3_tc = new O3ThreadContext<Impl>;
385
386        tc = o3_tc;
387
388        // If we're using a checker, then the TC should be the
389        // CheckerThreadContext.
390#if USE_CHECKER
391        if (params->checker) {
392            tc = new CheckerThreadContext<O3ThreadContext<Impl> >(
393                o3_tc, this->checker);
394        }
395#endif
396
397        o3_tc->cpu = (typename Impl::O3CPU *)(this);
398        assert(o3_tc->cpu);
399        o3_tc->thread = this->thread[i];
400
401#if FULL_SYSTEM
402        // Setup quiesce event.
403        this->thread[i]->quiesceEvent = new EndQuiesceEvent(tc);
404#endif
405        // Give the thread the TC.
406        this->thread[i]->tc = tc;
407
408        // Add the TC to the CPU's list of TC's.
409        this->threadContexts.push_back(tc);
410    }
411
412    for (int i=0; i < this->numThreads; i++) {
413        this->thread[i]->setFuncExeInst(0);
414    }
415
416    lockAddr = 0;
417    lockFlag = false;
418}
419
420template <class Impl>
421FullO3CPU<Impl>::~FullO3CPU()
422{
423}
424
425template <class Impl>
426void
427FullO3CPU<Impl>::regStats()
428{
429    BaseO3CPU::regStats();
430
431    // Register any of the O3CPU's stats here.
432    timesIdled
433        .name(name() + ".timesIdled")
434        .desc("Number of times that the entire CPU went into an idle state and"
435              " unscheduled itself")
436        .prereq(timesIdled);
437
438    idleCycles
439        .name(name() + ".idleCycles")
440        .desc("Total number of cycles that the CPU has spent unscheduled due "
441              "to idling")
442        .prereq(idleCycles);
443
444    // Number of Instructions simulated
445    // --------------------------------
446    // Should probably be in Base CPU but need templated
447    // MaxThreads so put in here instead
448    committedInsts
449        .init(numThreads)
450        .name(name() + ".committedInsts")
451        .desc("Number of Instructions Simulated");
452
453    totalCommittedInsts
454        .name(name() + ".committedInsts_total")
455        .desc("Number of Instructions Simulated");
456
457    cpi
458        .name(name() + ".cpi")
459        .desc("CPI: Cycles Per Instruction")
460        .precision(6);
461    cpi = numCycles / committedInsts;
462
463    totalCpi
464        .name(name() + ".cpi_total")
465        .desc("CPI: Total CPI of All Threads")
466        .precision(6);
467    totalCpi = numCycles / totalCommittedInsts;
468
469    ipc
470        .name(name() + ".ipc")
471        .desc("IPC: Instructions Per Cycle")
472        .precision(6);
473    ipc =  committedInsts / numCycles;
474
475    totalIpc
476        .name(name() + ".ipc_total")
477        .desc("IPC: Total IPC of All Threads")
478        .precision(6);
479    totalIpc =  totalCommittedInsts / numCycles;
480
481    this->fetch.regStats();
482    this->decode.regStats();
483    this->rename.regStats();
484    this->iew.regStats();
485    this->commit.regStats();
486}
487
488template <class Impl>
489Port *
490FullO3CPU<Impl>::getPort(const std::string &if_name, int idx)
491{
492    if (if_name == "dcache_port")
493        return iew.getDcachePort();
494    else if (if_name == "icache_port")
495        return fetch.getIcachePort();
496    else
497        panic("No Such Port\n");
498}
499
500template <class Impl>
501void
502FullO3CPU<Impl>::tick()
503{
504    DPRINTF(O3CPU, "\n\nFullO3CPU: Ticking main, FullO3CPU.\n");
505
506    ++numCycles;
507
508//    activity = false;
509
510    //Tick each of the stages
511    fetch.tick();
512
513    decode.tick();
514
515    rename.tick();
516
517    iew.tick();
518
519    commit.tick();
520
521#if !FULL_SYSTEM
522    doContextSwitch();
523#endif
524
525    // Now advance the time buffers
526    timeBuffer.advance();
527
528    fetchQueue.advance();
529    decodeQueue.advance();
530    renameQueue.advance();
531    iewQueue.advance();
532
533    activityRec.advance();
534
535    if (removeInstsThisCycle) {
536        cleanUpRemovedInsts();
537    }
538
539    if (!tickEvent.scheduled()) {
540        if (_status == SwitchedOut ||
541            getState() == SimObject::Drained) {
542            DPRINTF(O3CPU, "Switched out!\n");
543            // increment stat
544            lastRunningCycle = curTick;
545        } else if (!activityRec.active() || _status == Idle) {
546            DPRINTF(O3CPU, "Idle!\n");
547            lastRunningCycle = curTick;
548            timesIdled++;
549        } else {
550            schedule(tickEvent, nextCycle(curTick + ticks(1)));
551            DPRINTF(O3CPU, "Scheduling next tick!\n");
552        }
553    }
554
555#if !FULL_SYSTEM
556    updateThreadPriority();
557#endif
558}
559
560template <class Impl>
561void
562FullO3CPU<Impl>::init()
563{
564    BaseCPU::init();
565
566    // Set inSyscall so that the CPU doesn't squash when initially
567    // setting up registers.
568    for (int i = 0; i < number_of_threads; ++i)
569        thread[i]->inSyscall = true;
570
571    for (int tid=0; tid < number_of_threads; tid++) {
572#if FULL_SYSTEM
573        ThreadContext *src_tc = threadContexts[tid];
574#else
575        ThreadContext *src_tc = thread[tid]->getTC();
576#endif
577        // Threads start in the Suspended State
578        if (src_tc->status() != ThreadContext::Suspended) {
579            continue;
580        }
581
582#if FULL_SYSTEM
583        TheISA::initCPU(src_tc, src_tc->contextId());
584#endif
585    }
586
587    // Clear inSyscall.
588    for (int i = 0; i < number_of_threads; ++i)
589        thread[i]->inSyscall = false;
590
591    // Initialize stages.
592    fetch.initStage();
593    iew.initStage();
594    rename.initStage();
595    commit.initStage();
596
597    commit.setThreads(thread);
598}
599
600template <class Impl>
601void
602FullO3CPU<Impl>::activateThread(unsigned tid)
603{
604    std::list<unsigned>::iterator isActive =
605        std::find(activeThreads.begin(), activeThreads.end(), tid);
606
607    DPRINTF(O3CPU, "[tid:%i]: Calling activate thread.\n", tid);
608
609    if (isActive == activeThreads.end()) {
610        DPRINTF(O3CPU, "[tid:%i]: Adding to active threads list\n",
611                tid);
612
613        activeThreads.push_back(tid);
614    }
615}
616
617template <class Impl>
618void
619FullO3CPU<Impl>::deactivateThread(unsigned tid)
620{
621    //Remove From Active List, if Active
622    std::list<unsigned>::iterator thread_it =
623        std::find(activeThreads.begin(), activeThreads.end(), tid);
624
625    DPRINTF(O3CPU, "[tid:%i]: Calling deactivate thread.\n", tid);
626
627    if (thread_it != activeThreads.end()) {
628        DPRINTF(O3CPU,"[tid:%i]: Removing from active threads list\n",
629                tid);
630        activeThreads.erase(thread_it);
631    }
632}
633
634template <class Impl>
635void
636FullO3CPU<Impl>::activateContext(int tid, int delay)
637{
638    // Needs to set each stage to running as well.
639    if (delay){
640        DPRINTF(O3CPU, "[tid:%i]: Scheduling thread context to activate "
641                "on cycle %d\n", tid, curTick + ticks(delay));
642        scheduleActivateThreadEvent(tid, delay);
643    } else {
644        activateThread(tid);
645    }
646
647    if (lastActivatedCycle < curTick) {
648        scheduleTickEvent(delay);
649
650        // Be sure to signal that there's some activity so the CPU doesn't
651        // deschedule itself.
652        activityRec.activity();
653        fetch.wakeFromQuiesce();
654
655        lastActivatedCycle = curTick;
656
657        _status = Running;
658    }
659}
660
661template <class Impl>
662bool
663FullO3CPU<Impl>::deallocateContext(int tid, bool remove, int delay)
664{
665    // Schedule removal of thread data from CPU
666    if (delay){
667        DPRINTF(O3CPU, "[tid:%i]: Scheduling thread context to deallocate "
668                "on cycle %d\n", tid, curTick + ticks(delay));
669        scheduleDeallocateContextEvent(tid, remove, delay);
670        return false;
671    } else {
672        deactivateThread(tid);
673        if (remove)
674            removeThread(tid);
675        return true;
676    }
677}
678
679template <class Impl>
680void
681FullO3CPU<Impl>::suspendContext(int tid)
682{
683    DPRINTF(O3CPU,"[tid: %i]: Suspending Thread Context.\n", tid);
684    bool deallocated = deallocateContext(tid, false, 1);
685    // If this was the last thread then unschedule the tick event.
686    if ((activeThreads.size() == 1 && !deallocated) ||
687        activeThreads.size() == 0)
688        unscheduleTickEvent();
689    _status = Idle;
690}
691
692template <class Impl>
693void
694FullO3CPU<Impl>::haltContext(int tid)
695{
696    //For now, this is the same as deallocate
697    DPRINTF(O3CPU,"[tid:%i]: Halt Context called. Deallocating", tid);
698    deallocateContext(tid, true, 1);
699}
700
701template <class Impl>
702void
703FullO3CPU<Impl>::insertThread(unsigned tid)
704{
705    DPRINTF(O3CPU,"[tid:%i] Initializing thread into CPU");
706    // Will change now that the PC and thread state is internal to the CPU
707    // and not in the ThreadContext.
708#if FULL_SYSTEM
709    ThreadContext *src_tc = system->threadContexts[tid];
710#else
711    ThreadContext *src_tc = tcBase(tid);
712#endif
713
714    //Bind Int Regs to Rename Map
715    for (int ireg = 0; ireg < TheISA::NumIntRegs; ireg++) {
716        PhysRegIndex phys_reg = freeList.getIntReg();
717
718        renameMap[tid].setEntry(ireg,phys_reg);
719        scoreboard.setReg(phys_reg);
720    }
721
722    //Bind Float Regs to Rename Map
723    for (int freg = 0; freg < TheISA::NumFloatRegs; freg++) {
724        PhysRegIndex phys_reg = freeList.getFloatReg();
725
726        renameMap[tid].setEntry(freg,phys_reg);
727        scoreboard.setReg(phys_reg);
728    }
729
730    //Copy Thread Data Into RegFile
731    //this->copyFromTC(tid);
732
733    //Set PC/NPC/NNPC
734    setPC(src_tc->readPC(), tid);
735    setNextPC(src_tc->readNextPC(), tid);
736    setNextNPC(src_tc->readNextNPC(), tid);
737
738    src_tc->setStatus(ThreadContext::Active);
739
740    activateContext(tid,1);
741
742    //Reset ROB/IQ/LSQ Entries
743    commit.rob->resetEntries();
744    iew.resetEntries();
745}
746
747template <class Impl>
748void
749FullO3CPU<Impl>::removeThread(unsigned tid)
750{
751    DPRINTF(O3CPU,"[tid:%i] Removing thread context from CPU.\n", tid);
752
753    // Copy Thread Data From RegFile
754    // If thread is suspended, it might be re-allocated
755    // this->copyToTC(tid);
756
757
758    // @todo: 2-27-2008: Fix how we free up rename mappings
759    // here to alleviate the case for double-freeing registers
760    // in SMT workloads.
761
762    // Unbind Int Regs from Rename Map
763    for (int ireg = 0; ireg < TheISA::NumIntRegs; ireg++) {
764        PhysRegIndex phys_reg = renameMap[tid].lookup(ireg);
765
766        scoreboard.unsetReg(phys_reg);
767        freeList.addReg(phys_reg);
768    }
769
770    // Unbind Float Regs from Rename Map
771    for (int freg = TheISA::NumIntRegs; freg < TheISA::NumFloatRegs; freg++) {
772        PhysRegIndex phys_reg = renameMap[tid].lookup(freg);
773
774        scoreboard.unsetReg(phys_reg);
775        freeList.addReg(phys_reg);
776    }
777
778    // Squash Throughout Pipeline
779    InstSeqNum squash_seq_num = commit.rob->readHeadInst(tid)->seqNum;
780    fetch.squash(0, sizeof(TheISA::MachInst), 0, squash_seq_num, tid);
781    decode.squash(tid);
782    rename.squash(squash_seq_num, tid);
783    iew.squash(tid);
784    iew.ldstQueue.squash(squash_seq_num, tid);
785    commit.rob->squash(squash_seq_num, tid);
786
787
788    assert(iew.instQueue.getCount(tid) == 0);
789    assert(iew.ldstQueue.getCount(tid) == 0);
790
791    // Reset ROB/IQ/LSQ Entries
792
793    // Commented out for now.  This should be possible to do by
794    // telling all the pipeline stages to drain first, and then
795    // checking until the drain completes.  Once the pipeline is
796    // drained, call resetEntries(). - 10-09-06 ktlim
797/*
798    if (activeThreads.size() >= 1) {
799        commit.rob->resetEntries();
800        iew.resetEntries();
801    }
802*/
803}
804
805
806template <class Impl>
807void
808FullO3CPU<Impl>::activateWhenReady(int tid)
809{
810    DPRINTF(O3CPU,"[tid:%i]: Checking if resources are available for incoming"
811            "(e.g. PhysRegs/ROB/IQ/LSQ) \n",
812            tid);
813
814    bool ready = true;
815
816    if (freeList.numFreeIntRegs() >= TheISA::NumIntRegs) {
817        DPRINTF(O3CPU,"[tid:%i] Suspending thread due to not enough "
818                "Phys. Int. Regs.\n",
819                tid);
820        ready = false;
821    } else if (freeList.numFreeFloatRegs() >= TheISA::NumFloatRegs) {
822        DPRINTF(O3CPU,"[tid:%i] Suspending thread due to not enough "
823                "Phys. Float. Regs.\n",
824                tid);
825        ready = false;
826    } else if (commit.rob->numFreeEntries() >=
827               commit.rob->entryAmount(activeThreads.size() + 1)) {
828        DPRINTF(O3CPU,"[tid:%i] Suspending thread due to not enough "
829                "ROB entries.\n",
830                tid);
831        ready = false;
832    } else if (iew.instQueue.numFreeEntries() >=
833               iew.instQueue.entryAmount(activeThreads.size() + 1)) {
834        DPRINTF(O3CPU,"[tid:%i] Suspending thread due to not enough "
835                "IQ entries.\n",
836                tid);
837        ready = false;
838    } else if (iew.ldstQueue.numFreeEntries() >=
839               iew.ldstQueue.entryAmount(activeThreads.size() + 1)) {
840        DPRINTF(O3CPU,"[tid:%i] Suspending thread due to not enough "
841                "LSQ entries.\n",
842                tid);
843        ready = false;
844    }
845
846    if (ready) {
847        insertThread(tid);
848
849        contextSwitch = false;
850
851        cpuWaitList.remove(tid);
852    } else {
853        suspendContext(tid);
854
855        //blocks fetch
856        contextSwitch = true;
857
858        //@todo: dont always add to waitlist
859        //do waitlist
860        cpuWaitList.push_back(tid);
861    }
862}
863
864#if FULL_SYSTEM
865template <class Impl>
866Fault
867FullO3CPU<Impl>::hwrei(unsigned tid)
868{
869#if THE_ISA == ALPHA_ISA
870    // Need to clear the lock flag upon returning from an interrupt.
871    this->setMiscRegNoEffect(AlphaISA::MISCREG_LOCKFLAG, false, tid);
872
873    this->thread[tid]->kernelStats->hwrei();
874
875    // FIXME: XXX check for interrupts? XXX
876#endif
877    return NoFault;
878}
879
880template <class Impl>
881bool
882FullO3CPU<Impl>::simPalCheck(int palFunc, unsigned tid)
883{
884#if THE_ISA == ALPHA_ISA
885    if (this->thread[tid]->kernelStats)
886        this->thread[tid]->kernelStats->callpal(palFunc,
887                                                this->threadContexts[tid]);
888
889    switch (palFunc) {
890      case PAL::halt:
891        halt();
892        if (--System::numSystemsRunning == 0)
893            exitSimLoop("all cpus halted");
894        break;
895
896      case PAL::bpt:
897      case PAL::bugchk:
898        if (this->system->breakpoint())
899            return false;
900        break;
901    }
902#endif
903    return true;
904}
905
906template <class Impl>
907Fault
908FullO3CPU<Impl>::getInterrupts()
909{
910    // Check if there are any outstanding interrupts
911    return this->interrupts->getInterrupt(this->threadContexts[0]);
912}
913
914template <class Impl>
915void
916FullO3CPU<Impl>::processInterrupts(Fault interrupt)
917{
918    // Check for interrupts here.  For now can copy the code that
919    // exists within isa_fullsys_traits.hh.  Also assume that thread 0
920    // is the one that handles the interrupts.
921    // @todo: Possibly consolidate the interrupt checking code.
922    // @todo: Allow other threads to handle interrupts.
923
924    assert(interrupt != NoFault);
925    this->interrupts->updateIntrInfo(this->threadContexts[0]);
926
927    DPRINTF(O3CPU, "Interrupt %s being handled\n", interrupt->name());
928    this->trap(interrupt, 0);
929}
930
931template <class Impl>
932void
933FullO3CPU<Impl>::updateMemPorts()
934{
935    // Update all ThreadContext's memory ports (Functional/Virtual
936    // Ports)
937    for (int i = 0; i < thread.size(); ++i)
938        thread[i]->connectMemPorts(thread[i]->getTC());
939}
940#endif
941
942template <class Impl>
943void
944FullO3CPU<Impl>::trap(Fault fault, unsigned tid)
945{
946    // Pass the thread's TC into the invoke method.
947    fault->invoke(this->threadContexts[tid]);
948}
949
950#if !FULL_SYSTEM
951
952template <class Impl>
953void
954FullO3CPU<Impl>::syscall(int64_t callnum, int tid)
955{
956    DPRINTF(O3CPU, "[tid:%i] Executing syscall().\n\n", tid);
957
958    DPRINTF(Activity,"Activity: syscall() called.\n");
959
960    // Temporarily increase this by one to account for the syscall
961    // instruction.
962    ++(this->thread[tid]->funcExeInst);
963
964    // Execute the actual syscall.
965    this->thread[tid]->syscall(callnum);
966
967    // Decrease funcExeInst by one as the normal commit will handle
968    // incrementing it.
969    --(this->thread[tid]->funcExeInst);
970}
971
972#endif
973
974template <class Impl>
975void
976FullO3CPU<Impl>::serialize(std::ostream &os)
977{
978    SimObject::State so_state = SimObject::getState();
979    SERIALIZE_ENUM(so_state);
980    BaseCPU::serialize(os);
981    nameOut(os, csprintf("%s.tickEvent", name()));
982    tickEvent.serialize(os);
983
984    // Use SimpleThread's ability to checkpoint to make it easier to
985    // write out the registers.  Also make this static so it doesn't
986    // get instantiated multiple times (causes a panic in statistics).
987    static SimpleThread temp;
988
989    for (int i = 0; i < thread.size(); i++) {
990        nameOut(os, csprintf("%s.xc.%i", name(), i));
991        temp.copyTC(thread[i]->getTC());
992        temp.serialize(os);
993    }
994}
995
996template <class Impl>
997void
998FullO3CPU<Impl>::unserialize(Checkpoint *cp, const std::string &section)
999{
1000    SimObject::State so_state;
1001    UNSERIALIZE_ENUM(so_state);
1002    BaseCPU::unserialize(cp, section);
1003    tickEvent.unserialize(cp, csprintf("%s.tickEvent", section));
1004
1005    // Use SimpleThread's ability to checkpoint to make it easier to
1006    // read in the registers.  Also make this static so it doesn't
1007    // get instantiated multiple times (causes a panic in statistics).
1008    static SimpleThread temp;
1009
1010    for (int i = 0; i < thread.size(); i++) {
1011        temp.copyTC(thread[i]->getTC());
1012        temp.unserialize(cp, csprintf("%s.xc.%i", section, i));
1013        thread[i]->getTC()->copyArchRegs(temp.getTC());
1014    }
1015}
1016
1017template <class Impl>
1018unsigned int
1019FullO3CPU<Impl>::drain(Event *drain_event)
1020{
1021    DPRINTF(O3CPU, "Switching out\n");
1022
1023    // If the CPU isn't doing anything, then return immediately.
1024    if (_status == Idle || _status == SwitchedOut) {
1025        return 0;
1026    }
1027
1028    drainCount = 0;
1029    fetch.drain();
1030    decode.drain();
1031    rename.drain();
1032    iew.drain();
1033    commit.drain();
1034
1035    // Wake the CPU and record activity so everything can drain out if
1036    // the CPU was not able to immediately drain.
1037    if (getState() != SimObject::Drained) {
1038        // A bit of a hack...set the drainEvent after all the drain()
1039        // calls have been made, that way if all of the stages drain
1040        // immediately, the signalDrained() function knows not to call
1041        // process on the drain event.
1042        drainEvent = drain_event;
1043
1044        wakeCPU();
1045        activityRec.activity();
1046
1047        return 1;
1048    } else {
1049        return 0;
1050    }
1051}
1052
1053template <class Impl>
1054void
1055FullO3CPU<Impl>::resume()
1056{
1057    fetch.resume();
1058    decode.resume();
1059    rename.resume();
1060    iew.resume();
1061    commit.resume();
1062
1063    changeState(SimObject::Running);
1064
1065    if (_status == SwitchedOut || _status == Idle)
1066        return;
1067
1068#if FULL_SYSTEM
1069    assert(system->getMemoryMode() == Enums::timing);
1070#endif
1071
1072    if (!tickEvent.scheduled())
1073        schedule(tickEvent, nextCycle());
1074    _status = Running;
1075}
1076
1077template <class Impl>
1078void
1079FullO3CPU<Impl>::signalDrained()
1080{
1081    if (++drainCount == NumStages) {
1082        if (tickEvent.scheduled())
1083            tickEvent.squash();
1084
1085        changeState(SimObject::Drained);
1086
1087        BaseCPU::switchOut();
1088
1089        if (drainEvent) {
1090            drainEvent->process();
1091            drainEvent = NULL;
1092        }
1093    }
1094    assert(drainCount <= 5);
1095}
1096
1097template <class Impl>
1098void
1099FullO3CPU<Impl>::switchOut()
1100{
1101    fetch.switchOut();
1102    rename.switchOut();
1103    iew.switchOut();
1104    commit.switchOut();
1105    instList.clear();
1106    while (!removeList.empty()) {
1107        removeList.pop();
1108    }
1109
1110    _status = SwitchedOut;
1111#if USE_CHECKER
1112    if (checker)
1113        checker->switchOut();
1114#endif
1115    if (tickEvent.scheduled())
1116        tickEvent.squash();
1117}
1118
1119template <class Impl>
1120void
1121FullO3CPU<Impl>::takeOverFrom(BaseCPU *oldCPU)
1122{
1123    // Flush out any old data from the time buffers.
1124    for (int i = 0; i < timeBuffer.getSize(); ++i) {
1125        timeBuffer.advance();
1126        fetchQueue.advance();
1127        decodeQueue.advance();
1128        renameQueue.advance();
1129        iewQueue.advance();
1130    }
1131
1132    activityRec.reset();
1133
1134    BaseCPU::takeOverFrom(oldCPU, fetch.getIcachePort(), iew.getDcachePort());
1135
1136    fetch.takeOverFrom();
1137    decode.takeOverFrom();
1138    rename.takeOverFrom();
1139    iew.takeOverFrom();
1140    commit.takeOverFrom();
1141
1142    assert(!tickEvent.scheduled());
1143
1144    // @todo: Figure out how to properly select the tid to put onto
1145    // the active threads list.
1146    int tid = 0;
1147
1148    std::list<unsigned>::iterator isActive =
1149        std::find(activeThreads.begin(), activeThreads.end(), tid);
1150
1151    if (isActive == activeThreads.end()) {
1152        //May Need to Re-code this if the delay variable is the delay
1153        //needed for thread to activate
1154        DPRINTF(O3CPU, "Adding Thread %i to active threads list\n",
1155                tid);
1156
1157        activeThreads.push_back(tid);
1158    }
1159
1160    // Set all statuses to active, schedule the CPU's tick event.
1161    // @todo: Fix up statuses so this is handled properly
1162    for (int i = 0; i < threadContexts.size(); ++i) {
1163        ThreadContext *tc = threadContexts[i];
1164        if (tc->status() == ThreadContext::Active && _status != Running) {
1165            _status = Running;
1166            schedule(tickEvent, nextCycle());
1167        }
1168    }
1169    if (!tickEvent.scheduled())
1170        schedule(tickEvent, nextCycle());
1171}
1172
1173template <class Impl>
1174TheISA::MiscReg
1175FullO3CPU<Impl>::readMiscRegNoEffect(int misc_reg, unsigned tid)
1176{
1177    return this->regFile.readMiscRegNoEffect(misc_reg, tid);
1178}
1179
1180template <class Impl>
1181TheISA::MiscReg
1182FullO3CPU<Impl>::readMiscReg(int misc_reg, unsigned tid)
1183{
1184    return this->regFile.readMiscReg(misc_reg, tid);
1185}
1186
1187template <class Impl>
1188void
1189FullO3CPU<Impl>::setMiscRegNoEffect(int misc_reg,
1190        const TheISA::MiscReg &val, unsigned tid)
1191{
1192    this->regFile.setMiscRegNoEffect(misc_reg, val, tid);
1193}
1194
1195template <class Impl>
1196void
1197FullO3CPU<Impl>::setMiscReg(int misc_reg,
1198        const TheISA::MiscReg &val, unsigned tid)
1199{
1200    this->regFile.setMiscReg(misc_reg, val, tid);
1201}
1202
1203template <class Impl>
1204uint64_t
1205FullO3CPU<Impl>::readIntReg(int reg_idx)
1206{
1207    return regFile.readIntReg(reg_idx);
1208}
1209
1210template <class Impl>
1211FloatReg
1212FullO3CPU<Impl>::readFloatReg(int reg_idx, int width)
1213{
1214    return regFile.readFloatReg(reg_idx, width);
1215}
1216
1217template <class Impl>
1218FloatReg
1219FullO3CPU<Impl>::readFloatReg(int reg_idx)
1220{
1221    return regFile.readFloatReg(reg_idx);
1222}
1223
1224template <class Impl>
1225FloatRegBits
1226FullO3CPU<Impl>::readFloatRegBits(int reg_idx, int width)
1227{
1228    return regFile.readFloatRegBits(reg_idx, width);
1229}
1230
1231template <class Impl>
1232FloatRegBits
1233FullO3CPU<Impl>::readFloatRegBits(int reg_idx)
1234{
1235    return regFile.readFloatRegBits(reg_idx);
1236}
1237
1238template <class Impl>
1239void
1240FullO3CPU<Impl>::setIntReg(int reg_idx, uint64_t val)
1241{
1242    regFile.setIntReg(reg_idx, val);
1243}
1244
1245template <class Impl>
1246void
1247FullO3CPU<Impl>::setFloatReg(int reg_idx, FloatReg val, int width)
1248{
1249    regFile.setFloatReg(reg_idx, val, width);
1250}
1251
1252template <class Impl>
1253void
1254FullO3CPU<Impl>::setFloatReg(int reg_idx, FloatReg val)
1255{
1256    regFile.setFloatReg(reg_idx, val);
1257}
1258
1259template <class Impl>
1260void
1261FullO3CPU<Impl>::setFloatRegBits(int reg_idx, FloatRegBits val, int width)
1262{
1263    regFile.setFloatRegBits(reg_idx, val, width);
1264}
1265
1266template <class Impl>
1267void
1268FullO3CPU<Impl>::setFloatRegBits(int reg_idx, FloatRegBits val)
1269{
1270    regFile.setFloatRegBits(reg_idx, val);
1271}
1272
1273template <class Impl>
1274uint64_t
1275FullO3CPU<Impl>::readArchIntReg(int reg_idx, unsigned tid)
1276{
1277    PhysRegIndex phys_reg = commitRenameMap[tid].lookup(reg_idx);
1278
1279    return regFile.readIntReg(phys_reg);
1280}
1281
1282template <class Impl>
1283float
1284FullO3CPU<Impl>::readArchFloatRegSingle(int reg_idx, unsigned tid)
1285{
1286    int idx = reg_idx + TheISA::NumIntRegs;
1287    PhysRegIndex phys_reg = commitRenameMap[tid].lookup(idx);
1288
1289    return regFile.readFloatReg(phys_reg);
1290}
1291
1292template <class Impl>
1293double
1294FullO3CPU<Impl>::readArchFloatRegDouble(int reg_idx, unsigned tid)
1295{
1296    int idx = reg_idx + TheISA::NumIntRegs;
1297    PhysRegIndex phys_reg = commitRenameMap[tid].lookup(idx);
1298
1299    return regFile.readFloatReg(phys_reg, 64);
1300}
1301
1302template <class Impl>
1303uint64_t
1304FullO3CPU<Impl>::readArchFloatRegInt(int reg_idx, unsigned tid)
1305{
1306    int idx = reg_idx + TheISA::NumIntRegs;
1307    PhysRegIndex phys_reg = commitRenameMap[tid].lookup(idx);
1308
1309    return regFile.readFloatRegBits(phys_reg);
1310}
1311
1312template <class Impl>
1313void
1314FullO3CPU<Impl>::setArchIntReg(int reg_idx, uint64_t val, unsigned tid)
1315{
1316    PhysRegIndex phys_reg = commitRenameMap[tid].lookup(reg_idx);
1317
1318    regFile.setIntReg(phys_reg, val);
1319}
1320
1321template <class Impl>
1322void
1323FullO3CPU<Impl>::setArchFloatRegSingle(int reg_idx, float val, unsigned tid)
1324{
1325    int idx = reg_idx + TheISA::NumIntRegs;
1326    PhysRegIndex phys_reg = commitRenameMap[tid].lookup(idx);
1327
1328    regFile.setFloatReg(phys_reg, val);
1329}
1330
1331template <class Impl>
1332void
1333FullO3CPU<Impl>::setArchFloatRegDouble(int reg_idx, double val, unsigned tid)
1334{
1335    int idx = reg_idx + TheISA::NumIntRegs;
1336    PhysRegIndex phys_reg = commitRenameMap[tid].lookup(idx);
1337
1338    regFile.setFloatReg(phys_reg, val, 64);
1339}
1340
1341template <class Impl>
1342void
1343FullO3CPU<Impl>::setArchFloatRegInt(int reg_idx, uint64_t val, unsigned tid)
1344{
1345    int idx = reg_idx + TheISA::NumIntRegs;
1346    PhysRegIndex phys_reg = commitRenameMap[tid].lookup(idx);
1347
1348    regFile.setFloatRegBits(phys_reg, val);
1349}
1350
1351template <class Impl>
1352uint64_t
1353FullO3CPU<Impl>::readPC(unsigned tid)
1354{
1355    return commit.readPC(tid);
1356}
1357
1358template <class Impl>
1359void
1360FullO3CPU<Impl>::setPC(Addr new_PC,unsigned tid)
1361{
1362    commit.setPC(new_PC, tid);
1363}
1364
1365template <class Impl>
1366uint64_t
1367FullO3CPU<Impl>::readMicroPC(unsigned tid)
1368{
1369    return commit.readMicroPC(tid);
1370}
1371
1372template <class Impl>
1373void
1374FullO3CPU<Impl>::setMicroPC(Addr new_PC,unsigned tid)
1375{
1376    commit.setMicroPC(new_PC, tid);
1377}
1378
1379template <class Impl>
1380uint64_t
1381FullO3CPU<Impl>::readNextPC(unsigned tid)
1382{
1383    return commit.readNextPC(tid);
1384}
1385
1386template <class Impl>
1387void
1388FullO3CPU<Impl>::setNextPC(uint64_t val,unsigned tid)
1389{
1390    commit.setNextPC(val, tid);
1391}
1392
1393template <class Impl>
1394uint64_t
1395FullO3CPU<Impl>::readNextNPC(unsigned tid)
1396{
1397    return commit.readNextNPC(tid);
1398}
1399
1400template <class Impl>
1401void
1402FullO3CPU<Impl>::setNextNPC(uint64_t val,unsigned tid)
1403{
1404    commit.setNextNPC(val, tid);
1405}
1406
1407template <class Impl>
1408uint64_t
1409FullO3CPU<Impl>::readNextMicroPC(unsigned tid)
1410{
1411    return commit.readNextMicroPC(tid);
1412}
1413
1414template <class Impl>
1415void
1416FullO3CPU<Impl>::setNextMicroPC(Addr new_PC,unsigned tid)
1417{
1418    commit.setNextMicroPC(new_PC, tid);
1419}
1420
1421template <class Impl>
1422void
1423FullO3CPU<Impl>::squashFromTC(unsigned tid)
1424{
1425    this->thread[tid]->inSyscall = true;
1426    this->commit.generateTCEvent(tid);
1427}
1428
1429template <class Impl>
1430typename FullO3CPU<Impl>::ListIt
1431FullO3CPU<Impl>::addInst(DynInstPtr &inst)
1432{
1433    instList.push_back(inst);
1434
1435    return --(instList.end());
1436}
1437
1438template <class Impl>
1439void
1440FullO3CPU<Impl>::instDone(unsigned tid)
1441{
1442    // Keep an instruction count.
1443    thread[tid]->numInst++;
1444    thread[tid]->numInsts++;
1445    committedInsts[tid]++;
1446    totalCommittedInsts++;
1447
1448    // Check for instruction-count-based events.
1449    comInstEventQueue[tid]->serviceEvents(thread[tid]->numInst);
1450}
1451
1452template <class Impl>
1453void
1454FullO3CPU<Impl>::addToRemoveList(DynInstPtr &inst)
1455{
1456    removeInstsThisCycle = true;
1457
1458    removeList.push(inst->getInstListIt());
1459}
1460
1461template <class Impl>
1462void
1463FullO3CPU<Impl>::removeFrontInst(DynInstPtr &inst)
1464{
1465    DPRINTF(O3CPU, "Removing committed instruction [tid:%i] PC %#x "
1466            "[sn:%lli]\n",
1467            inst->threadNumber, inst->readPC(), inst->seqNum);
1468
1469    removeInstsThisCycle = true;
1470
1471    // Remove the front instruction.
1472    removeList.push(inst->getInstListIt());
1473}
1474
1475template <class Impl>
1476void
1477FullO3CPU<Impl>::removeInstsNotInROB(unsigned tid)
1478{
1479    DPRINTF(O3CPU, "Thread %i: Deleting instructions from instruction"
1480            " list.\n", tid);
1481
1482    ListIt end_it;
1483
1484    bool rob_empty = false;
1485
1486    if (instList.empty()) {
1487        return;
1488    } else if (rob.isEmpty(/*tid*/)) {
1489        DPRINTF(O3CPU, "ROB is empty, squashing all insts.\n");
1490        end_it = instList.begin();
1491        rob_empty = true;
1492    } else {
1493        end_it = (rob.readTailInst(tid))->getInstListIt();
1494        DPRINTF(O3CPU, "ROB is not empty, squashing insts not in ROB.\n");
1495    }
1496
1497    removeInstsThisCycle = true;
1498
1499    ListIt inst_it = instList.end();
1500
1501    inst_it--;
1502
1503    // Walk through the instruction list, removing any instructions
1504    // that were inserted after the given instruction iterator, end_it.
1505    while (inst_it != end_it) {
1506        assert(!instList.empty());
1507
1508        squashInstIt(inst_it, tid);
1509
1510        inst_it--;
1511    }
1512
1513    // If the ROB was empty, then we actually need to remove the first
1514    // instruction as well.
1515    if (rob_empty) {
1516        squashInstIt(inst_it, tid);
1517    }
1518}
1519
1520template <class Impl>
1521void
1522FullO3CPU<Impl>::removeInstsUntil(const InstSeqNum &seq_num,
1523                                  unsigned tid)
1524{
1525    assert(!instList.empty());
1526
1527    removeInstsThisCycle = true;
1528
1529    ListIt inst_iter = instList.end();
1530
1531    inst_iter--;
1532
1533    DPRINTF(O3CPU, "Deleting instructions from instruction "
1534            "list that are from [tid:%i] and above [sn:%lli] (end=%lli).\n",
1535            tid, seq_num, (*inst_iter)->seqNum);
1536
1537    while ((*inst_iter)->seqNum > seq_num) {
1538
1539        bool break_loop = (inst_iter == instList.begin());
1540
1541        squashInstIt(inst_iter, tid);
1542
1543        inst_iter--;
1544
1545        if (break_loop)
1546            break;
1547    }
1548}
1549
1550template <class Impl>
1551inline void
1552FullO3CPU<Impl>::squashInstIt(const ListIt &instIt, const unsigned &tid)
1553{
1554    if ((*instIt)->threadNumber == tid) {
1555        DPRINTF(O3CPU, "Squashing instruction, "
1556                "[tid:%i] [sn:%lli] PC %#x\n",
1557                (*instIt)->threadNumber,
1558                (*instIt)->seqNum,
1559                (*instIt)->readPC());
1560
1561        // Mark it as squashed.
1562        (*instIt)->setSquashed();
1563
1564        // @todo: Formulate a consistent method for deleting
1565        // instructions from the instruction list
1566        // Remove the instruction from the list.
1567        removeList.push(instIt);
1568    }
1569}
1570
1571template <class Impl>
1572void
1573FullO3CPU<Impl>::cleanUpRemovedInsts()
1574{
1575    while (!removeList.empty()) {
1576        DPRINTF(O3CPU, "Removing instruction, "
1577                "[tid:%i] [sn:%lli] PC %#x\n",
1578                (*removeList.front())->threadNumber,
1579                (*removeList.front())->seqNum,
1580                (*removeList.front())->readPC());
1581
1582        instList.erase(removeList.front());
1583
1584        removeList.pop();
1585    }
1586
1587    removeInstsThisCycle = false;
1588}
1589/*
1590template <class Impl>
1591void
1592FullO3CPU<Impl>::removeAllInsts()
1593{
1594    instList.clear();
1595}
1596*/
1597template <class Impl>
1598void
1599FullO3CPU<Impl>::dumpInsts()
1600{
1601    int num = 0;
1602
1603    ListIt inst_list_it = instList.begin();
1604
1605    cprintf("Dumping Instruction List\n");
1606
1607    while (inst_list_it != instList.end()) {
1608        cprintf("Instruction:%i\nPC:%#x\n[tid:%i]\n[sn:%lli]\nIssued:%i\n"
1609                "Squashed:%i\n\n",
1610                num, (*inst_list_it)->readPC(), (*inst_list_it)->threadNumber,
1611                (*inst_list_it)->seqNum, (*inst_list_it)->isIssued(),
1612                (*inst_list_it)->isSquashed());
1613        inst_list_it++;
1614        ++num;
1615    }
1616}
1617/*
1618template <class Impl>
1619void
1620FullO3CPU<Impl>::wakeDependents(DynInstPtr &inst)
1621{
1622    iew.wakeDependents(inst);
1623}
1624*/
1625template <class Impl>
1626void
1627FullO3CPU<Impl>::wakeCPU()
1628{
1629    if (activityRec.active() || tickEvent.scheduled()) {
1630        DPRINTF(Activity, "CPU already running.\n");
1631        return;
1632    }
1633
1634    DPRINTF(Activity, "Waking up CPU\n");
1635
1636    idleCycles += tickToCycles((curTick - 1) - lastRunningCycle);
1637    numCycles += tickToCycles((curTick - 1) - lastRunningCycle);
1638
1639    schedule(tickEvent, nextCycle());
1640}
1641
1642#if FULL_SYSTEM
1643template <class Impl>
1644void
1645FullO3CPU<Impl>::wakeup()
1646{
1647    if (this->thread[0]->status() != ThreadContext::Suspended)
1648        return;
1649
1650    this->wakeCPU();
1651
1652    DPRINTF(Quiesce, "Suspended Processor woken\n");
1653    this->threadContexts[0]->activate();
1654}
1655#endif
1656
1657template <class Impl>
1658int
1659FullO3CPU<Impl>::getFreeTid()
1660{
1661    for (int i=0; i < numThreads; i++) {
1662        if (!tids[i]) {
1663            tids[i] = true;
1664            return i;
1665        }
1666    }
1667
1668    return -1;
1669}
1670
1671template <class Impl>
1672void
1673FullO3CPU<Impl>::doContextSwitch()
1674{
1675    if (contextSwitch) {
1676
1677        //ADD CODE TO DEACTIVE THREAD HERE (???)
1678
1679        for (int tid=0; tid < cpuWaitList.size(); tid++) {
1680            activateWhenReady(tid);
1681        }
1682
1683        if (cpuWaitList.size() == 0)
1684            contextSwitch = true;
1685    }
1686}
1687
1688template <class Impl>
1689void
1690FullO3CPU<Impl>::updateThreadPriority()
1691{
1692    if (activeThreads.size() > 1)
1693    {
1694        //DEFAULT TO ROUND ROBIN SCHEME
1695        //e.g. Move highest priority to end of thread list
1696        std::list<unsigned>::iterator list_begin = activeThreads.begin();
1697        std::list<unsigned>::iterator list_end   = activeThreads.end();
1698
1699        unsigned high_thread = *list_begin;
1700
1701        activeThreads.erase(list_begin);
1702
1703        activeThreads.push_back(high_thread);
1704    }
1705}
1706
1707// Forward declaration of FullO3CPU.
1708template class FullO3CPU<O3CPUImpl>;
1709