cpu.cc revision 2733
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 */
30
31#include "config/full_system.hh"
32#include "config/use_checker.hh"
33
34#if FULL_SYSTEM
35#include "sim/system.hh"
36#else
37#include "sim/process.hh"
38#endif
39
40#include "cpu/activity.hh"
41#include "cpu/checker/cpu.hh"
42#include "cpu/simple_thread.hh"
43#include "cpu/thread_context.hh"
44#include "cpu/o3/alpha_dyn_inst.hh"
45#include "cpu/o3/alpha_impl.hh"
46#include "cpu/o3/cpu.hh"
47
48#include "sim/root.hh"
49#include "sim/stat_control.hh"
50
51using namespace std;
52using namespace TheISA;
53
54BaseO3CPU::BaseO3CPU(Params *params)
55    : BaseCPU(params), cpu_id(0)
56{
57}
58
59void
60BaseO3CPU::regStats()
61{
62    BaseCPU::regStats();
63}
64
65template <class Impl>
66FullO3CPU<Impl>::TickEvent::TickEvent(FullO3CPU<Impl> *c)
67    : Event(&mainEventQueue, CPU_Tick_Pri), cpu(c)
68{
69}
70
71template <class Impl>
72void
73FullO3CPU<Impl>::TickEvent::process()
74{
75    cpu->tick();
76}
77
78template <class Impl>
79const char *
80FullO3CPU<Impl>::TickEvent::description()
81{
82    return "FullO3CPU tick event";
83}
84
85template <class Impl>
86FullO3CPU<Impl>::FullO3CPU(Params *params)
87    : BaseO3CPU(params),
88      tickEvent(this),
89      removeInstsThisCycle(false),
90      fetch(params),
91      decode(params),
92      rename(params),
93      iew(params),
94      commit(params),
95
96      regFile(params->numPhysIntRegs, params->numPhysFloatRegs),
97
98      freeList(params->numberOfThreads,//number of activeThreads
99               TheISA::NumIntRegs, params->numPhysIntRegs,
100               TheISA::NumFloatRegs, params->numPhysFloatRegs),
101
102      rob(params->numROBEntries, params->squashWidth,
103          params->smtROBPolicy, params->smtROBThreshold,
104          params->numberOfThreads),
105
106      scoreboard(params->numberOfThreads,//number of activeThreads
107                 TheISA::NumIntRegs, params->numPhysIntRegs,
108                 TheISA::NumFloatRegs, params->numPhysFloatRegs,
109                 TheISA::NumMiscRegs * number_of_threads,
110                 TheISA::ZeroReg),
111
112      // For now just have these time buffers be pretty big.
113      // @todo: Make these time buffer sizes parameters or derived
114      // from latencies
115      timeBuffer(5, 5),
116      fetchQueue(5, 5),
117      decodeQueue(5, 5),
118      renameQueue(5, 5),
119      iewQueue(5, 5),
120      activityRec(NumStages, 10, params->activity),
121
122      globalSeqNum(1),
123
124#if FULL_SYSTEM
125      system(params->system),
126      physmem(system->physmem),
127#endif // FULL_SYSTEM
128      mem(params->mem),
129      switchCount(0),
130      deferRegistration(params->deferRegistration),
131      numThreads(number_of_threads)
132{
133    _status = Idle;
134
135    checker = NULL;
136
137#if USE_CHECKER
138    if (params->checker) {
139        BaseCPU *temp_checker = params->checker;
140        checker = dynamic_cast<Checker<DynInstPtr> *>(temp_checker);
141        checker->setMemory(mem);
142#if FULL_SYSTEM
143        checker->setSystem(params->system);
144#endif
145    }
146#endif
147
148#if !FULL_SYSTEM
149    thread.resize(number_of_threads);
150    tids.resize(number_of_threads);
151#endif
152
153    // The stages also need their CPU pointer setup.  However this
154    // must be done at the upper level CPU because they have pointers
155    // to the upper level CPU, and not this FullO3CPU.
156
157    // Set up Pointers to the activeThreads list for each stage
158    fetch.setActiveThreads(&activeThreads);
159    decode.setActiveThreads(&activeThreads);
160    rename.setActiveThreads(&activeThreads);
161    iew.setActiveThreads(&activeThreads);
162    commit.setActiveThreads(&activeThreads);
163
164    // Give each of the stages the time buffer they will use.
165    fetch.setTimeBuffer(&timeBuffer);
166    decode.setTimeBuffer(&timeBuffer);
167    rename.setTimeBuffer(&timeBuffer);
168    iew.setTimeBuffer(&timeBuffer);
169    commit.setTimeBuffer(&timeBuffer);
170
171    // Also setup each of the stages' queues.
172    fetch.setFetchQueue(&fetchQueue);
173    decode.setFetchQueue(&fetchQueue);
174    commit.setFetchQueue(&fetchQueue);
175    decode.setDecodeQueue(&decodeQueue);
176    rename.setDecodeQueue(&decodeQueue);
177    rename.setRenameQueue(&renameQueue);
178    iew.setRenameQueue(&renameQueue);
179    iew.setIEWQueue(&iewQueue);
180    commit.setIEWQueue(&iewQueue);
181    commit.setRenameQueue(&renameQueue);
182
183    commit.setFetchStage(&fetch);
184    commit.setIEWStage(&iew);
185    rename.setIEWStage(&iew);
186    rename.setCommitStage(&commit);
187
188#if !FULL_SYSTEM
189    int active_threads = params->workload.size();
190#else
191    int active_threads = 1;
192#endif
193
194    //Make Sure That this a Valid Architeture
195    assert(params->numPhysIntRegs   >= numThreads * TheISA::NumIntRegs);
196    assert(params->numPhysFloatRegs >= numThreads * TheISA::NumFloatRegs);
197
198    rename.setScoreboard(&scoreboard);
199    iew.setScoreboard(&scoreboard);
200
201    // Setup the rename map for whichever stages need it.
202    PhysRegIndex lreg_idx = 0;
203    PhysRegIndex freg_idx = params->numPhysIntRegs; //Index to 1 after int regs
204
205    for (int tid=0; tid < numThreads; tid++) {
206        bool bindRegs = (tid <= active_threads - 1);
207
208        commitRenameMap[tid].init(TheISA::NumIntRegs,
209                                  params->numPhysIntRegs,
210                                  lreg_idx,            //Index for Logical. Regs
211
212                                  TheISA::NumFloatRegs,
213                                  params->numPhysFloatRegs,
214                                  freg_idx,            //Index for Float Regs
215
216                                  TheISA::NumMiscRegs,
217
218                                  TheISA::ZeroReg,
219                                  TheISA::ZeroReg,
220
221                                  tid,
222                                  false);
223
224        renameMap[tid].init(TheISA::NumIntRegs,
225                            params->numPhysIntRegs,
226                            lreg_idx,                  //Index for Logical. Regs
227
228                            TheISA::NumFloatRegs,
229                            params->numPhysFloatRegs,
230                            freg_idx,                  //Index for Float Regs
231
232                            TheISA::NumMiscRegs,
233
234                            TheISA::ZeroReg,
235                            TheISA::ZeroReg,
236
237                            tid,
238                            bindRegs);
239    }
240
241    rename.setRenameMap(renameMap);
242    commit.setRenameMap(commitRenameMap);
243
244    // Give renameMap & rename stage access to the freeList;
245    for (int i=0; i < numThreads; i++) {
246        renameMap[i].setFreeList(&freeList);
247    }
248    rename.setFreeList(&freeList);
249
250    // Setup the ROB for whichever stages need it.
251    commit.setROB(&rob);
252
253    lastRunningCycle = curTick;
254
255    contextSwitch = false;
256}
257
258template <class Impl>
259FullO3CPU<Impl>::~FullO3CPU()
260{
261}
262
263template <class Impl>
264void
265FullO3CPU<Impl>::fullCPURegStats()
266{
267    BaseO3CPU::regStats();
268
269    // Register any of the O3CPU's stats here.
270    timesIdled
271        .name(name() + ".timesIdled")
272        .desc("Number of times that the entire CPU went into an idle state and"
273              " unscheduled itself")
274        .prereq(timesIdled);
275
276    idleCycles
277        .name(name() + ".idleCycles")
278        .desc("Total number of cycles that the CPU has spent unscheduled due "
279              "to idling")
280        .prereq(idleCycles);
281
282    // Number of Instructions simulated
283    // --------------------------------
284    // Should probably be in Base CPU but need templated
285    // MaxThreads so put in here instead
286    committedInsts
287        .init(numThreads)
288        .name(name() + ".committedInsts")
289        .desc("Number of Instructions Simulated");
290
291    totalCommittedInsts
292        .name(name() + ".committedInsts_total")
293        .desc("Number of Instructions Simulated");
294
295    cpi
296        .name(name() + ".cpi")
297        .desc("CPI: Cycles Per Instruction")
298        .precision(6);
299    cpi = simTicks / committedInsts;
300
301    totalCpi
302        .name(name() + ".cpi_total")
303        .desc("CPI: Total CPI of All Threads")
304        .precision(6);
305    totalCpi = simTicks / totalCommittedInsts;
306
307    ipc
308        .name(name() + ".ipc")
309        .desc("IPC: Instructions Per Cycle")
310        .precision(6);
311    ipc =  committedInsts / simTicks;
312
313    totalIpc
314        .name(name() + ".ipc_total")
315        .desc("IPC: Total IPC of All Threads")
316        .precision(6);
317    totalIpc =  totalCommittedInsts / simTicks;
318
319}
320
321template <class Impl>
322void
323FullO3CPU<Impl>::tick()
324{
325    DPRINTF(O3CPU, "\n\nFullO3CPU: Ticking main, FullO3CPU.\n");
326
327    ++numCycles;
328
329//    activity = false;
330
331    //Tick each of the stages
332    fetch.tick();
333
334    decode.tick();
335
336    rename.tick();
337
338    iew.tick();
339
340    commit.tick();
341
342#if !FULL_SYSTEM
343    doContextSwitch();
344#endif
345
346    // Now advance the time buffers
347    timeBuffer.advance();
348
349    fetchQueue.advance();
350    decodeQueue.advance();
351    renameQueue.advance();
352    iewQueue.advance();
353
354    activityRec.advance();
355
356    if (removeInstsThisCycle) {
357        cleanUpRemovedInsts();
358    }
359
360    if (!tickEvent.scheduled()) {
361        if (_status == SwitchedOut) {
362            // increment stat
363            lastRunningCycle = curTick;
364        } else if (!activityRec.active()) {
365            lastRunningCycle = curTick;
366            timesIdled++;
367        } else {
368            tickEvent.schedule(curTick + cycles(1));
369        }
370    }
371
372#if !FULL_SYSTEM
373    updateThreadPriority();
374#endif
375
376}
377
378template <class Impl>
379void
380FullO3CPU<Impl>::init()
381{
382    if (!deferRegistration) {
383        registerThreadContexts();
384    }
385
386    // Set inSyscall so that the CPU doesn't squash when initially
387    // setting up registers.
388    for (int i = 0; i < number_of_threads; ++i)
389        thread[i]->inSyscall = true;
390
391    for (int tid=0; tid < number_of_threads; tid++) {
392#if FULL_SYSTEM
393        ThreadContext *src_tc = threadContexts[tid];
394#else
395        ThreadContext *src_tc = thread[tid]->getTC();
396#endif
397        // Threads start in the Suspended State
398        if (src_tc->status() != ThreadContext::Suspended) {
399            continue;
400        }
401
402#if FULL_SYSTEM
403        TheISA::initCPU(src_tc, src_tc->readCpuId());
404#endif
405    }
406
407    // Clear inSyscall.
408    for (int i = 0; i < number_of_threads; ++i)
409        thread[i]->inSyscall = false;
410
411    // Initialize stages.
412    fetch.initStage();
413    iew.initStage();
414    rename.initStage();
415    commit.initStage();
416
417    commit.setThreads(thread);
418}
419
420template <class Impl>
421void
422FullO3CPU<Impl>::insertThread(unsigned tid)
423{
424    DPRINTF(O3CPU,"[tid:%i] Initializing thread data");
425    // Will change now that the PC and thread state is internal to the CPU
426    // and not in the ThreadContext.
427#if 0
428#if FULL_SYSTEM
429    ThreadContext *src_tc = system->threadContexts[tid];
430#else
431    ThreadContext *src_tc = thread[tid];
432#endif
433
434    //Bind Int Regs to Rename Map
435    for (int ireg = 0; ireg < TheISA::NumIntRegs; ireg++) {
436        PhysRegIndex phys_reg = freeList.getIntReg();
437
438        renameMap[tid].setEntry(ireg,phys_reg);
439        scoreboard.setReg(phys_reg);
440    }
441
442    //Bind Float Regs to Rename Map
443    for (int freg = 0; freg < TheISA::NumFloatRegs; freg++) {
444        PhysRegIndex phys_reg = freeList.getFloatReg();
445
446        renameMap[tid].setEntry(freg,phys_reg);
447        scoreboard.setReg(phys_reg);
448    }
449
450    //Copy Thread Data Into RegFile
451    this->copyFromTC(tid);
452
453    //Set PC/NPC
454    regFile.pc[tid]  = src_tc->readPC();
455    regFile.npc[tid] = src_tc->readNextPC();
456
457    src_tc->setStatus(ThreadContext::Active);
458
459    activateContext(tid,1);
460
461    //Reset ROB/IQ/LSQ Entries
462    commit.rob->resetEntries();
463    iew.resetEntries();
464#endif
465}
466
467template <class Impl>
468void
469FullO3CPU<Impl>::removeThread(unsigned tid)
470{
471    DPRINTF(O3CPU,"[tid:%i] Removing thread data");
472#if 0
473    //Unbind Int Regs from Rename Map
474    for (int ireg = 0; ireg < TheISA::NumIntRegs; ireg++) {
475        PhysRegIndex phys_reg = renameMap[tid].lookup(ireg);
476
477        scoreboard.unsetReg(phys_reg);
478        freeList.addReg(phys_reg);
479    }
480
481    //Unbind Float Regs from Rename Map
482    for (int freg = 0; freg < TheISA::NumFloatRegs; freg++) {
483        PhysRegIndex phys_reg = renameMap[tid].lookup(freg);
484
485        scoreboard.unsetReg(phys_reg);
486        freeList.addReg(phys_reg);
487    }
488
489    //Copy Thread Data From RegFile
490    /* Fix Me:
491     * Do we really need to do this if we are removing a thread
492     * in the sense that it's finished (exiting)? If the thread is just
493     * being suspended we might...
494     */
495//    this->copyToTC(tid);
496
497    //Squash Throughout Pipeline
498    fetch.squash(0,tid);
499    decode.squash(tid);
500    rename.squash(tid);
501
502    assert(iew.ldstQueue.getCount(tid) == 0);
503
504    //Reset ROB/IQ/LSQ Entries
505    if (activeThreads.size() >= 1) {
506        commit.rob->resetEntries();
507        iew.resetEntries();
508    }
509#endif
510}
511
512
513template <class Impl>
514void
515FullO3CPU<Impl>::activateWhenReady(int tid)
516{
517    DPRINTF(O3CPU,"[tid:%i]: Checking if resources are available for incoming"
518            "(e.g. PhysRegs/ROB/IQ/LSQ) \n",
519            tid);
520
521    bool ready = true;
522
523    if (freeList.numFreeIntRegs() >= TheISA::NumIntRegs) {
524        DPRINTF(O3CPU,"[tid:%i] Suspending thread due to not enough "
525                "Phys. Int. Regs.\n",
526                tid);
527        ready = false;
528    } else if (freeList.numFreeFloatRegs() >= TheISA::NumFloatRegs) {
529        DPRINTF(O3CPU,"[tid:%i] Suspending thread due to not enough "
530                "Phys. Float. Regs.\n",
531                tid);
532        ready = false;
533    } else if (commit.rob->numFreeEntries() >=
534               commit.rob->entryAmount(activeThreads.size() + 1)) {
535        DPRINTF(O3CPU,"[tid:%i] Suspending thread due to not enough "
536                "ROB entries.\n",
537                tid);
538        ready = false;
539    } else if (iew.instQueue.numFreeEntries() >=
540               iew.instQueue.entryAmount(activeThreads.size() + 1)) {
541        DPRINTF(O3CPU,"[tid:%i] Suspending thread due to not enough "
542                "IQ entries.\n",
543                tid);
544        ready = false;
545    } else if (iew.ldstQueue.numFreeEntries() >=
546               iew.ldstQueue.entryAmount(activeThreads.size() + 1)) {
547        DPRINTF(O3CPU,"[tid:%i] Suspending thread due to not enough "
548                "LSQ entries.\n",
549                tid);
550        ready = false;
551    }
552
553    if (ready) {
554        insertThread(tid);
555
556        contextSwitch = false;
557
558        cpuWaitList.remove(tid);
559    } else {
560        suspendContext(tid);
561
562        //blocks fetch
563        contextSwitch = true;
564
565        //do waitlist
566        cpuWaitList.push_back(tid);
567    }
568}
569
570template <class Impl>
571void
572FullO3CPU<Impl>::activateContext(int tid, int delay)
573{
574    // Needs to set each stage to running as well.
575    list<unsigned>::iterator isActive = find(
576        activeThreads.begin(), activeThreads.end(), tid);
577
578    if (isActive == activeThreads.end()) {
579        //May Need to Re-code this if the delay variable is the
580        //delay needed for thread to activate
581        DPRINTF(O3CPU, "Adding Thread %i to active threads list\n",
582                tid);
583
584        activeThreads.push_back(tid);
585    }
586
587    assert(_status == Idle || _status == SwitchedOut);
588
589    scheduleTickEvent(delay);
590
591    // Be sure to signal that there's some activity so the CPU doesn't
592    // deschedule itself.
593    activityRec.activity();
594    fetch.wakeFromQuiesce();
595
596    _status = Running;
597}
598
599template <class Impl>
600void
601FullO3CPU<Impl>::suspendContext(int tid)
602{
603    DPRINTF(O3CPU,"[tid: %i]: Suspended ...\n", tid);
604    unscheduleTickEvent();
605    _status = Idle;
606/*
607    //Remove From Active List, if Active
608    list<unsigned>::iterator isActive = find(
609        activeThreads.begin(), activeThreads.end(), tid);
610
611    if (isActive != activeThreads.end()) {
612        DPRINTF(O3CPU,"[tid:%i]: Removing from active threads list\n",
613                tid);
614        activeThreads.erase(isActive);
615    }
616*/
617}
618
619template <class Impl>
620void
621FullO3CPU<Impl>::deallocateContext(int tid)
622{
623    DPRINTF(O3CPU,"[tid:%i]: Deallocating ...", tid);
624/*
625    //Remove From Active List, if Active
626    list<unsigned>::iterator isActive = find(
627        activeThreads.begin(), activeThreads.end(), tid);
628
629    if (isActive != activeThreads.end()) {
630        DPRINTF(O3CPU,"[tid:%i]: Removing from active threads list\n",
631                tid);
632        activeThreads.erase(isActive);
633
634        removeThread(tid);
635    }
636*/
637}
638
639template <class Impl>
640void
641FullO3CPU<Impl>::haltContext(int tid)
642{
643    DPRINTF(O3CPU,"[tid:%i]: Halted ...", tid);
644/*
645    //Remove From Active List, if Active
646    list<unsigned>::iterator isActive = find(
647        activeThreads.begin(), activeThreads.end(), tid);
648
649    if (isActive != activeThreads.end()) {
650        DPRINTF(O3CPU,"[tid:%i]: Removing from active threads list\n",
651                tid);
652        activeThreads.erase(isActive);
653
654        removeThread(tid);
655    }
656*/
657}
658
659template <class Impl>
660void
661FullO3CPU<Impl>::switchOut(Sampler *_sampler)
662{
663    sampler = _sampler;
664    switchCount = 0;
665    fetch.switchOut();
666    decode.switchOut();
667    rename.switchOut();
668    iew.switchOut();
669    commit.switchOut();
670
671    // Wake the CPU and record activity so everything can drain out if
672    // the CPU is currently idle.
673    wakeCPU();
674    activityRec.activity();
675}
676
677template <class Impl>
678void
679FullO3CPU<Impl>::signalSwitched()
680{
681    if (++switchCount == NumStages) {
682        fetch.doSwitchOut();
683        rename.doSwitchOut();
684        commit.doSwitchOut();
685        instList.clear();
686        while (!removeList.empty()) {
687            removeList.pop();
688        }
689
690        if (checker)
691            checker->switchOut(sampler);
692
693        if (tickEvent.scheduled())
694            tickEvent.squash();
695        sampler->signalSwitched();
696        _status = SwitchedOut;
697    }
698    assert(switchCount <= 5);
699}
700
701template <class Impl>
702void
703FullO3CPU<Impl>::takeOverFrom(BaseCPU *oldCPU)
704{
705    // Flush out any old data from the time buffers.
706    for (int i = 0; i < 10; ++i) {
707        timeBuffer.advance();
708        fetchQueue.advance();
709        decodeQueue.advance();
710        renameQueue.advance();
711        iewQueue.advance();
712    }
713
714    activityRec.reset();
715
716    BaseCPU::takeOverFrom(oldCPU);
717
718    fetch.takeOverFrom();
719    decode.takeOverFrom();
720    rename.takeOverFrom();
721    iew.takeOverFrom();
722    commit.takeOverFrom();
723
724    assert(!tickEvent.scheduled());
725
726    // @todo: Figure out how to properly select the tid to put onto
727    // the active threads list.
728    int tid = 0;
729
730    list<unsigned>::iterator isActive = find(
731        activeThreads.begin(), activeThreads.end(), tid);
732
733    if (isActive == activeThreads.end()) {
734        //May Need to Re-code this if the delay variable is the delay
735        //needed for thread to activate
736        DPRINTF(O3CPU, "Adding Thread %i to active threads list\n",
737                tid);
738
739        activeThreads.push_back(tid);
740    }
741
742    // Set all statuses to active, schedule the CPU's tick event.
743    // @todo: Fix up statuses so this is handled properly
744    for (int i = 0; i < threadContexts.size(); ++i) {
745        ThreadContext *tc = threadContexts[i];
746        if (tc->status() == ThreadContext::Active && _status != Running) {
747            _status = Running;
748            tickEvent.schedule(curTick);
749        }
750    }
751    if (!tickEvent.scheduled())
752        tickEvent.schedule(curTick);
753}
754
755template <class Impl>
756uint64_t
757FullO3CPU<Impl>::readIntReg(int reg_idx)
758{
759    return regFile.readIntReg(reg_idx);
760}
761
762template <class Impl>
763FloatReg
764FullO3CPU<Impl>::readFloatReg(int reg_idx, int width)
765{
766    return regFile.readFloatReg(reg_idx, width);
767}
768
769template <class Impl>
770FloatReg
771FullO3CPU<Impl>::readFloatReg(int reg_idx)
772{
773    return regFile.readFloatReg(reg_idx);
774}
775
776template <class Impl>
777FloatRegBits
778FullO3CPU<Impl>::readFloatRegBits(int reg_idx, int width)
779{
780    return regFile.readFloatRegBits(reg_idx, width);
781}
782
783template <class Impl>
784FloatRegBits
785FullO3CPU<Impl>::readFloatRegBits(int reg_idx)
786{
787    return regFile.readFloatRegBits(reg_idx);
788}
789
790template <class Impl>
791void
792FullO3CPU<Impl>::setIntReg(int reg_idx, uint64_t val)
793{
794    regFile.setIntReg(reg_idx, val);
795}
796
797template <class Impl>
798void
799FullO3CPU<Impl>::setFloatReg(int reg_idx, FloatReg val, int width)
800{
801    regFile.setFloatReg(reg_idx, val, width);
802}
803
804template <class Impl>
805void
806FullO3CPU<Impl>::setFloatReg(int reg_idx, FloatReg val)
807{
808    regFile.setFloatReg(reg_idx, val);
809}
810
811template <class Impl>
812void
813FullO3CPU<Impl>::setFloatRegBits(int reg_idx, FloatRegBits val, int width)
814{
815    regFile.setFloatRegBits(reg_idx, val, width);
816}
817
818template <class Impl>
819void
820FullO3CPU<Impl>::setFloatRegBits(int reg_idx, FloatRegBits val)
821{
822    regFile.setFloatRegBits(reg_idx, val);
823}
824
825template <class Impl>
826uint64_t
827FullO3CPU<Impl>::readArchIntReg(int reg_idx, unsigned tid)
828{
829    PhysRegIndex phys_reg = commitRenameMap[tid].lookup(reg_idx);
830
831    return regFile.readIntReg(phys_reg);
832}
833
834template <class Impl>
835float
836FullO3CPU<Impl>::readArchFloatRegSingle(int reg_idx, unsigned tid)
837{
838    int idx = reg_idx + TheISA::FP_Base_DepTag;
839    PhysRegIndex phys_reg = commitRenameMap[tid].lookup(idx);
840
841    return regFile.readFloatReg(phys_reg);
842}
843
844template <class Impl>
845double
846FullO3CPU<Impl>::readArchFloatRegDouble(int reg_idx, unsigned tid)
847{
848    int idx = reg_idx + TheISA::FP_Base_DepTag;
849    PhysRegIndex phys_reg = commitRenameMap[tid].lookup(idx);
850
851    return regFile.readFloatReg(phys_reg, 64);
852}
853
854template <class Impl>
855uint64_t
856FullO3CPU<Impl>::readArchFloatRegInt(int reg_idx, unsigned tid)
857{
858    int idx = reg_idx + TheISA::FP_Base_DepTag;
859    PhysRegIndex phys_reg = commitRenameMap[tid].lookup(idx);
860
861    return regFile.readFloatRegBits(phys_reg);
862}
863
864template <class Impl>
865void
866FullO3CPU<Impl>::setArchIntReg(int reg_idx, uint64_t val, unsigned tid)
867{
868    PhysRegIndex phys_reg = commitRenameMap[tid].lookup(reg_idx);
869
870    regFile.setIntReg(phys_reg, val);
871}
872
873template <class Impl>
874void
875FullO3CPU<Impl>::setArchFloatRegSingle(int reg_idx, float val, unsigned tid)
876{
877    PhysRegIndex phys_reg = commitRenameMap[tid].lookup(reg_idx);
878
879    regFile.setFloatReg(phys_reg, val);
880}
881
882template <class Impl>
883void
884FullO3CPU<Impl>::setArchFloatRegDouble(int reg_idx, double val, unsigned tid)
885{
886    PhysRegIndex phys_reg = commitRenameMap[tid].lookup(reg_idx);
887
888    regFile.setFloatReg(phys_reg, val, 64);
889}
890
891template <class Impl>
892void
893FullO3CPU<Impl>::setArchFloatRegInt(int reg_idx, uint64_t val, unsigned tid)
894{
895    PhysRegIndex phys_reg = commitRenameMap[tid].lookup(reg_idx);
896
897    regFile.setFloatRegBits(phys_reg, val);
898}
899
900template <class Impl>
901uint64_t
902FullO3CPU<Impl>::readPC(unsigned tid)
903{
904    return commit.readPC(tid);
905}
906
907template <class Impl>
908void
909FullO3CPU<Impl>::setPC(Addr new_PC,unsigned tid)
910{
911    commit.setPC(new_PC, tid);
912}
913
914template <class Impl>
915uint64_t
916FullO3CPU<Impl>::readNextPC(unsigned tid)
917{
918    return commit.readNextPC(tid);
919}
920
921template <class Impl>
922void
923FullO3CPU<Impl>::setNextPC(uint64_t val,unsigned tid)
924{
925    commit.setNextPC(val, tid);
926}
927
928template <class Impl>
929typename FullO3CPU<Impl>::ListIt
930FullO3CPU<Impl>::addInst(DynInstPtr &inst)
931{
932    instList.push_back(inst);
933
934    return --(instList.end());
935}
936
937template <class Impl>
938void
939FullO3CPU<Impl>::instDone(unsigned tid)
940{
941    // Keep an instruction count.
942    thread[tid]->numInst++;
943    thread[tid]->numInsts++;
944    committedInsts[tid]++;
945    totalCommittedInsts++;
946
947    // Check for instruction-count-based events.
948    comInstEventQueue[tid]->serviceEvents(thread[tid]->numInst);
949}
950
951template <class Impl>
952void
953FullO3CPU<Impl>::addToRemoveList(DynInstPtr &inst)
954{
955    removeInstsThisCycle = true;
956
957    removeList.push(inst->getInstListIt());
958}
959
960template <class Impl>
961void
962FullO3CPU<Impl>::removeFrontInst(DynInstPtr &inst)
963{
964    DPRINTF(O3CPU, "Removing committed instruction [tid:%i] PC %#x "
965            "[sn:%lli]\n",
966            inst->threadNumber, inst->readPC(), inst->seqNum);
967
968    removeInstsThisCycle = true;
969
970    // Remove the front instruction.
971    removeList.push(inst->getInstListIt());
972}
973
974template <class Impl>
975void
976FullO3CPU<Impl>::removeInstsNotInROB(unsigned tid)
977{
978    DPRINTF(O3CPU, "Thread %i: Deleting instructions from instruction"
979            " list.\n", tid);
980
981    ListIt end_it;
982
983    bool rob_empty = false;
984
985    if (instList.empty()) {
986        return;
987    } else if (rob.isEmpty(/*tid*/)) {
988        DPRINTF(O3CPU, "ROB is empty, squashing all insts.\n");
989        end_it = instList.begin();
990        rob_empty = true;
991    } else {
992        end_it = (rob.readTailInst(tid))->getInstListIt();
993        DPRINTF(O3CPU, "ROB is not empty, squashing insts not in ROB.\n");
994    }
995
996    removeInstsThisCycle = true;
997
998    ListIt inst_it = instList.end();
999
1000    inst_it--;
1001
1002    // Walk through the instruction list, removing any instructions
1003    // that were inserted after the given instruction iterator, end_it.
1004    while (inst_it != end_it) {
1005        assert(!instList.empty());
1006
1007        squashInstIt(inst_it, tid);
1008
1009        inst_it--;
1010    }
1011
1012    // If the ROB was empty, then we actually need to remove the first
1013    // instruction as well.
1014    if (rob_empty) {
1015        squashInstIt(inst_it, tid);
1016    }
1017}
1018
1019template <class Impl>
1020void
1021FullO3CPU<Impl>::removeInstsUntil(const InstSeqNum &seq_num,
1022                                  unsigned tid)
1023{
1024    assert(!instList.empty());
1025
1026    removeInstsThisCycle = true;
1027
1028    ListIt inst_iter = instList.end();
1029
1030    inst_iter--;
1031
1032    DPRINTF(O3CPU, "Deleting instructions from instruction "
1033            "list that are from [tid:%i] and above [sn:%lli] (end=%lli).\n",
1034            tid, seq_num, (*inst_iter)->seqNum);
1035
1036    while ((*inst_iter)->seqNum > seq_num) {
1037
1038        bool break_loop = (inst_iter == instList.begin());
1039
1040        squashInstIt(inst_iter, tid);
1041
1042        inst_iter--;
1043
1044        if (break_loop)
1045            break;
1046    }
1047}
1048
1049template <class Impl>
1050inline void
1051FullO3CPU<Impl>::squashInstIt(const ListIt &instIt, const unsigned &tid)
1052{
1053    if ((*instIt)->threadNumber == tid) {
1054        DPRINTF(O3CPU, "Squashing instruction, "
1055                "[tid:%i] [sn:%lli] PC %#x\n",
1056                (*instIt)->threadNumber,
1057                (*instIt)->seqNum,
1058                (*instIt)->readPC());
1059
1060        // Mark it as squashed.
1061        (*instIt)->setSquashed();
1062
1063        // @todo: Formulate a consistent method for deleting
1064        // instructions from the instruction list
1065        // Remove the instruction from the list.
1066        removeList.push(instIt);
1067    }
1068}
1069
1070template <class Impl>
1071void
1072FullO3CPU<Impl>::cleanUpRemovedInsts()
1073{
1074    while (!removeList.empty()) {
1075        DPRINTF(O3CPU, "Removing instruction, "
1076                "[tid:%i] [sn:%lli] PC %#x\n",
1077                (*removeList.front())->threadNumber,
1078                (*removeList.front())->seqNum,
1079                (*removeList.front())->readPC());
1080
1081        instList.erase(removeList.front());
1082
1083        removeList.pop();
1084    }
1085
1086    removeInstsThisCycle = false;
1087}
1088/*
1089template <class Impl>
1090void
1091FullO3CPU<Impl>::removeAllInsts()
1092{
1093    instList.clear();
1094}
1095*/
1096template <class Impl>
1097void
1098FullO3CPU<Impl>::dumpInsts()
1099{
1100    int num = 0;
1101
1102    ListIt inst_list_it = instList.begin();
1103
1104    cprintf("Dumping Instruction List\n");
1105
1106    while (inst_list_it != instList.end()) {
1107        cprintf("Instruction:%i\nPC:%#x\n[tid:%i]\n[sn:%lli]\nIssued:%i\n"
1108                "Squashed:%i\n\n",
1109                num, (*inst_list_it)->readPC(), (*inst_list_it)->threadNumber,
1110                (*inst_list_it)->seqNum, (*inst_list_it)->isIssued(),
1111                (*inst_list_it)->isSquashed());
1112        inst_list_it++;
1113        ++num;
1114    }
1115}
1116/*
1117template <class Impl>
1118void
1119FullO3CPU<Impl>::wakeDependents(DynInstPtr &inst)
1120{
1121    iew.wakeDependents(inst);
1122}
1123*/
1124template <class Impl>
1125void
1126FullO3CPU<Impl>::wakeCPU()
1127{
1128    if (activityRec.active() || tickEvent.scheduled()) {
1129        DPRINTF(Activity, "CPU already running.\n");
1130        return;
1131    }
1132
1133    DPRINTF(Activity, "Waking up CPU\n");
1134
1135    idleCycles += (curTick - 1) - lastRunningCycle;
1136
1137    tickEvent.schedule(curTick);
1138}
1139
1140template <class Impl>
1141int
1142FullO3CPU<Impl>::getFreeTid()
1143{
1144    for (int i=0; i < numThreads; i++) {
1145        if (!tids[i]) {
1146            tids[i] = true;
1147            return i;
1148        }
1149    }
1150
1151    return -1;
1152}
1153
1154template <class Impl>
1155void
1156FullO3CPU<Impl>::doContextSwitch()
1157{
1158    if (contextSwitch) {
1159
1160        //ADD CODE TO DEACTIVE THREAD HERE (???)
1161
1162        for (int tid=0; tid < cpuWaitList.size(); tid++) {
1163            activateWhenReady(tid);
1164        }
1165
1166        if (cpuWaitList.size() == 0)
1167            contextSwitch = true;
1168    }
1169}
1170
1171template <class Impl>
1172void
1173FullO3CPU<Impl>::updateThreadPriority()
1174{
1175    if (activeThreads.size() > 1)
1176    {
1177        //DEFAULT TO ROUND ROBIN SCHEME
1178        //e.g. Move highest priority to end of thread list
1179        list<unsigned>::iterator list_begin = activeThreads.begin();
1180        list<unsigned>::iterator list_end   = activeThreads.end();
1181
1182        unsigned high_thread = *list_begin;
1183
1184        activeThreads.erase(list_begin);
1185
1186        activeThreads.push_back(high_thread);
1187    }
1188}
1189
1190// Forward declaration of FullO3CPU.
1191template class FullO3CPU<AlphaSimpleImpl>;
1192