cpu.cc (2665:a124942bacb8) cpu.cc (2669:f2b336e89d2a)
1/*
1/*
2 * Copyright (c) 2004-2005 The Regents of The University of Michigan
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

--- 8 unchanged lines hidden (view full) ---

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.
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

--- 8 unchanged lines hidden (view full) ---

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
33#if FULL_SYSTEM
34#include "sim/system.hh"
35#else
36#include "sim/process.hh"
37#endif
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
38#include "sim/root.hh"
39
36
37#include "cpu/activity.hh"
38#include "cpu/checker/cpu.hh"
40#include "cpu/cpu_exec_context.hh"
41#include "cpu/exec_context.hh"
42#include "cpu/o3/alpha_dyn_inst.hh"
43#include "cpu/o3/alpha_impl.hh"
44#include "cpu/o3/cpu.hh"
45
39#include "cpu/cpu_exec_context.hh"
40#include "cpu/exec_context.hh"
41#include "cpu/o3/alpha_dyn_inst.hh"
42#include "cpu/o3/alpha_impl.hh"
43#include "cpu/o3/cpu.hh"
44
45#include "sim/root.hh"
46#include "sim/stat_control.hh"
47
46using namespace std;
48using namespace std;
49using namespace TheISA;
47
50
48BaseFullCPU::BaseFullCPU(Params &params)
49 : BaseCPU(&params), cpu_id(0)
51BaseFullCPU::BaseFullCPU(Params *params)
52 : BaseCPU(params), cpu_id(0)
50{
51}
52
53{
54}
55
56void
57BaseFullCPU::regStats()
58{
59 BaseCPU::regStats();
60}
61
53template <class Impl>
54FullO3CPU<Impl>::TickEvent::TickEvent(FullO3CPU<Impl> *c)
55 : Event(&mainEventQueue, CPU_Tick_Pri), cpu(c)
56{
57}
58
59template <class Impl>
60void

--- 4 unchanged lines hidden (view full) ---

65
66template <class Impl>
67const char *
68FullO3CPU<Impl>::TickEvent::description()
69{
70 return "FullO3CPU tick event";
71}
72
62template <class Impl>
63FullO3CPU<Impl>::TickEvent::TickEvent(FullO3CPU<Impl> *c)
64 : Event(&mainEventQueue, CPU_Tick_Pri), cpu(c)
65{
66}
67
68template <class Impl>
69void

--- 4 unchanged lines hidden (view full) ---

74
75template <class Impl>
76const char *
77FullO3CPU<Impl>::TickEvent::description()
78{
79 return "FullO3CPU tick event";
80}
81
73//Call constructor to all the pipeline stages here
74template <class Impl>
82template <class Impl>
75FullO3CPU<Impl>::FullO3CPU(Params &params)
76#if FULL_SYSTEM
83FullO3CPU<Impl>::FullO3CPU(Params *params)
77 : BaseFullCPU(params),
84 : BaseFullCPU(params),
78#else
79 : BaseFullCPU(params),
80#endif // FULL_SYSTEM
81 tickEvent(this),
85 tickEvent(this),
86 removeInstsThisCycle(false),
82 fetch(params),
83 decode(params),
84 rename(params),
85 iew(params),
86 commit(params),
87
87 fetch(params),
88 decode(params),
89 rename(params),
90 iew(params),
91 commit(params),
92
88 regFile(params.numPhysIntRegs, params.numPhysFloatRegs),
93 regFile(params->numPhysIntRegs, params->numPhysFloatRegs),
89
94
90 freeList(TheISA::NumIntRegs, params.numPhysIntRegs,
91 TheISA::NumFloatRegs, params.numPhysFloatRegs),
95 freeList(params->numberOfThreads,//number of activeThreads
96 TheISA::NumIntRegs, params->numPhysIntRegs,
97 TheISA::NumFloatRegs, params->numPhysFloatRegs),
92
98
93 renameMap(TheISA::NumIntRegs, params.numPhysIntRegs,
94 TheISA::NumFloatRegs, params.numPhysFloatRegs,
95 TheISA::NumMiscRegs,
96 TheISA::ZeroReg,
97 TheISA::ZeroReg + TheISA::NumIntRegs),
99 rob(params->numROBEntries, params->squashWidth,
100 params->smtROBPolicy, params->smtROBThreshold,
101 params->numberOfThreads),
98
102
99 rob(params.numROBEntries, params.squashWidth),
103 scoreboard(params->numberOfThreads,//number of activeThreads
104 TheISA::NumIntRegs, params->numPhysIntRegs,
105 TheISA::NumFloatRegs, params->numPhysFloatRegs,
106 TheISA::NumMiscRegs * number_of_threads,
107 TheISA::ZeroReg),
100
108
101 // What to pass to these time buffers?
102 // For now just have these time buffers be pretty big.
109 // For now just have these time buffers be pretty big.
110 // @todo: Make these time buffer sizes parameters or derived
111 // from latencies
103 timeBuffer(5, 5),
104 fetchQueue(5, 5),
105 decodeQueue(5, 5),
106 renameQueue(5, 5),
107 iewQueue(5, 5),
112 timeBuffer(5, 5),
113 fetchQueue(5, 5),
114 decodeQueue(5, 5),
115 renameQueue(5, 5),
116 iewQueue(5, 5),
117 activityRec(NumStages, 10, params->activity),
108
118
109 cpuXC(NULL),
110
111 globalSeqNum(1),
112
113#if FULL_SYSTEM
119 globalSeqNum(1),
120
121#if FULL_SYSTEM
114 system(params.system),
122 system(params->system),
115 memCtrl(system->memctrl),
116 physmem(system->physmem),
123 memCtrl(system->memctrl),
124 physmem(system->physmem),
117 itb(params.itb),
118 dtb(params.dtb),
119 mem(params.mem),
120#else
121 // Hardcoded for a single thread!!
122 mem(params.workload[0]->getMemory()),
123#endif // FULL_SYSTEM
125#endif // FULL_SYSTEM
124
125 icacheInterface(params.icacheInterface),
126 dcacheInterface(params.dcacheInterface),
127 deferRegistration(params.defReg),
128 numInsts(0),
129 funcExeInst(0)
126 mem(params->mem),
127 switchCount(0),
128 deferRegistration(params->deferRegistration),
129 numThreads(number_of_threads)
130{
131 _status = Idle;
132
130{
131 _status = Idle;
132
133#if !FULL_SYSTEM
134 thread.resize(this->number_of_threads);
135#endif
136
137 for (int i = 0; i < this->number_of_threads; ++i) {
133 if (params->checker) {
134 BaseCPU *temp_checker = params->checker;
135 checker = dynamic_cast<Checker<DynInstPtr> *>(temp_checker);
136 checker->setMemory(mem);
138#if FULL_SYSTEM
137#if FULL_SYSTEM
139 assert(i == 0);
140 thread[i] = new CPUExecContext(this, 0, system, itb, dtb, mem);
141 system->execContexts[i] = thread[i]->getProxy();
142
143 execContexts.push_back(system->execContexts[i]);
144#else
145 if (i < params.workload.size()) {
146 DPRINTF(FullCPU, "FullCPU: Workload[%i]'s starting PC is %#x, "
147 "process is %#x",
148 i, params.workload[i]->prog_entry, thread[i]);
149 thread[i] = new CPUExecContext(this, i, params.workload[i], i);
150 }
151 assert(params.workload[i]->getMemory() != NULL);
152 assert(mem != NULL);
153 execContexts.push_back(thread[i]->getProxy());
154#endif // !FULL_SYSTEM
138 checker->setSystem(params->system);
139#endif
140 } else {
141 checker = NULL;
155 }
156
142 }
143
157 // Note that this is a hack so that my code which still uses xc-> will
158 // still work. I should remove this eventually
159 cpuXC = thread[0];
144#if !FULL_SYSTEM
145 thread.resize(number_of_threads);
146 tids.resize(number_of_threads);
147#endif
160
148
161 // The stages also need their CPU pointer setup. However this must be
162 // done at the upper level CPU because they have pointers to the upper
163 // level CPU, and not this FullO3CPU.
149 // The stages also need their CPU pointer setup. However this
150 // must be done at the upper level CPU because they have pointers
151 // to the upper level CPU, and not this FullO3CPU.
164
152
153 // Set up Pointers to the activeThreads list for each stage
154 fetch.setActiveThreads(&activeThreads);
155 decode.setActiveThreads(&activeThreads);
156 rename.setActiveThreads(&activeThreads);
157 iew.setActiveThreads(&activeThreads);
158 commit.setActiveThreads(&activeThreads);
159
165 // Give each of the stages the time buffer they will use.
166 fetch.setTimeBuffer(&timeBuffer);
167 decode.setTimeBuffer(&timeBuffer);
168 rename.setTimeBuffer(&timeBuffer);
169 iew.setTimeBuffer(&timeBuffer);
170 commit.setTimeBuffer(&timeBuffer);
171
172 // Also setup each of the stages' queues.
173 fetch.setFetchQueue(&fetchQueue);
174 decode.setFetchQueue(&fetchQueue);
160 // Give each of the stages the time buffer they will use.
161 fetch.setTimeBuffer(&timeBuffer);
162 decode.setTimeBuffer(&timeBuffer);
163 rename.setTimeBuffer(&timeBuffer);
164 iew.setTimeBuffer(&timeBuffer);
165 commit.setTimeBuffer(&timeBuffer);
166
167 // Also setup each of the stages' queues.
168 fetch.setFetchQueue(&fetchQueue);
169 decode.setFetchQueue(&fetchQueue);
170 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
171 decode.setDecodeQueue(&decodeQueue);
172 rename.setDecodeQueue(&decodeQueue);
173 rename.setRenameQueue(&renameQueue);
174 iew.setRenameQueue(&renameQueue);
175 iew.setIEWQueue(&iewQueue);
176 commit.setIEWQueue(&iewQueue);
177 commit.setRenameQueue(&renameQueue);
178
179 commit.setFetchStage(&fetch);
180 commit.setIEWStage(&iew);
181 rename.setIEWStage(&iew);
182 rename.setCommitStage(&commit);
183
184#if !FULL_SYSTEM
185 int active_threads = params->workload.size();
186#else
187 int active_threads = 1;
188#endif
189
190 //Make Sure That this a Valid Architeture
191 assert(params->numPhysIntRegs >= numThreads * TheISA::NumIntRegs);
192 assert(params->numPhysFloatRegs >= numThreads * TheISA::NumFloatRegs);
193
194 rename.setScoreboard(&scoreboard);
195 iew.setScoreboard(&scoreboard);
196
183 // Setup the rename map for whichever stages need it.
197 // Setup the rename map for whichever stages need it.
184 rename.setRenameMap(&renameMap);
185 iew.setRenameMap(&renameMap);
198 PhysRegIndex lreg_idx = 0;
199 PhysRegIndex freg_idx = params->numPhysIntRegs; //Index to 1 after int regs
186
200
187 // Setup the free list for whichever stages need it.
201 for (int tid=0; tid < numThreads; tid++) {
202 bool bindRegs = (tid <= active_threads - 1);
203
204 commitRenameMap[tid].init(TheISA::NumIntRegs,
205 params->numPhysIntRegs,
206 lreg_idx, //Index for Logical. Regs
207
208 TheISA::NumFloatRegs,
209 params->numPhysFloatRegs,
210 freg_idx, //Index for Float Regs
211
212 TheISA::NumMiscRegs,
213
214 TheISA::ZeroReg,
215 TheISA::ZeroReg,
216
217 tid,
218 false);
219
220 renameMap[tid].init(TheISA::NumIntRegs,
221 params->numPhysIntRegs,
222 lreg_idx, //Index for Logical. Regs
223
224 TheISA::NumFloatRegs,
225 params->numPhysFloatRegs,
226 freg_idx, //Index for Float Regs
227
228 TheISA::NumMiscRegs,
229
230 TheISA::ZeroReg,
231 TheISA::ZeroReg,
232
233 tid,
234 bindRegs);
235 }
236
237 rename.setRenameMap(renameMap);
238 commit.setRenameMap(commitRenameMap);
239
240 // Give renameMap & rename stage access to the freeList;
241 for (int i=0; i < numThreads; i++) {
242 renameMap[i].setFreeList(&freeList);
243 }
188 rename.setFreeList(&freeList);
244 rename.setFreeList(&freeList);
189 renameMap.setFreeList(&freeList);
190
245
246 // Setup the page table for whichever stages need it.
247#if !FULL_SYSTEM
248// fetch.setPageTable(pTable);
249// iew.setPageTable(pTable);
250#endif
251
191 // Setup the ROB for whichever stages need it.
192 commit.setROB(&rob);
252 // Setup the ROB for whichever stages need it.
253 commit.setROB(&rob);
254
255 lastRunningCycle = curTick;
256
257 contextSwitch = false;
193}
194
195template <class Impl>
196FullO3CPU<Impl>::~FullO3CPU()
197{
198}
199
200template <class Impl>
201void
202FullO3CPU<Impl>::fullCPURegStats()
203{
258}
259
260template <class Impl>
261FullO3CPU<Impl>::~FullO3CPU()
262{
263}
264
265template <class Impl>
266void
267FullO3CPU<Impl>::fullCPURegStats()
268{
269 BaseFullCPU::regStats();
270
204 // Register any of the FullCPU's stats here.
271 // Register any of the FullCPU's stats here.
272 timesIdled
273 .name(name() + ".timesIdled")
274 .desc("Number of times that the entire CPU went into an idle state and"
275 " unscheduled itself")
276 .prereq(timesIdled);
277
278 idleCycles
279 .name(name() + ".idleCycles")
280 .desc("Total number of cycles that the CPU has spent unscheduled due "
281 "to idling")
282 .prereq(idleCycles);
283
284 // Number of Instructions simulated
285 // --------------------------------
286 // Should probably be in Base CPU but need templated
287 // MaxThreads so put in here instead
288 committedInsts
289 .init(numThreads)
290 .name(name() + ".committedInsts")
291 .desc("Number of Instructions Simulated");
292
293 totalCommittedInsts
294 .name(name() + ".committedInsts_total")
295 .desc("Number of Instructions Simulated");
296
297 cpi
298 .name(name() + ".cpi")
299 .desc("CPI: Cycles Per Instruction")
300 .precision(6);
301 cpi = simTicks / committedInsts;
302
303 totalCpi
304 .name(name() + ".cpi_total")
305 .desc("CPI: Total CPI of All Threads")
306 .precision(6);
307 totalCpi = simTicks / totalCommittedInsts;
308
309 ipc
310 .name(name() + ".ipc")
311 .desc("IPC: Instructions Per Cycle")
312 .precision(6);
313 ipc = committedInsts / simTicks;
314
315 totalIpc
316 .name(name() + ".ipc_total")
317 .desc("IPC: Total IPC of All Threads")
318 .precision(6);
319 totalIpc = totalCommittedInsts / simTicks;
320
205}
206
207template <class Impl>
208void
209FullO3CPU<Impl>::tick()
210{
211 DPRINTF(FullCPU, "\n\nFullCPU: Ticking main, FullO3CPU.\n");
212
321}
322
323template <class Impl>
324void
325FullO3CPU<Impl>::tick()
326{
327 DPRINTF(FullCPU, "\n\nFullCPU: Ticking main, FullO3CPU.\n");
328
213 //Tick each of the stages if they're actually running.
214 //Will want to figure out a way to unschedule itself if they're all
215 //going to be idle for a long time.
329 ++numCycles;
330
331// activity = false;
332
333 //Tick each of the stages
216 fetch.tick();
217
218 decode.tick();
219
220 rename.tick();
221
222 iew.tick();
223
224 commit.tick();
225
334 fetch.tick();
335
336 decode.tick();
337
338 rename.tick();
339
340 iew.tick();
341
342 commit.tick();
343
226 // Now advance the time buffers, unless the stage is stalled.
344#if !FULL_SYSTEM
345 doContextSwitch();
346#endif
347
348 // Now advance the time buffers
227 timeBuffer.advance();
228
229 fetchQueue.advance();
230 decodeQueue.advance();
231 renameQueue.advance();
232 iewQueue.advance();
233
349 timeBuffer.advance();
350
351 fetchQueue.advance();
352 decodeQueue.advance();
353 renameQueue.advance();
354 iewQueue.advance();
355
234 if (_status == Running && !tickEvent.scheduled())
235 tickEvent.schedule(curTick + 1);
356 activityRec.advance();
357
358 if (removeInstsThisCycle) {
359 cleanUpRemovedInsts();
360 }
361
362 if (!tickEvent.scheduled()) {
363 if (_status == SwitchedOut) {
364 // increment stat
365 lastRunningCycle = curTick;
366 } else if (!activityRec.active()) {
367 lastRunningCycle = curTick;
368 timesIdled++;
369 } else {
370 tickEvent.schedule(curTick + cycles(1));
371 }
372 }
373
374#if !FULL_SYSTEM
375 updateThreadPriority();
376#endif
377
236}
237
238template <class Impl>
239void
240FullO3CPU<Impl>::init()
241{
378}
379
380template <class Impl>
381void
382FullO3CPU<Impl>::init()
383{
242 if(!deferRegistration)
243 {
244 this->registerExecContexts();
384 if (!deferRegistration) {
385 registerExecContexts();
386 }
245
387
246 // Need to do a copy of the xc->regs into the CPU's regfile so
247 // that it can start properly.
388 // Set inSyscall so that the CPU doesn't squash when initially
389 // setting up registers.
390 for (int i = 0; i < number_of_threads; ++i)
391 thread[i]->inSyscall = true;
392
393 for (int tid=0; tid < number_of_threads; tid++) {
248#if FULL_SYSTEM
394#if FULL_SYSTEM
249 ExecContext *src_xc = system->execContexts[0];
250 TheISA::initCPU(src_xc, src_xc->readCpuId());
395 ExecContext *src_xc = execContexts[tid];
251#else
396#else
252 ExecContext *src_xc = thread[0]->getProxy();
397 ExecContext *src_xc = thread[tid]->getXCProxy();
253#endif
398#endif
254 // First loop through the integer registers.
255 for (int i = 0; i < TheISA::NumIntRegs; ++i)
256 {
257 regFile.intRegFile[i] = src_xc->readIntReg(i);
399 // Threads start in the Suspended State
400 if (src_xc->status() != ExecContext::Suspended) {
401 continue;
258 }
259
402 }
403
260 // Then loop through the floating point registers.
261 for (int i = 0; i < TheISA::NumFloatRegs; ++i)
262 {
263 regFile.floatRegFile.setRegBits(i, src_xc->readRegBits(i))
264 }
265/*
266 // Then loop through the misc registers.
267 regFile.miscRegs.fpcr = src_xc->regs.miscRegs.fpcr;
268 regFile.miscRegs.uniq = src_xc->regs.miscRegs.uniq;
269 regFile.miscRegs.lock_flag = src_xc->regs.miscRegs.lock_flag;
270 regFile.miscRegs.lock_addr = src_xc->regs.miscRegs.lock_addr;
271*/
272 // Then finally set the PC and the next PC.
273 regFile.pc = src_xc->readPC();
274 regFile.npc = src_xc->readNextPC();
404#if FULL_SYSTEM
405 TheISA::initCPU(src_xc, src_xc->readCpuId());
406#endif
275 }
407 }
408
409 // Clear inSyscall.
410 for (int i = 0; i < number_of_threads; ++i)
411 thread[i]->inSyscall = false;
412
413 // Initialize stages.
414 fetch.initStage();
415 iew.initStage();
416 rename.initStage();
417 commit.initStage();
418
419 commit.setThreads(thread);
276}
277
278template <class Impl>
279void
420}
421
422template <class Impl>
423void
280FullO3CPU<Impl>::activateContext(int thread_num, int delay)
424FullO3CPU<Impl>::insertThread(unsigned tid)
281{
425{
426 DPRINTF(FullCPU,"[tid:%i] Initializing thread data");
427 // Will change now that the PC and thread state is internal to the CPU
428 // and not in the CPUExecContext.
429#if 0
430#if FULL_SYSTEM
431 ExecContext *src_xc = system->execContexts[tid];
432#else
433 CPUExecContext *src_xc = thread[tid];
434#endif
435
436 //Bind Int Regs to Rename Map
437 for (int ireg = 0; ireg < TheISA::NumIntRegs; ireg++) {
438 PhysRegIndex phys_reg = freeList.getIntReg();
439
440 renameMap[tid].setEntry(ireg,phys_reg);
441 scoreboard.setReg(phys_reg);
442 }
443
444 //Bind Float Regs to Rename Map
445 for (int freg = 0; freg < TheISA::NumFloatRegs; freg++) {
446 PhysRegIndex phys_reg = freeList.getFloatReg();
447
448 renameMap[tid].setEntry(freg,phys_reg);
449 scoreboard.setReg(phys_reg);
450 }
451
452 //Copy Thread Data Into RegFile
453 this->copyFromXC(tid);
454
455 //Set PC/NPC
456 regFile.pc[tid] = src_xc->readPC();
457 regFile.npc[tid] = src_xc->readNextPC();
458
459 src_xc->setStatus(ExecContext::Active);
460
461 activateContext(tid,1);
462
463 //Reset ROB/IQ/LSQ Entries
464 commit.rob->resetEntries();
465 iew.resetEntries();
466#endif
467}
468
469template <class Impl>
470void
471FullO3CPU<Impl>::removeThread(unsigned tid)
472{
473 DPRINTF(FullCPU,"[tid:%i] Removing thread data");
474#if 0
475 //Unbind Int Regs from Rename Map
476 for (int ireg = 0; ireg < TheISA::NumIntRegs; ireg++) {
477 PhysRegIndex phys_reg = renameMap[tid].lookup(ireg);
478
479 scoreboard.unsetReg(phys_reg);
480 freeList.addReg(phys_reg);
481 }
482
483 //Unbind Float Regs from Rename Map
484 for (int freg = 0; freg < TheISA::NumFloatRegs; freg++) {
485 PhysRegIndex phys_reg = renameMap[tid].lookup(freg);
486
487 scoreboard.unsetReg(phys_reg);
488 freeList.addReg(phys_reg);
489 }
490
491 //Copy Thread Data From RegFile
492 /* Fix Me:
493 * Do we really need to do this if we are removing a thread
494 * in the sense that it's finished (exiting)? If the thread is just
495 * being suspended we might...
496 */
497// this->copyToXC(tid);
498
499 //Squash Throughout Pipeline
500 fetch.squash(0,tid);
501 decode.squash(tid);
502 rename.squash(tid);
503
504 assert(iew.ldstQueue.getCount(tid) == 0);
505
506 //Reset ROB/IQ/LSQ Entries
507 if (activeThreads.size() >= 1) {
508 commit.rob->resetEntries();
509 iew.resetEntries();
510 }
511#endif
512}
513
514
515template <class Impl>
516void
517FullO3CPU<Impl>::activateWhenReady(int tid)
518{
519 DPRINTF(FullCPU,"[tid:%i]: Checking if resources are available for incoming"
520 "(e.g. PhysRegs/ROB/IQ/LSQ) \n",
521 tid);
522
523 bool ready = true;
524
525 if (freeList.numFreeIntRegs() >= TheISA::NumIntRegs) {
526 DPRINTF(FullCPU,"[tid:%i] Suspending thread due to not enough "
527 "Phys. Int. Regs.\n",
528 tid);
529 ready = false;
530 } else if (freeList.numFreeFloatRegs() >= TheISA::NumFloatRegs) {
531 DPRINTF(FullCPU,"[tid:%i] Suspending thread due to not enough "
532 "Phys. Float. Regs.\n",
533 tid);
534 ready = false;
535 } else if (commit.rob->numFreeEntries() >=
536 commit.rob->entryAmount(activeThreads.size() + 1)) {
537 DPRINTF(FullCPU,"[tid:%i] Suspending thread due to not enough "
538 "ROB entries.\n",
539 tid);
540 ready = false;
541 } else if (iew.instQueue.numFreeEntries() >=
542 iew.instQueue.entryAmount(activeThreads.size() + 1)) {
543 DPRINTF(FullCPU,"[tid:%i] Suspending thread due to not enough "
544 "IQ entries.\n",
545 tid);
546 ready = false;
547 } else if (iew.ldstQueue.numFreeEntries() >=
548 iew.ldstQueue.entryAmount(activeThreads.size() + 1)) {
549 DPRINTF(FullCPU,"[tid:%i] Suspending thread due to not enough "
550 "LSQ entries.\n",
551 tid);
552 ready = false;
553 }
554
555 if (ready) {
556 insertThread(tid);
557
558 contextSwitch = false;
559
560 cpuWaitList.remove(tid);
561 } else {
562 suspendContext(tid);
563
564 //blocks fetch
565 contextSwitch = true;
566
567 //do waitlist
568 cpuWaitList.push_back(tid);
569 }
570}
571
572template <class Impl>
573void
574FullO3CPU<Impl>::activateContext(int tid, int delay)
575{
282 // Needs to set each stage to running as well.
576 // Needs to set each stage to running as well.
577 list<unsigned>::iterator isActive = find(
578 activeThreads.begin(), activeThreads.end(), tid);
283
579
580 if (isActive == activeThreads.end()) {
581 //May Need to Re-code this if the delay variable is the
582 //delay needed for thread to activate
583 DPRINTF(FullCPU, "Adding Thread %i to active threads list\n",
584 tid);
585
586 activeThreads.push_back(tid);
587 }
588
589 assert(_status == Idle || _status == SwitchedOut);
590
284 scheduleTickEvent(delay);
285
591 scheduleTickEvent(delay);
592
593 // Be sure to signal that there's some activity so the CPU doesn't
594 // deschedule itself.
595 activityRec.activity();
596 fetch.wakeFromQuiesce();
597
286 _status = Running;
287}
288
289template <class Impl>
290void
598 _status = Running;
599}
600
601template <class Impl>
602void
291FullO3CPU<Impl>::suspendContext(int thread_num)
603FullO3CPU<Impl>::suspendContext(int tid)
292{
604{
293 panic("suspendContext unimplemented!");
605 DPRINTF(FullCPU,"[tid: %i]: Suspended ...\n", tid);
606 unscheduleTickEvent();
607 _status = Idle;
608/*
609 //Remove From Active List, if Active
610 list<unsigned>::iterator isActive = find(
611 activeThreads.begin(), activeThreads.end(), tid);
612
613 if (isActive != activeThreads.end()) {
614 DPRINTF(FullCPU,"[tid:%i]: Removing from active threads list\n",
615 tid);
616 activeThreads.erase(isActive);
617 }
618*/
294}
295
296template <class Impl>
297void
619}
620
621template <class Impl>
622void
298FullO3CPU<Impl>::deallocateContext(int thread_num)
623FullO3CPU<Impl>::deallocateContext(int tid)
299{
624{
300 panic("deallocateContext unimplemented!");
625 DPRINTF(FullCPU,"[tid:%i]: Deallocating ...", tid);
626/*
627 //Remove From Active List, if Active
628 list<unsigned>::iterator isActive = find(
629 activeThreads.begin(), activeThreads.end(), tid);
630
631 if (isActive != activeThreads.end()) {
632 DPRINTF(FullCPU,"[tid:%i]: Removing from active threads list\n",
633 tid);
634 activeThreads.erase(isActive);
635
636 removeThread(tid);
637 }
638*/
301}
302
303template <class Impl>
304void
639}
640
641template <class Impl>
642void
305FullO3CPU<Impl>::haltContext(int thread_num)
643FullO3CPU<Impl>::haltContext(int tid)
306{
644{
307 panic("haltContext unimplemented!");
645 DPRINTF(FullCPU,"[tid:%i]: Halted ...", tid);
646/*
647 //Remove From Active List, if Active
648 list<unsigned>::iterator isActive = find(
649 activeThreads.begin(), activeThreads.end(), tid);
650
651 if (isActive != activeThreads.end()) {
652 DPRINTF(FullCPU,"[tid:%i]: Removing from active threads list\n",
653 tid);
654 activeThreads.erase(isActive);
655
656 removeThread(tid);
657 }
658*/
308}
309
310template <class Impl>
311void
659}
660
661template <class Impl>
662void
312FullO3CPU::switchOut()
663FullO3CPU<Impl>::switchOut(Sampler *_sampler)
313{
664{
314 panic("FullO3CPU does not have a switch out function.\n");
665 sampler = _sampler;
666 switchCount = 0;
667 fetch.switchOut();
668 decode.switchOut();
669 rename.switchOut();
670 iew.switchOut();
671 commit.switchOut();
672
673 // Wake the CPU and record activity so everything can drain out if
674 // the CPU is currently idle.
675 wakeCPU();
676 activityRec.activity();
315}
316
317template <class Impl>
318void
677}
678
679template <class Impl>
680void
681FullO3CPU<Impl>::signalSwitched()
682{
683 if (++switchCount == NumStages) {
684 fetch.doSwitchOut();
685 rename.doSwitchOut();
686 commit.doSwitchOut();
687 instList.clear();
688 while (!removeList.empty()) {
689 removeList.pop();
690 }
691
692 if (checker)
693 checker->switchOut(sampler);
694
695 if (tickEvent.scheduled())
696 tickEvent.squash();
697 sampler->signalSwitched();
698 _status = SwitchedOut;
699 }
700 assert(switchCount <= 5);
701}
702
703template <class Impl>
704void
319FullO3CPU<Impl>::takeOverFrom(BaseCPU *oldCPU)
320{
705FullO3CPU<Impl>::takeOverFrom(BaseCPU *oldCPU)
706{
707 // Flush out any old data from the time buffers.
708 for (int i = 0; i < 10; ++i) {
709 timeBuffer.advance();
710 fetchQueue.advance();
711 decodeQueue.advance();
712 renameQueue.advance();
713 iewQueue.advance();
714 }
715
716 activityRec.reset();
717
321 BaseCPU::takeOverFrom(oldCPU);
322
718 BaseCPU::takeOverFrom(oldCPU);
719
720 fetch.takeOverFrom();
721 decode.takeOverFrom();
722 rename.takeOverFrom();
723 iew.takeOverFrom();
724 commit.takeOverFrom();
725
323 assert(!tickEvent.scheduled());
324
726 assert(!tickEvent.scheduled());
727
325 // Set all status's to active, schedule the
326 // CPU's tick event.
728 // @todo: Figure out how to properly select the tid to put onto
729 // the active threads list.
730 int tid = 0;
731
732 list<unsigned>::iterator isActive = find(
733 activeThreads.begin(), activeThreads.end(), tid);
734
735 if (isActive == activeThreads.end()) {
736 //May Need to Re-code this if the delay variable is the delay
737 //needed for thread to activate
738 DPRINTF(FullCPU, "Adding Thread %i to active threads list\n",
739 tid);
740
741 activeThreads.push_back(tid);
742 }
743
744 // Set all statuses to active, schedule the CPU's tick event.
745 // @todo: Fix up statuses so this is handled properly
327 for (int i = 0; i < execContexts.size(); ++i) {
328 ExecContext *xc = execContexts[i];
329 if (xc->status() == ExecContext::Active && _status != Running) {
330 _status = Running;
331 tickEvent.schedule(curTick);
332 }
333 }
746 for (int i = 0; i < execContexts.size(); ++i) {
747 ExecContext *xc = execContexts[i];
748 if (xc->status() == ExecContext::Active && _status != Running) {
749 _status = Running;
750 tickEvent.schedule(curTick);
751 }
752 }
753 if (!tickEvent.scheduled())
754 tickEvent.schedule(curTick);
334}
335
336template <class Impl>
755}
756
757template <class Impl>
337InstSeqNum
338FullO3CPU<Impl>::getAndIncrementInstSeq()
339{
340 // Hopefully this works right.
341 return globalSeqNum++;
342}
343
344template <class Impl>
345uint64_t
346FullO3CPU<Impl>::readIntReg(int reg_idx)
347{
348 return regFile.readIntReg(reg_idx);
349}
350
351template <class Impl>
352FloatReg

