2 * Copyright (c) 2004-2006 The Regents of The University of Michigan
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.
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.
31 #include "config/full_system.hh"
34 #include "sim/system.hh"
36 #include "sim/process.hh"
39 #include "cpu/activity.hh"
40 #include "cpu/checker/cpu.hh"
41 #include "cpu/cpu_exec_context.hh"
42 #include "cpu/exec_context.hh"
43 #include "cpu/o3/alpha_dyn_inst.hh"
44 #include "cpu/o3/alpha_impl.hh"
45 #include "cpu/o3/cpu.hh"
47 #include "sim/root.hh"
48 #include "sim/stat_control.hh"
51 using namespace TheISA
;
53 BaseFullCPU::BaseFullCPU(Params
*params
)
54 : BaseCPU(params
), cpu_id(0)
59 BaseFullCPU::regStats()
65 FullO3CPU
<Impl
>::TickEvent::TickEvent(FullO3CPU
<Impl
> *c
)
66 : Event(&mainEventQueue
, CPU_Tick_Pri
), cpu(c
)
72 FullO3CPU
<Impl
>::TickEvent::process()
79 FullO3CPU
<Impl
>::TickEvent::description()
81 return "FullO3CPU tick event";
85 FullO3CPU
<Impl
>::FullO3CPU(Params
*params
)
86 : BaseFullCPU(params
),
88 removeInstsThisCycle(false),
95 regFile(params
->numPhysIntRegs
, params
->numPhysFloatRegs
),
97 freeList(params
->numberOfThreads
,//number of activeThreads
98 TheISA::NumIntRegs
, params
->numPhysIntRegs
,
99 TheISA::NumFloatRegs
, params
->numPhysFloatRegs
),
101 rob(params
->numROBEntries
, params
->squashWidth
,
102 params
->smtROBPolicy
, params
->smtROBThreshold
,
103 params
->numberOfThreads
),
105 scoreboard(params
->numberOfThreads
,//number of activeThreads
106 TheISA::NumIntRegs
, params
->numPhysIntRegs
,
107 TheISA::NumFloatRegs
, params
->numPhysFloatRegs
,
108 TheISA::NumMiscRegs
* number_of_threads
,
111 // For now just have these time buffers be pretty big.
112 // @todo: Make these time buffer sizes parameters or derived
119 activityRec(NumStages
, 10, params
->activity
),
124 system(params
->system
),
125 memCtrl(system
->memctrl
),
126 physmem(system
->physmem
),
127 #endif // FULL_SYSTEM
130 deferRegistration(params
->deferRegistration
),
131 numThreads(number_of_threads
)
135 if (params
->checker
) {
136 BaseCPU
*temp_checker
= params
->checker
;
137 checker
= dynamic_cast<Checker
<DynInstPtr
> *>(temp_checker
);
138 checker
->setMemory(mem
);
140 checker
->setSystem(params
->system
);
147 thread
.resize(number_of_threads
);
148 tids
.resize(number_of_threads
);
151 // The stages also need their CPU pointer setup. However this
152 // must be done at the upper level CPU because they have pointers
153 // to the upper level CPU, and not this FullO3CPU.
155 // Set up Pointers to the activeThreads list for each stage
156 fetch
.setActiveThreads(&activeThreads
);
157 decode
.setActiveThreads(&activeThreads
);
158 rename
.setActiveThreads(&activeThreads
);
159 iew
.setActiveThreads(&activeThreads
);
160 commit
.setActiveThreads(&activeThreads
);
162 // Give each of the stages the time buffer they will use.
163 fetch
.setTimeBuffer(&timeBuffer
);
164 decode
.setTimeBuffer(&timeBuffer
);
165 rename
.setTimeBuffer(&timeBuffer
);
166 iew
.setTimeBuffer(&timeBuffer
);
167 commit
.setTimeBuffer(&timeBuffer
);
169 // Also setup each of the stages' queues.
170 fetch
.setFetchQueue(&fetchQueue
);
171 decode
.setFetchQueue(&fetchQueue
);
172 commit
.setFetchQueue(&fetchQueue
);
173 decode
.setDecodeQueue(&decodeQueue
);
174 rename
.setDecodeQueue(&decodeQueue
);
175 rename
.setRenameQueue(&renameQueue
);
176 iew
.setRenameQueue(&renameQueue
);
177 iew
.setIEWQueue(&iewQueue
);
178 commit
.setIEWQueue(&iewQueue
);
179 commit
.setRenameQueue(&renameQueue
);
181 commit
.setFetchStage(&fetch
);
182 commit
.setIEWStage(&iew
);
183 rename
.setIEWStage(&iew
);
184 rename
.setCommitStage(&commit
);
187 int active_threads
= params
->workload
.size();
189 int active_threads
= 1;
192 //Make Sure That this a Valid Architeture
193 assert(params
->numPhysIntRegs
>= numThreads
* TheISA::NumIntRegs
);
194 assert(params
->numPhysFloatRegs
>= numThreads
* TheISA::NumFloatRegs
);
196 rename
.setScoreboard(&scoreboard
);
197 iew
.setScoreboard(&scoreboard
);
199 // Setup the rename map for whichever stages need it.
200 PhysRegIndex lreg_idx
= 0;
201 PhysRegIndex freg_idx
= params
->numPhysIntRegs
; //Index to 1 after int regs
203 for (int tid
=0; tid
< numThreads
; tid
++) {
204 bool bindRegs
= (tid
<= active_threads
- 1);
206 commitRenameMap
[tid
].init(TheISA::NumIntRegs
,
207 params
->numPhysIntRegs
,
208 lreg_idx
, //Index for Logical. Regs
210 TheISA::NumFloatRegs
,
211 params
->numPhysFloatRegs
,
212 freg_idx
, //Index for Float Regs
222 renameMap
[tid
].init(TheISA::NumIntRegs
,
223 params
->numPhysIntRegs
,
224 lreg_idx
, //Index for Logical. Regs
226 TheISA::NumFloatRegs
,
227 params
->numPhysFloatRegs
,
228 freg_idx
, //Index for Float Regs
239 rename
.setRenameMap(renameMap
);
240 commit
.setRenameMap(commitRenameMap
);
242 // Give renameMap & rename stage access to the freeList;
243 for (int i
=0; i
< numThreads
; i
++) {
244 renameMap
[i
].setFreeList(&freeList
);
246 rename
.setFreeList(&freeList
);
248 // Setup the page table for whichever stages need it.
250 // fetch.setPageTable(pTable);
251 // iew.setPageTable(pTable);
254 // Setup the ROB for whichever stages need it.
257 lastRunningCycle
= curTick
;
259 contextSwitch
= false;
262 template <class Impl
>
263 FullO3CPU
<Impl
>::~FullO3CPU()
267 template <class Impl
>
269 FullO3CPU
<Impl
>::fullCPURegStats()
271 BaseFullCPU::regStats();
273 // Register any of the FullCPU's stats here.
275 .name(name() + ".timesIdled")
276 .desc("Number of times that the entire CPU went into an idle state and"
277 " unscheduled itself")
281 .name(name() + ".idleCycles")
282 .desc("Total number of cycles that the CPU has spent unscheduled due "
286 // Number of Instructions simulated
287 // --------------------------------
288 // Should probably be in Base CPU but need templated
289 // MaxThreads so put in here instead
292 .name(name() + ".committedInsts")
293 .desc("Number of Instructions Simulated");
296 .name(name() + ".committedInsts_total")
297 .desc("Number of Instructions Simulated");
300 .name(name() + ".cpi")
301 .desc("CPI: Cycles Per Instruction")
303 cpi
= simTicks
/ committedInsts
;
306 .name(name() + ".cpi_total")
307 .desc("CPI: Total CPI of All Threads")
309 totalCpi
= simTicks
/ totalCommittedInsts
;
312 .name(name() + ".ipc")
313 .desc("IPC: Instructions Per Cycle")
315 ipc
= committedInsts
/ simTicks
;
318 .name(name() + ".ipc_total")
319 .desc("IPC: Total IPC of All Threads")
321 totalIpc
= totalCommittedInsts
/ simTicks
;
325 template <class Impl
>
327 FullO3CPU
<Impl
>::tick()
329 DPRINTF(FullCPU
, "\n\nFullCPU: Ticking main, FullO3CPU.\n");
335 //Tick each of the stages
350 // Now advance the time buffers
351 timeBuffer
.advance();
353 fetchQueue
.advance();
354 decodeQueue
.advance();
355 renameQueue
.advance();
358 activityRec
.advance();
360 if (removeInstsThisCycle
) {
361 cleanUpRemovedInsts();
364 if (!tickEvent
.scheduled()) {
365 if (_status
== SwitchedOut
) {
367 lastRunningCycle
= curTick
;
368 } else if (!activityRec
.active()) {
369 lastRunningCycle
= curTick
;
372 tickEvent
.schedule(curTick
+ cycles(1));
377 updateThreadPriority();
382 template <class Impl
>
384 FullO3CPU
<Impl
>::init()
386 if (!deferRegistration
) {
387 registerExecContexts();
390 // Set inSyscall so that the CPU doesn't squash when initially
391 // setting up registers.
392 for (int i
= 0; i
< number_of_threads
; ++i
)
393 thread
[i
]->inSyscall
= true;
395 for (int tid
=0; tid
< number_of_threads
; tid
++) {
397 ExecContext
*src_xc
= execContexts
[tid
];
399 ExecContext
*src_xc
= thread
[tid
]->getXCProxy();
401 // Threads start in the Suspended State
402 if (src_xc
->status() != ExecContext::Suspended
) {
407 TheISA::initCPU(src_xc
, src_xc
->readCpuId());
412 for (int i
= 0; i
< number_of_threads
; ++i
)
413 thread
[i
]->inSyscall
= false;
415 // Initialize stages.
421 commit
.setThreads(thread
);
424 template <class Impl
>
426 FullO3CPU
<Impl
>::insertThread(unsigned tid
)
428 DPRINTF(FullCPU
,"[tid:%i] Initializing thread data");
429 // Will change now that the PC and thread state is internal to the CPU
430 // and not in the CPUExecContext.
433 ExecContext
*src_xc
= system
->execContexts
[tid
];
435 CPUExecContext
*src_xc
= thread
[tid
];
438 //Bind Int Regs to Rename Map
439 for (int ireg
= 0; ireg
< TheISA::NumIntRegs
; ireg
++) {
440 PhysRegIndex phys_reg
= freeList
.getIntReg();
442 renameMap
[tid
].setEntry(ireg
,phys_reg
);
443 scoreboard
.setReg(phys_reg
);
446 //Bind Float Regs to Rename Map
447 for (int freg
= 0; freg
< TheISA::NumFloatRegs
; freg
++) {
448 PhysRegIndex phys_reg
= freeList
.getFloatReg();
450 renameMap
[tid
].setEntry(freg
,phys_reg
);
451 scoreboard
.setReg(phys_reg
);
454 //Copy Thread Data Into RegFile
455 this->copyFromXC(tid
);
458 regFile
.pc
[tid
] = src_xc
->readPC();
459 regFile
.npc
[tid
] = src_xc
->readNextPC();
461 src_xc
->setStatus(ExecContext::Active
);
463 activateContext(tid
,1);
465 //Reset ROB/IQ/LSQ Entries
466 commit
.rob
->resetEntries();
471 template <class Impl
>
473 FullO3CPU
<Impl
>::removeThread(unsigned tid
)
475 DPRINTF(FullCPU
,"[tid:%i] Removing thread data");
477 //Unbind Int Regs from Rename Map
478 for (int ireg
= 0; ireg
< TheISA::NumIntRegs
; ireg
++) {
479 PhysRegIndex phys_reg
= renameMap
[tid
].lookup(ireg
);
481 scoreboard
.unsetReg(phys_reg
);
482 freeList
.addReg(phys_reg
);
485 //Unbind Float Regs from Rename Map
486 for (int freg
= 0; freg
< TheISA::NumFloatRegs
; freg
++) {
487 PhysRegIndex phys_reg
= renameMap
[tid
].lookup(freg
);
489 scoreboard
.unsetReg(phys_reg
);
490 freeList
.addReg(phys_reg
);
493 //Copy Thread Data From RegFile
495 * Do we really need to do this if we are removing a thread
496 * in the sense that it's finished (exiting)? If the thread is just
497 * being suspended we might...
499 // this->copyToXC(tid);
501 //Squash Throughout Pipeline
506 assert(iew
.ldstQueue
.getCount(tid
) == 0);
508 //Reset ROB/IQ/LSQ Entries
509 if (activeThreads
.size() >= 1) {
510 commit
.rob
->resetEntries();
517 template <class Impl
>
519 FullO3CPU
<Impl
>::activateWhenReady(int tid
)
521 DPRINTF(FullCPU
,"[tid:%i]: Checking if resources are available for incoming"
522 "(e.g. PhysRegs/ROB/IQ/LSQ) \n",
527 if (freeList
.numFreeIntRegs() >= TheISA::NumIntRegs
) {
528 DPRINTF(FullCPU
,"[tid:%i] Suspending thread due to not enough "
529 "Phys. Int. Regs.\n",
532 } else if (freeList
.numFreeFloatRegs() >= TheISA::NumFloatRegs
) {
533 DPRINTF(FullCPU
,"[tid:%i] Suspending thread due to not enough "
534 "Phys. Float. Regs.\n",
537 } else if (commit
.rob
->numFreeEntries() >=
538 commit
.rob
->entryAmount(activeThreads
.size() + 1)) {
539 DPRINTF(FullCPU
,"[tid:%i] Suspending thread due to not enough "
543 } else if (iew
.instQueue
.numFreeEntries() >=
544 iew
.instQueue
.entryAmount(activeThreads
.size() + 1)) {
545 DPRINTF(FullCPU
,"[tid:%i] Suspending thread due to not enough "
549 } else if (iew
.ldstQueue
.numFreeEntries() >=
550 iew
.ldstQueue
.entryAmount(activeThreads
.size() + 1)) {
551 DPRINTF(FullCPU
,"[tid:%i] Suspending thread due to not enough "
560 contextSwitch
= false;
562 cpuWaitList
.remove(tid
);
567 contextSwitch
= true;
570 cpuWaitList
.push_back(tid
);
574 template <class Impl
>
576 FullO3CPU
<Impl
>::activateContext(int tid
, int delay
)
578 // Needs to set each stage to running as well.
579 list
<unsigned>::iterator isActive
= find(
580 activeThreads
.begin(), activeThreads
.end(), tid
);
582 if (isActive
== activeThreads
.end()) {
583 //May Need to Re-code this if the delay variable is the
584 //delay needed for thread to activate
585 DPRINTF(FullCPU
, "Adding Thread %i to active threads list\n",
588 activeThreads
.push_back(tid
);
591 assert(_status
== Idle
|| _status
== SwitchedOut
);
593 scheduleTickEvent(delay
);
595 // Be sure to signal that there's some activity so the CPU doesn't
596 // deschedule itself.
597 activityRec
.activity();
598 fetch
.wakeFromQuiesce();
603 template <class Impl
>
605 FullO3CPU
<Impl
>::suspendContext(int tid
)
607 DPRINTF(FullCPU
,"[tid: %i]: Suspended ...\n", tid
);
608 unscheduleTickEvent();
611 //Remove From Active List, if Active
612 list<unsigned>::iterator isActive = find(
613 activeThreads.begin(), activeThreads.end(), tid);
615 if (isActive != activeThreads.end()) {
616 DPRINTF(FullCPU,"[tid:%i]: Removing from active threads list\n",
618 activeThreads.erase(isActive);
623 template <class Impl
>
625 FullO3CPU
<Impl
>::deallocateContext(int tid
)
627 DPRINTF(FullCPU
,"[tid:%i]: Deallocating ...", tid
);
629 //Remove From Active List, if Active
630 list<unsigned>::iterator isActive = find(
631 activeThreads.begin(), activeThreads.end(), tid);
633 if (isActive != activeThreads.end()) {
634 DPRINTF(FullCPU,"[tid:%i]: Removing from active threads list\n",
636 activeThreads.erase(isActive);
643 template <class Impl
>
645 FullO3CPU
<Impl
>::haltContext(int tid
)
647 DPRINTF(FullCPU
,"[tid:%i]: Halted ...", tid
);
649 //Remove From Active List, if Active
650 list<unsigned>::iterator isActive = find(
651 activeThreads.begin(), activeThreads.end(), tid);
653 if (isActive != activeThreads.end()) {
654 DPRINTF(FullCPU,"[tid:%i]: Removing from active threads list\n",
656 activeThreads.erase(isActive);
663 template <class Impl
>
665 FullO3CPU
<Impl
>::switchOut(Sampler
*_sampler
)
675 // Wake the CPU and record activity so everything can drain out if
676 // the CPU is currently idle.
678 activityRec
.activity();
681 template <class Impl
>
683 FullO3CPU
<Impl
>::signalSwitched()
685 if (++switchCount
== NumStages
) {
687 rename
.doSwitchOut();
688 commit
.doSwitchOut();
690 while (!removeList
.empty()) {
695 checker
->switchOut(sampler
);
697 if (tickEvent
.scheduled())
699 sampler
->signalSwitched();
700 _status
= SwitchedOut
;
702 assert(switchCount
<= 5);
705 template <class Impl
>
707 FullO3CPU
<Impl
>::takeOverFrom(BaseCPU
*oldCPU
)
709 // Flush out any old data from the time buffers.
710 for (int i
= 0; i
< 10; ++i
) {
711 timeBuffer
.advance();
712 fetchQueue
.advance();
713 decodeQueue
.advance();
714 renameQueue
.advance();
720 BaseCPU::takeOverFrom(oldCPU
);
722 fetch
.takeOverFrom();
723 decode
.takeOverFrom();
724 rename
.takeOverFrom();
726 commit
.takeOverFrom();
728 assert(!tickEvent
.scheduled());
730 // @todo: Figure out how to properly select the tid to put onto
731 // the active threads list.
734 list
<unsigned>::iterator isActive
= find(
735 activeThreads
.begin(), activeThreads
.end(), tid
);
737 if (isActive
== activeThreads
.end()) {
738 //May Need to Re-code this if the delay variable is the delay
739 //needed for thread to activate
740 DPRINTF(FullCPU
, "Adding Thread %i to active threads list\n",
743 activeThreads
.push_back(tid
);
746 // Set all statuses to active, schedule the CPU's tick event.
747 // @todo: Fix up statuses so this is handled properly
748 for (int i
= 0; i
< execContexts
.size(); ++i
) {
749 ExecContext
*xc
= execContexts
[i
];
750 if (xc
->status() == ExecContext::Active
&& _status
!= Running
) {
752 tickEvent
.schedule(curTick
);
755 if (!tickEvent
.scheduled())
756 tickEvent
.schedule(curTick
);
759 template <class Impl
>
761 FullO3CPU
<Impl
>::readIntReg(int reg_idx
)
763 return regFile
.readIntReg(reg_idx
);
766 template <class Impl
>
768 FullO3CPU
<Impl
>::readFloatReg(int reg_idx
, int width
)
770 return regFile
.readFloatReg(reg_idx
, width
);
773 template <class Impl
>
775 FullO3CPU
<Impl
>::readFloatReg(int reg_idx
)
777 return regFile
.readFloatReg(reg_idx
);
780 template <class Impl
>
782 FullO3CPU
<Impl
>::readFloatRegBits(int reg_idx
, int width
)
784 return regFile
.readFloatRegBits(reg_idx
, width
);
787 template <class Impl
>
789 FullO3CPU
<Impl
>::readFloatRegBits(int reg_idx
)
791 return regFile
.readFloatRegBits(reg_idx
);
794 template <class Impl
>
796 FullO3CPU
<Impl
>::setIntReg(int reg_idx
, uint64_t val
)
798 regFile
.setIntReg(reg_idx
, val
);
801 template <class Impl
>
803 FullO3CPU
<Impl
>::setFloatReg(int reg_idx
, FloatReg val
, int width
)
805 regFile
.setFloatReg(reg_idx
, val
, width
);
808 template <class Impl
>
810 FullO3CPU
<Impl
>::setFloatReg(int reg_idx
, FloatReg val
)
812 regFile
.setFloatReg(reg_idx
, val
);
815 template <class Impl
>
817 FullO3CPU
<Impl
>::setFloatRegBits(int reg_idx
, FloatRegBits val
, int width
)
819 regFile
.setFloatRegBits(reg_idx
, val
, width
);
822 template <class Impl
>
824 FullO3CPU
<Impl
>::setFloatRegBits(int reg_idx
, FloatRegBits val
)
826 regFile
.setFloatRegBits(reg_idx
, val
);
829 template <class Impl
>
831 FullO3CPU
<Impl
>::readArchIntReg(int reg_idx
, unsigned tid
)
833 PhysRegIndex phys_reg
= commitRenameMap
[tid
].lookup(reg_idx
);
835 return regFile
.readIntReg(phys_reg
);
838 template <class Impl
>
840 FullO3CPU
<Impl
>::readArchFloatRegSingle(int reg_idx
, unsigned tid
)
842 int idx
= reg_idx
+ TheISA::FP_Base_DepTag
;
843 PhysRegIndex phys_reg
= commitRenameMap
[tid
].lookup(idx
);
845 return regFile
.readFloatReg(phys_reg
);
848 template <class Impl
>
850 FullO3CPU
<Impl
>::readArchFloatRegDouble(int reg_idx
, unsigned tid
)
852 int idx
= reg_idx
+ TheISA::FP_Base_DepTag
;
853 PhysRegIndex phys_reg
= commitRenameMap
[tid
].lookup(idx
);
855 return regFile
.readFloatReg(phys_reg
, 64);
858 template <class Impl
>
860 FullO3CPU
<Impl
>::readArchFloatRegInt(int reg_idx
, unsigned tid
)
862 int idx
= reg_idx
+ TheISA::FP_Base_DepTag
;
863 PhysRegIndex phys_reg
= commitRenameMap
[tid
].lookup(idx
);
865 return regFile
.readFloatRegBits(phys_reg
);
868 template <class Impl
>
870 FullO3CPU
<Impl
>::setArchIntReg(int reg_idx
, uint64_t val
, unsigned tid
)
872 PhysRegIndex phys_reg
= commitRenameMap
[tid
].lookup(reg_idx
);
874 regFile
.setIntReg(phys_reg
, val
);
877 template <class Impl
>
879 FullO3CPU
<Impl
>::setArchFloatRegSingle(int reg_idx
, float val
, unsigned tid
)
881 PhysRegIndex phys_reg
= commitRenameMap
[tid
].lookup(reg_idx
);
883 regFile
.setFloatReg(phys_reg
, val
);
886 template <class Impl
>
888 FullO3CPU
<Impl
>::setArchFloatRegDouble(int reg_idx
, double val
, unsigned tid
)
890 PhysRegIndex phys_reg
= commitRenameMap
[tid
].lookup(reg_idx
);
892 regFile
.setFloatReg(phys_reg
, val
, 64);
895 template <class Impl
>
897 FullO3CPU
<Impl
>::setArchFloatRegInt(int reg_idx
, uint64_t val
, unsigned tid
)
899 PhysRegIndex phys_reg
= commitRenameMap
[tid
].lookup(reg_idx
);
901 regFile
.setFloatRegBits(phys_reg
, val
);
904 template <class Impl
>
906 FullO3CPU
<Impl
>::readPC(unsigned tid
)
908 return commit
.readPC(tid
);
911 template <class Impl
>
913 FullO3CPU
<Impl
>::setPC(Addr new_PC
,unsigned tid
)
915 commit
.setPC(new_PC
, tid
);
918 template <class Impl
>
920 FullO3CPU
<Impl
>::readNextPC(unsigned tid
)
922 return commit
.readNextPC(tid
);
925 template <class Impl
>
927 FullO3CPU
<Impl
>::setNextPC(uint64_t val
,unsigned tid
)
929 commit
.setNextPC(val
, tid
);
932 template <class Impl
>
933 typename FullO3CPU
<Impl
>::ListIt
934 FullO3CPU
<Impl
>::addInst(DynInstPtr
&inst
)
936 instList
.push_back(inst
);
938 return --(instList
.end());
941 template <class Impl
>
943 FullO3CPU
<Impl
>::instDone(unsigned tid
)
945 // Keep an instruction count.
946 thread
[tid
]->numInst
++;
947 thread
[tid
]->numInsts
++;
948 committedInsts
[tid
]++;
949 totalCommittedInsts
++;
951 // Check for instruction-count-based events.
952 comInstEventQueue
[tid
]->serviceEvents(thread
[tid
]->numInst
);
955 template <class Impl
>
957 FullO3CPU
<Impl
>::addToRemoveList(DynInstPtr
&inst
)
959 removeInstsThisCycle
= true;
961 removeList
.push(inst
->getInstListIt());
964 template <class Impl
>
966 FullO3CPU
<Impl
>::removeFrontInst(DynInstPtr
&inst
)
968 DPRINTF(FullCPU
, "FullCPU: Removing committed instruction [tid:%i] PC %#x "
970 inst
->threadNumber
, inst
->readPC(), inst
->seqNum
);
972 removeInstsThisCycle
= true;
974 // Remove the front instruction.
975 removeList
.push(inst
->getInstListIt());
978 template <class Impl
>
980 FullO3CPU
<Impl
>::removeInstsNotInROB(unsigned tid
)
982 DPRINTF(FullCPU
, "FullCPU: Thread %i: Deleting instructions from instruction"
987 bool rob_empty
= false;
989 if (instList
.empty()) {
991 } else if (rob
.isEmpty(/*tid*/)) {
992 DPRINTF(FullCPU
, "FullCPU: ROB is empty, squashing all insts.\n");
993 end_it
= instList
.begin();
996 end_it
= (rob
.readTailInst(tid
))->getInstListIt();
997 DPRINTF(FullCPU
, "FullCPU: ROB is not empty, squashing insts not in ROB.\n");
1000 removeInstsThisCycle
= true;
1002 ListIt inst_it
= instList
.end();
1006 // Walk through the instruction list, removing any instructions
1007 // that were inserted after the given instruction iterator, end_it.
1008 while (inst_it
!= end_it
) {
1009 assert(!instList
.empty());
1011 squashInstIt(inst_it
, tid
);
1016 // If the ROB was empty, then we actually need to remove the first
1017 // instruction as well.
1019 squashInstIt(inst_it
, tid
);
1023 template <class Impl
>
1025 FullO3CPU
<Impl
>::removeInstsUntil(const InstSeqNum
&seq_num
,
1028 assert(!instList
.empty());
1030 removeInstsThisCycle
= true;
1032 ListIt inst_iter
= instList
.end();
1036 DPRINTF(FullCPU
, "FullCPU: Deleting instructions from instruction "
1037 "list that are from [tid:%i] and above [sn:%lli] (end=%lli).\n",
1038 tid
, seq_num
, (*inst_iter
)->seqNum
);
1040 while ((*inst_iter
)->seqNum
> seq_num
) {
1042 bool break_loop
= (inst_iter
== instList
.begin());
1044 squashInstIt(inst_iter
, tid
);
1053 template <class Impl
>
1055 FullO3CPU
<Impl
>::squashInstIt(const ListIt
&instIt
, const unsigned &tid
)
1057 if ((*instIt
)->threadNumber
== tid
) {
1058 DPRINTF(FullCPU
, "FullCPU: Squashing instruction, "
1059 "[tid:%i] [sn:%lli] PC %#x\n",
1060 (*instIt
)->threadNumber
,
1062 (*instIt
)->readPC());
1064 // Mark it as squashed.
1065 (*instIt
)->setSquashed();
1067 // @todo: Formulate a consistent method for deleting
1068 // instructions from the instruction list
1069 // Remove the instruction from the list.
1070 removeList
.push(instIt
);
1074 template <class Impl
>
1076 FullO3CPU
<Impl
>::cleanUpRemovedInsts()
1078 while (!removeList
.empty()) {
1079 DPRINTF(FullCPU
, "FullCPU: Removing instruction, "
1080 "[tid:%i] [sn:%lli] PC %#x\n",
1081 (*removeList
.front())->threadNumber
,
1082 (*removeList
.front())->seqNum
,
1083 (*removeList
.front())->readPC());
1085 instList
.erase(removeList
.front());
1090 removeInstsThisCycle
= false;
1093 template <class Impl>
1095 FullO3CPU<Impl>::removeAllInsts()
1100 template <class Impl
>
1102 FullO3CPU
<Impl
>::dumpInsts()
1106 ListIt inst_list_it
= instList
.begin();
1108 cprintf("Dumping Instruction List\n");
1110 while (inst_list_it
!= instList
.end()) {
1111 cprintf("Instruction:%i\nPC:%#x\n[tid:%i]\n[sn:%lli]\nIssued:%i\n"
1113 num
, (*inst_list_it
)->readPC(), (*inst_list_it
)->threadNumber
,
1114 (*inst_list_it
)->seqNum
, (*inst_list_it
)->isIssued(),
1115 (*inst_list_it
)->isSquashed());
1121 template <class Impl>
1123 FullO3CPU<Impl>::wakeDependents(DynInstPtr &inst)
1125 iew.wakeDependents(inst);
1128 template <class Impl
>
1130 FullO3CPU
<Impl
>::wakeCPU()
1132 if (activityRec
.active() || tickEvent
.scheduled()) {
1133 DPRINTF(Activity
, "CPU already running.\n");
1137 DPRINTF(Activity
, "Waking up CPU\n");
1139 idleCycles
+= (curTick
- 1) - lastRunningCycle
;
1141 tickEvent
.schedule(curTick
);
1144 template <class Impl
>
1146 FullO3CPU
<Impl
>::getFreeTid()
1148 for (int i
=0; i
< numThreads
; i
++) {
1158 template <class Impl
>
1160 FullO3CPU
<Impl
>::doContextSwitch()
1162 if (contextSwitch
) {
1164 //ADD CODE TO DEACTIVE THREAD HERE (???)
1166 for (int tid
=0; tid
< cpuWaitList
.size(); tid
++) {
1167 activateWhenReady(tid
);
1170 if (cpuWaitList
.size() == 0)
1171 contextSwitch
= true;
1175 template <class Impl
>
1177 FullO3CPU
<Impl
>::updateThreadPriority()
1179 if (activeThreads
.size() > 1)
1181 //DEFAULT TO ROUND ROBIN SCHEME
1182 //e.g. Move highest priority to end of thread list
1183 list
<unsigned>::iterator list_begin
= activeThreads
.begin();
1184 list
<unsigned>::iterator list_end
= activeThreads
.end();
1186 unsigned high_thread
= *list_begin
;
1188 activeThreads
.erase(list_begin
);
1190 activeThreads
.push_back(high_thread
);
1194 // Forward declaration of FullO3CPU.
1195 template class FullO3CPU
<AlphaSimpleImpl
>;