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