--- 55 unchanged lines hidden (view full) ---

408void
409FullO3CPU<Impl>::setFloatRegBits(int reg_idx, FloatRegBits val)
410{
411 regFile.setFloatRegBits(reg_idx, val);
412}
413
414template <class Impl>
415uint64_t
758uint64_t
759FullO3CPU<Impl>::readIntReg(int reg_idx)
760{
761 return regFile.readIntReg(reg_idx);
762}
763
764template <class Impl>
765FloatReg

--- 55 unchanged lines hidden (view full) ---

821void
822FullO3CPU<Impl>::setFloatRegBits(int reg_idx, FloatRegBits val)
823{
824 regFile.setFloatRegBits(reg_idx, val);
825}
826
827template <class Impl>
828uint64_t
416FullO3CPU<Impl>::readPC()
829FullO3CPU<Impl>::readArchIntReg(int reg_idx, unsigned tid)
417{
830{
418 return regFile.readPC();
831 PhysRegIndex phys_reg = commitRenameMap[tid].lookup(reg_idx);
832
833 return regFile.readIntReg(phys_reg);
419}
420
421template <class Impl>
834}
835
836template <class Impl>
837float
838FullO3CPU<Impl>::readArchFloatRegSingle(int reg_idx, unsigned tid)
839{
840 int idx = reg_idx + TheISA::FP_Base_DepTag;
841 PhysRegIndex phys_reg = commitRenameMap[tid].lookup(idx);
842
843 return regFile.readFloatReg(phys_reg);
844}
845
846template <class Impl>
847double
848FullO3CPU<Impl>::readArchFloatRegDouble(int reg_idx, unsigned tid)
849{
850 int idx = reg_idx + TheISA::FP_Base_DepTag;
851 PhysRegIndex phys_reg = commitRenameMap[tid].lookup(idx);
852
853 return regFile.readFloatReg(phys_reg, 64);
854}
855
856template <class Impl>
857uint64_t
858FullO3CPU<Impl>::readArchFloatRegInt(int reg_idx, unsigned tid)
859{
860 int idx = reg_idx + TheISA::FP_Base_DepTag;
861 PhysRegIndex phys_reg = commitRenameMap[tid].lookup(idx);
862
863 return regFile.readFloatRegBits(phys_reg);
864}
865
866template <class Impl>
422void
867void
423FullO3CPU<Impl>::setNextPC(uint64_t val)
868FullO3CPU<Impl>::setArchIntReg(int reg_idx, uint64_t val, unsigned tid)
424{
869{
425 regFile.setNextPC(val);
870 PhysRegIndex phys_reg = commitRenameMap[tid].lookup(reg_idx);
871
872 regFile.setIntReg(phys_reg, val);
426}
427
428template <class Impl>
429void
873}
874
875template <class Impl>
876void
430FullO3CPU<Impl>::setPC(Addr new_PC)
877FullO3CPU<Impl>::setArchFloatRegSingle(int reg_idx, float val, unsigned tid)
431{
878{
432 regFile.setPC(new_PC);
879 PhysRegIndex phys_reg = commitRenameMap[tid].lookup(reg_idx);
880
881 regFile.setFloatReg(phys_reg, val);
433}
434
435template <class Impl>
436void
882}
883
884template <class Impl>
885void
437FullO3CPU<Impl>::addInst(DynInstPtr &inst)
886FullO3CPU<Impl>::setArchFloatRegDouble(int reg_idx, double val, unsigned tid)
438{
887{
439 instList.push_back(inst);
888 PhysRegIndex phys_reg = commitRenameMap[tid].lookup(reg_idx);
889
890 regFile.setFloatReg(phys_reg, val, 64);
440}
441
442template <class Impl>
443void
891}
892
893template <class Impl>
894void
444FullO3CPU<Impl>::instDone()
895FullO3CPU<Impl>::setArchFloatRegInt(int reg_idx, uint64_t val, unsigned tid)
445{
896{
446 // Keep an instruction count.
447 numInsts++;
897 PhysRegIndex phys_reg = commitRenameMap[tid].lookup(reg_idx);
448
898
449 // Check for instruction-count-based events.
450 comInstEventQueue[0]->serviceEvents(numInsts);
899 regFile.setFloatRegBits(phys_reg, val);
451}
452
453template <class Impl>
900}
901
902template <class Impl>
903uint64_t
904FullO3CPU<Impl>::readPC(unsigned tid)
905{
906 return commit.readPC(tid);
907}
908
909template <class Impl>
454void
910void
455FullO3CPU<Impl>::removeBackInst(DynInstPtr &inst)
911FullO3CPU<Impl>::setPC(Addr new_PC,unsigned tid)
456{
912{
457 DynInstPtr inst_to_delete;
913 commit.setPC(new_PC, tid);
914}
458
915
459 // Walk through the instruction list, removing any instructions
460 // that were inserted after the given instruction, inst.
461 while (instList.back() != inst)
462 {
463 assert(!instList.empty());
916template <class Impl>
917uint64_t
918FullO3CPU<Impl>::readNextPC(unsigned tid)
919{
920 return commit.readNextPC(tid);
921}
464
922
465 // Obtain the pointer to the instruction.
466 inst_to_delete = instList.back();
923template <class Impl>
924void
925FullO3CPU<Impl>::setNextPC(uint64_t val,unsigned tid)
926{
927 commit.setNextPC(val, tid);
928}
467
929
468 DPRINTF(FullCPU, "FullCPU: Removing instruction %i, PC %#x\n",
469 inst_to_delete->seqNum, inst_to_delete->readPC());
930template <class Impl>
931typename FullO3CPU<Impl>::ListIt
932FullO3CPU<Impl>::addInst(DynInstPtr &inst)
933{
934 instList.push_back(inst);
470
935
471 // Remove the instruction from the list.
472 instList.pop_back();
936 return --(instList.end());
937}
473
938
474 // Mark it as squashed.
475 inst_to_delete->setSquashed();
476 }
939template <class Impl>
940void
941FullO3CPU<Impl>::instDone(unsigned tid)
942{
943 // Keep an instruction count.
944 thread[tid]->numInst++;
945 thread[tid]->numInsts++;
946 committedInsts[tid]++;
947 totalCommittedInsts++;
948
949 // Check for instruction-count-based events.
950 comInstEventQueue[tid]->serviceEvents(thread[tid]->numInst);
477}
478
479template <class Impl>
480void
951}
952
953template <class Impl>
954void
955FullO3CPU<Impl>::addToRemoveList(DynInstPtr &inst)
956{
957 removeInstsThisCycle = true;
958
959 removeList.push(inst->getInstListIt());
960}
961
962template <class Impl>
963void
481FullO3CPU<Impl>::removeFrontInst(DynInstPtr &inst)
482{
964FullO3CPU<Impl>::removeFrontInst(DynInstPtr &inst)
965{
483 DynInstPtr inst_to_remove;
966 DPRINTF(FullCPU, "FullCPU: Removing committed instruction [tid:%i] PC %#x "
967 "[sn:%lli]\n",
968 inst->threadNumber, inst->readPC(), inst->seqNum);
484
969
485 // The front instruction should be the same one being asked to be removed.
486 assert(instList.front() == inst);
970 removeInstsThisCycle = true;
487
488 // Remove the front instruction.
971
972 // Remove the front instruction.
489 inst_to_remove = inst;
490 instList.pop_front();
491
492 DPRINTF(FullCPU, "FullCPU: Removing committed instruction %#x, PC %#x\n",
493 inst_to_remove, inst_to_remove->readPC());
973 removeList.push(inst->getInstListIt());
494}
495
496template <class Impl>
497void
974}
975
976template <class Impl>
977void
498FullO3CPU::removeInstsNotInROB()
978FullO3CPU<Impl>::removeInstsNotInROB(unsigned tid)
499{
979{
500 DPRINTF(FullCPU, "FullCPU: Deleting instructions from instruction "
501 "list.\n");
980 DPRINTF(FullCPU, "FullCPU: Thread %i: Deleting instructions from instruction"
981 " list.\n", tid);
502
982
503 DynInstPtr rob_tail = rob.readTailInst();
983 ListIt end_it;
504
984
505 removeBackInst(rob_tail);
985 bool rob_empty = false;
986
987 if (instList.empty()) {
988 return;
989 } else if (rob.isEmpty(/*tid*/)) {
990 DPRINTF(FullCPU, "FullCPU: ROB is empty, squashing all insts.\n");
991 end_it = instList.begin();
992 rob_empty = true;
993 } else {
994 end_it = (rob.readTailInst(tid))->getInstListIt();
995 DPRINTF(FullCPU, "FullCPU: ROB is not empty, squashing insts not in ROB.\n");
996 }
997
998 removeInstsThisCycle = true;
999
1000 ListIt inst_it = instList.end();
1001
1002 inst_it--;
1003
1004 // Walk through the instruction list, removing any instructions
1005 // that were inserted after the given instruction iterator, end_it.
1006 while (inst_it != end_it) {
1007 assert(!instList.empty());
1008
1009 squashInstIt(inst_it, tid);
1010
1011 inst_it--;
1012 }
1013
1014 // If the ROB was empty, then we actually need to remove the first
1015 // instruction as well.
1016 if (rob_empty) {
1017 squashInstIt(inst_it, tid);
1018 }
506}
507
508template <class Impl>
509void
1019}
1020
1021template <class Impl>
1022void
510FullO3CPU<Impl>::removeInstsUntil(const InstSeqNum &seq_num)
1023FullO3CPU<Impl>::removeInstsUntil(const InstSeqNum &seq_num,
1024 unsigned tid)
511{
1025{
1026 assert(!instList.empty());
1027
1028 removeInstsThisCycle = true;
1029
1030 ListIt inst_iter = instList.end();
1031
1032 inst_iter--;
1033
512 DPRINTF(FullCPU, "FullCPU: Deleting instructions from instruction "
1034 DPRINTF(FullCPU, "FullCPU: Deleting instructions from instruction "
513 "list.\n");
1035 "list that are from [tid:%i] and above [sn:%lli] (end=%lli).\n",
1036 tid, seq_num, (*inst_iter)->seqNum);
514
1037
515 DynInstPtr inst_to_delete;
1038 while ((*inst_iter)->seqNum > seq_num) {
516
1039
517 while (instList.back()->seqNum > seq_num) {
518 assert(!instList.empty());
1040 bool break_loop = (inst_iter == instList.begin());
519
1041
520 // Obtain the pointer to the instruction.
521 inst_to_delete = instList.back();
1042 squashInstIt(inst_iter, tid);
522
1043
523 DPRINTF(FullCPU, "FullCPU: Removing instruction %i, PC %#x\n",
524 inst_to_delete->seqNum, inst_to_delete->readPC());
1044 inst_iter--;
525
1045
526 // Remove the instruction from the list.
527 instList.back() = NULL;
528 instList.pop_back();
1046 if (break_loop)
1047 break;
1048 }
1049}
529
1050
1051template <class Impl>
1052inline void
1053FullO3CPU<Impl>::squashInstIt(const ListIt &instIt, const unsigned &tid)
1054{
1055 if ((*instIt)->threadNumber == tid) {
1056 DPRINTF(FullCPU, "FullCPU: Squashing instruction, "
1057 "[tid:%i] [sn:%lli] PC %#x\n",
1058 (*instIt)->threadNumber,
1059 (*instIt)->seqNum,
1060 (*instIt)->readPC());
1061
530 // Mark it as squashed.
1062 // Mark it as squashed.
531 inst_to_delete->setSquashed();
532 }
1063 (*instIt)->setSquashed();
533
1064
1065 // @todo: Formulate a consistent method for deleting
1066 // instructions from the instruction list
1067 // Remove the instruction from the list.
1068 removeList.push(instIt);
1069 }
534}
535
536template <class Impl>
537void
1070}
1071
1072template <class Impl>
1073void
1074FullO3CPU<Impl>::cleanUpRemovedInsts()
1075{
1076 while (!removeList.empty()) {
1077 DPRINTF(FullCPU, "FullCPU: Removing instruction, "
1078 "[tid:%i] [sn:%lli] PC %#x\n",
1079 (*removeList.front())->threadNumber,
1080 (*removeList.front())->seqNum,
1081 (*removeList.front())->readPC());
1082
1083 instList.erase(removeList.front());
1084
1085 removeList.pop();
1086 }
1087
1088 removeInstsThisCycle = false;
1089}
1090/*
1091template <class Impl>
1092void
538FullO3CPU<Impl>::removeAllInsts()
539{
540 instList.clear();
541}
1093FullO3CPU<Impl>::removeAllInsts()
1094{
1095 instList.clear();
1096}
542
1097*/
543template <class Impl>
544void
545FullO3CPU<Impl>::dumpInsts()
546{
547 int num = 0;
1098template <class Impl>
1099void
1100FullO3CPU<Impl>::dumpInsts()
1101{
1102 int num = 0;
548 typename list<DynInstPtr>::iterator inst_list_it = instList.begin();
549
1103
550 while (inst_list_it != instList.end())
551 {
552 cprintf("Instruction:%i\nPC:%#x\nSN:%lli\nIssued:%i\nSquashed:%i\n\n",
553 num, (*inst_list_it)->readPC(), (*inst_list_it)->seqNum,
554 (*inst_list_it)->isIssued(), (*inst_list_it)->isSquashed());
1104 ListIt inst_list_it = instList.begin();
1105
1106 cprintf("Dumping Instruction List\n");
1107
1108 while (inst_list_it != instList.end()) {
1109 cprintf("Instruction:%i\nPC:%#x\n[tid:%i]\n[sn:%lli]\nIssued:%i\n"
1110 "Squashed:%i\n\n",
1111 num, (*inst_list_it)->readPC(), (*inst_list_it)->threadNumber,
1112 (*inst_list_it)->seqNum, (*inst_list_it)->isIssued(),
1113 (*inst_list_it)->isSquashed());
555 inst_list_it++;
556 ++num;
557 }
558}
1114 inst_list_it++;
1115 ++num;
1116 }
1117}
559
1118/*
560template <class Impl>
561void
562FullO3CPU<Impl>::wakeDependents(DynInstPtr &inst)
563{
564 iew.wakeDependents(inst);
565}
1119template <class Impl>
1120void
1121FullO3CPU<Impl>::wakeDependents(DynInstPtr &inst)
1122{
1123 iew.wakeDependents(inst);
1124}
1125*/
1126template <class Impl>
1127void
1128FullO3CPU<Impl>::wakeCPU()
1129{
1130 if (activityRec.active() || tickEvent.scheduled()) {
1131 DPRINTF(Activity, "CPU already running.\n");
1132 return;
1133 }
566
1134
1135 DPRINTF(Activity, "Waking up CPU\n");
1136
1137 idleCycles += (curTick - 1) - lastRunningCycle;
1138
1139 tickEvent.schedule(curTick);
1140}
1141
1142template <class Impl>
1143int
1144FullO3CPU<Impl>::getFreeTid()
1145{
1146 for (int i=0; i < numThreads; i++) {
1147 if (!tids[i]) {
1148 tids[i] = true;
1149 return i;
1150 }
1151 }
1152
1153 return -1;
1154}
1155
1156template <class Impl>
1157void
1158FullO3CPU<Impl>::doContextSwitch()
1159{
1160 if (contextSwitch) {
1161
1162 //ADD CODE TO DEACTIVE THREAD HERE (???)
1163
1164 for (int tid=0; tid < cpuWaitList.size(); tid++) {
1165 activateWhenReady(tid);
1166 }
1167
1168 if (cpuWaitList.size() == 0)
1169 contextSwitch = true;
1170 }
1171}
1172
1173template <class Impl>
1174void
1175FullO3CPU<Impl>::updateThreadPriority()
1176{
1177 if (activeThreads.size() > 1)
1178 {
1179 //DEFAULT TO ROUND ROBIN SCHEME
1180 //e.g. Move highest priority to end of thread list
1181 list<unsigned>::iterator list_begin = activeThreads.begin();
1182 list<unsigned>::iterator list_end = activeThreads.end();
1183
1184 unsigned high_thread = *list_begin;
1185
1186 activeThreads.erase(list_begin);
1187
1188 activeThreads.push_back(high_thread);
1189 }
1190}
1191
567// Forward declaration of FullO3CPU.
568template class FullO3CPU<AlphaSimpleImpl>;
1192// Forward declaration of FullO3CPU.
1193template class FullO3CPU<AlphaSimpleImpl>;