Fix SCons version check.
[gem5.git] / src / cpu / o3 / cpu.cc
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 using namespace std;
45
46 BaseFullCPU::BaseFullCPU(Params &params)
47 : BaseCPU(&params), cpu_id(0)
48 {
49 }
50
51 template <class Impl>
52 FullO3CPU<Impl>::TickEvent::TickEvent(FullO3CPU<Impl> *c)
53 : Event(&mainEventQueue, CPU_Tick_Pri), cpu(c)
54 {
55 }
56
57 template <class Impl>
58 void
59 FullO3CPU<Impl>::TickEvent::process()
60 {
61 cpu->tick();
62 }
63
64 template <class Impl>
65 const char *
66 FullO3CPU<Impl>::TickEvent::description()
67 {
68 return "FullO3CPU tick event";
69 }
70
71 //Call constructor to all the pipeline stages here
72 template <class Impl>
73 FullO3CPU<Impl>::FullO3CPU(Params &params)
74 #if FULL_SYSTEM
75 : BaseFullCPU(params),
76 #else
77 : BaseFullCPU(params),
78 #endif // FULL_SYSTEM
79 tickEvent(this),
80 fetch(params),
81 decode(params),
82 rename(params),
83 iew(params),
84 commit(params),
85
86 regFile(params.numPhysIntRegs, params.numPhysFloatRegs),
87
88 freeList(TheISA::NumIntRegs, params.numPhysIntRegs,
89 TheISA::NumFloatRegs, params.numPhysFloatRegs),
90
91 renameMap(TheISA::NumIntRegs, params.numPhysIntRegs,
92 TheISA::NumFloatRegs, params.numPhysFloatRegs,
93 TheISA::NumMiscRegs,
94 TheISA::ZeroReg,
95 TheISA::ZeroReg + TheISA::NumIntRegs),
96
97 rob(params.numROBEntries, params.squashWidth),
98
99 // What to pass to these time buffers?
100 // For now just have these time buffers be pretty big.
101 timeBuffer(5, 5),
102 fetchQueue(5, 5),
103 decodeQueue(5, 5),
104 renameQueue(5, 5),
105 iewQueue(5, 5),
106
107 cpuXC(NULL),
108
109 globalSeqNum(1),
110
111 #if FULL_SYSTEM
112 system(params.system),
113 memCtrl(system->memctrl),
114 physmem(system->physmem),
115 itb(params.itb),
116 dtb(params.dtb),
117 mem(params.mem),
118 #else
119 // Hardcoded for a single thread!!
120 mem(params.workload[0]->getMemory()),
121 #endif // FULL_SYSTEM
122
123 icacheInterface(params.icacheInterface),
124 dcacheInterface(params.dcacheInterface),
125 deferRegistration(params.defReg),
126 numInsts(0),
127 funcExeInst(0)
128 {
129 _status = Idle;
130
131 #if !FULL_SYSTEM
132 thread.resize(this->number_of_threads);
133 #endif
134
135 for (int i = 0; i < this->number_of_threads; ++i) {
136 #if FULL_SYSTEM
137 assert(i == 0);
138 thread[i] = new CPUExecContext(this, 0, system, itb, dtb, mem);
139 system->execContexts[i] = thread[i]->getProxy();
140
141 execContexts.push_back(system->execContexts[i]);
142 #else
143 if (i < params.workload.size()) {
144 DPRINTF(FullCPU, "FullCPU: Workload[%i]'s starting PC is %#x, "
145 "process is %#x",
146 i, params.workload[i]->prog_entry, thread[i]);
147 thread[i] = new CPUExecContext(this, i, params.workload[i], i);
148 }
149 assert(params.workload[i]->getMemory() != NULL);
150 assert(mem != NULL);
151 execContexts.push_back(thread[i]->getProxy());
152 #endif // !FULL_SYSTEM
153 }
154
155 // Note that this is a hack so that my code which still uses xc-> will
156 // still work. I should remove this eventually
157 cpuXC = thread[0];
158
159 // The stages also need their CPU pointer setup. However this must be
160 // done at the upper level CPU because they have pointers to the upper
161 // level CPU, and not this FullO3CPU.
162
163 // Give each of the stages the time buffer they will use.
164 fetch.setTimeBuffer(&timeBuffer);
165 decode.setTimeBuffer(&timeBuffer);
166 rename.setTimeBuffer(&timeBuffer);
167 iew.setTimeBuffer(&timeBuffer);
168 commit.setTimeBuffer(&timeBuffer);
169
170 // Also setup each of the stages' queues.
171 fetch.setFetchQueue(&fetchQueue);
172 decode.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);
180
181 // Setup the rename map for whichever stages need it.
182 rename.setRenameMap(&renameMap);
183 iew.setRenameMap(&renameMap);
184
185 // Setup the free list for whichever stages need it.
186 rename.setFreeList(&freeList);
187 renameMap.setFreeList(&freeList);
188
189 // Setup the ROB for whichever stages need it.
190 commit.setROB(&rob);
191 }
192
193 template <class Impl>
194 FullO3CPU<Impl>::~FullO3CPU()
195 {
196 }
197
198 template <class Impl>
199 void
200 FullO3CPU<Impl>::fullCPURegStats()
201 {
202 // Register any of the FullCPU's stats here.
203 }
204
205 template <class Impl>
206 void
207 FullO3CPU<Impl>::tick()
208 {
209 DPRINTF(FullCPU, "\n\nFullCPU: Ticking main, FullO3CPU.\n");
210
211 //Tick each of the stages if they're actually running.
212 //Will want to figure out a way to unschedule itself if they're all
213 //going to be idle for a long time.
214 fetch.tick();
215
216 decode.tick();
217
218 rename.tick();
219
220 iew.tick();
221
222 commit.tick();
223
224 // Now advance the time buffers, unless the stage is stalled.
225 timeBuffer.advance();
226
227 fetchQueue.advance();
228 decodeQueue.advance();
229 renameQueue.advance();
230 iewQueue.advance();
231
232 if (_status == Running && !tickEvent.scheduled())
233 tickEvent.schedule(curTick + 1);
234 }
235
236 template <class Impl>
237 void
238 FullO3CPU<Impl>::init()
239 {
240 if(!deferRegistration)
241 {
242 this->registerExecContexts();
243
244 // Need to do a copy of the xc->regs into the CPU's regfile so
245 // that it can start properly.
246 #if FULL_SYSTEM
247 ExecContext *src_xc = system->execContexts[0];
248 TheISA::initCPU(src_xc, src_xc->readCpuId());
249 #else
250 ExecContext *src_xc = thread[0]->getProxy();
251 #endif
252 // First loop through the integer registers.
253 for (int i = 0; i < TheISA::NumIntRegs; ++i)
254 {
255 regFile.intRegFile[i] = src_xc->readIntReg(i);
256 }
257
258 // Then loop through the floating point registers.
259 for (int i = 0; i < TheISA::NumFloatRegs; ++i)
260 {
261 regFile.floatRegFile.setRegBits(i, src_xc->readRegBits(i))
262 }
263 /*
264 // Then loop through the misc registers.
265 regFile.miscRegs.fpcr = src_xc->regs.miscRegs.fpcr;
266 regFile.miscRegs.uniq = src_xc->regs.miscRegs.uniq;
267 regFile.miscRegs.lock_flag = src_xc->regs.miscRegs.lock_flag;
268 regFile.miscRegs.lock_addr = src_xc->regs.miscRegs.lock_addr;
269 */
270 // Then finally set the PC and the next PC.
271 regFile.pc = src_xc->readPC();
272 regFile.npc = src_xc->readNextPC();
273 }
274 }
275
276 template <class Impl>
277 void
278 FullO3CPU<Impl>::activateContext(int thread_num, int delay)
279 {
280 // Needs to set each stage to running as well.
281
282 scheduleTickEvent(delay);
283
284 _status = Running;
285 }
286
287 template <class Impl>
288 void
289 FullO3CPU<Impl>::suspendContext(int thread_num)
290 {
291 panic("suspendContext unimplemented!");
292 }
293
294 template <class Impl>
295 void
296 FullO3CPU<Impl>::deallocateContext(int thread_num)
297 {
298 panic("deallocateContext unimplemented!");
299 }
300
301 template <class Impl>
302 void
303 FullO3CPU<Impl>::haltContext(int thread_num)
304 {
305 panic("haltContext unimplemented!");
306 }
307
308 template <class Impl>
309 void
310 FullO3CPU<Impl>::switchOut()
311 {
312 panic("FullO3CPU does not have a switch out function.\n");
313 }
314
315 template <class Impl>
316 void
317 FullO3CPU<Impl>::takeOverFrom(BaseCPU *oldCPU)
318 {
319 BaseCPU::takeOverFrom(oldCPU);
320
321 assert(!tickEvent.scheduled());
322
323 // Set all status's to active, schedule the
324 // CPU's tick event.
325 for (int i = 0; i < execContexts.size(); ++i) {
326 ExecContext *xc = execContexts[i];
327 if (xc->status() == ExecContext::Active && _status != Running) {
328 _status = Running;
329 tickEvent.schedule(curTick);
330 }
331 }
332 }
333
334 template <class Impl>
335 InstSeqNum
336 FullO3CPU<Impl>::getAndIncrementInstSeq()
337 {
338 // Hopefully this works right.
339 return globalSeqNum++;
340 }
341
342 template <class Impl>
343 uint64_t
344 FullO3CPU<Impl>::readIntReg(int reg_idx)
345 {
346 return regFile.readIntReg(reg_idx);
347 }
348
349 template <class Impl>
350 FloatReg
351 FullO3CPU<Impl>::readFloatReg(int reg_idx, int width)
352 {
353 return regFile.readFloatReg(reg_idx, width);
354 }
355
356 template <class Impl>
357 FloatReg
358 FullO3CPU<Impl>::readFloatReg(int reg_idx)
359 {
360 return regFile.readFloatReg(reg_idx);
361 }
362
363 template <class Impl>
364 FloatRegBits
365 FullO3CPU<Impl>::readFloatRegBits(int reg_idx, int width)
366 {
367 return regFile.readFloatRegBits(reg_idx, width);
368 }
369
370 template <class Impl>
371 FloatRegBits
372 FullO3CPU<Impl>::readFloatRegBits(int reg_idx)
373 {
374 return regFile.readFloatRegBits(reg_idx);
375 }
376
377 template <class Impl>
378 void
379 FullO3CPU<Impl>::setIntReg(int reg_idx, uint64_t val)
380 {
381 regFile.setIntReg(reg_idx, val);
382 }
383
384 template <class Impl>
385 void
386 FullO3CPU<Impl>::setFloatReg(int reg_idx, FloatReg val, int width)
387 {
388 regFile.setFloatReg(reg_idx, val, width);
389 }
390
391 template <class Impl>
392 void
393 FullO3CPU<Impl>::setFloatReg(int reg_idx, FloatReg val)
394 {
395 regFile.setFloatReg(reg_idx, val);
396 }
397
398 template <class Impl>
399 void
400 FullO3CPU<Impl>::setFloatRegBits(int reg_idx, FloatRegBits val, int width)
401 {
402 regFile.setFloatRegBits(reg_idx, val, width);
403 }
404
405 template <class Impl>
406 void
407 FullO3CPU<Impl>::setFloatRegBits(int reg_idx, FloatRegBits val)
408 {
409 regFile.setFloatRegBits(reg_idx, val);
410 }
411
412 template <class Impl>
413 uint64_t
414 FullO3CPU<Impl>::readPC()
415 {
416 return regFile.readPC();
417 }
418
419 template <class Impl>
420 void
421 FullO3CPU<Impl>::setNextPC(uint64_t val)
422 {
423 regFile.setNextPC(val);
424 }
425
426 template <class Impl>
427 void
428 FullO3CPU<Impl>::setPC(Addr new_PC)
429 {
430 regFile.setPC(new_PC);
431 }
432
433 template <class Impl>
434 void
435 FullO3CPU<Impl>::addInst(DynInstPtr &inst)
436 {
437 instList.push_back(inst);
438 }
439
440 template <class Impl>
441 void
442 FullO3CPU<Impl>::instDone()
443 {
444 // Keep an instruction count.
445 numInsts++;
446
447 // Check for instruction-count-based events.
448 comInstEventQueue[0]->serviceEvents(numInsts);
449 }
450
451 template <class Impl>
452 void
453 FullO3CPU<Impl>::removeBackInst(DynInstPtr &inst)
454 {
455 DynInstPtr inst_to_delete;
456
457 // Walk through the instruction list, removing any instructions
458 // that were inserted after the given instruction, inst.
459 while (instList.back() != inst)
460 {
461 assert(!instList.empty());
462
463 // Obtain the pointer to the instruction.
464 inst_to_delete = instList.back();
465
466 DPRINTF(FullCPU, "FullCPU: Removing instruction %i, PC %#x\n",
467 inst_to_delete->seqNum, inst_to_delete->readPC());
468
469 // Remove the instruction from the list.
470 instList.pop_back();
471
472 // Mark it as squashed.
473 inst_to_delete->setSquashed();
474 }
475 }
476
477 template <class Impl>
478 void
479 FullO3CPU<Impl>::removeFrontInst(DynInstPtr &inst)
480 {
481 DynInstPtr inst_to_remove;
482
483 // The front instruction should be the same one being asked to be removed.
484 assert(instList.front() == inst);
485
486 // Remove the front instruction.
487 inst_to_remove = inst;
488 instList.pop_front();
489
490 DPRINTF(FullCPU, "FullCPU: Removing committed instruction %#x, PC %#x\n",
491 inst_to_remove, inst_to_remove->readPC());
492 }
493
494 template <class Impl>
495 void
496 FullO3CPU<Impl>::removeInstsNotInROB()
497 {
498 DPRINTF(FullCPU, "FullCPU: Deleting instructions from instruction "
499 "list.\n");
500
501 DynInstPtr rob_tail = rob.readTailInst();
502
503 removeBackInst(rob_tail);
504 }
505
506 template <class Impl>
507 void
508 FullO3CPU<Impl>::removeInstsUntil(const InstSeqNum &seq_num)
509 {
510 DPRINTF(FullCPU, "FullCPU: Deleting instructions from instruction "
511 "list.\n");
512
513 DynInstPtr inst_to_delete;
514
515 while (instList.back()->seqNum > seq_num) {
516 assert(!instList.empty());
517
518 // Obtain the pointer to the instruction.
519 inst_to_delete = instList.back();
520
521 DPRINTF(FullCPU, "FullCPU: Removing instruction %i, PC %#x\n",
522 inst_to_delete->seqNum, inst_to_delete->readPC());
523
524 // Remove the instruction from the list.
525 instList.back() = NULL;
526 instList.pop_back();
527
528 // Mark it as squashed.
529 inst_to_delete->setSquashed();
530 }
531
532 }
533
534 template <class Impl>
535 void
536 FullO3CPU<Impl>::removeAllInsts()
537 {
538 instList.clear();
539 }
540
541 template <class Impl>
542 void
543 FullO3CPU<Impl>::dumpInsts()
544 {
545 int num = 0;
546 typename list<DynInstPtr>::iterator inst_list_it = instList.begin();
547
548 while (inst_list_it != instList.end())
549 {
550 cprintf("Instruction:%i\nPC:%#x\nSN:%lli\nIssued:%i\nSquashed:%i\n\n",
551 num, (*inst_list_it)->readPC(), (*inst_list_it)->seqNum,
552 (*inst_list_it)->isIssued(), (*inst_list_it)->isSquashed());
553 inst_list_it++;
554 ++num;
555 }
556 }
557
558 template <class Impl>
559 void
560 FullO3CPU<Impl>::wakeDependents(DynInstPtr &inst)
561 {
562 iew.wakeDependents(inst);
563 }
564
565 // Forward declaration of FullO3CPU.
566 template class FullO3CPU<AlphaSimpleImpl>;