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