Updated Authors from bk prs info
[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 * 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
38 #include "sim/root.hh"
39
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
46 using namespace std;
47
48 BaseFullCPU::BaseFullCPU(Params &params)
49 : BaseCPU(&params), cpu_id(0)
50 {
51 }
52
53 template <class Impl>
54 FullO3CPU<Impl>::TickEvent::TickEvent(FullO3CPU<Impl> *c)
55 : Event(&mainEventQueue, CPU_Tick_Pri), cpu(c)
56 {
57 }
58
59 template <class Impl>
60 void
61 FullO3CPU<Impl>::TickEvent::process()
62 {
63 cpu->tick();
64 }
65
66 template <class Impl>
67 const char *
68 FullO3CPU<Impl>::TickEvent::description()
69 {
70 return "FullO3CPU tick event";
71 }
72
73 //Call constructor to all the pipeline stages here
74 template <class Impl>
75 FullO3CPU<Impl>::FullO3CPU(Params &params)
76 #if FULL_SYSTEM
77 : BaseFullCPU(params),
78 #else
79 : BaseFullCPU(params),
80 #endif // FULL_SYSTEM
81 tickEvent(this),
82 fetch(params),
83 decode(params),
84 rename(params),
85 iew(params),
86 commit(params),
87
88 regFile(params.numPhysIntRegs, params.numPhysFloatRegs),
89
90 freeList(TheISA::NumIntRegs, params.numPhysIntRegs,
91 TheISA::NumFloatRegs, params.numPhysFloatRegs),
92
93 renameMap(TheISA::NumIntRegs, params.numPhysIntRegs,
94 TheISA::NumFloatRegs, params.numPhysFloatRegs,
95 TheISA::NumMiscRegs,
96 TheISA::ZeroReg,
97 TheISA::ZeroReg + TheISA::NumIntRegs),
98
99 rob(params.numROBEntries, params.squashWidth),
100
101 // What to pass to these time buffers?
102 // For now just have these time buffers be pretty big.
103 timeBuffer(5, 5),
104 fetchQueue(5, 5),
105 decodeQueue(5, 5),
106 renameQueue(5, 5),
107 iewQueue(5, 5),
108
109 cpuXC(NULL),
110
111 globalSeqNum(1),
112
113 #if FULL_SYSTEM
114 system(params.system),
115 memCtrl(system->memctrl),
116 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
124
125 icacheInterface(params.icacheInterface),
126 dcacheInterface(params.dcacheInterface),
127 deferRegistration(params.defReg),
128 numInsts(0),
129 funcExeInst(0)
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) {
138 #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
155 }
156
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];
160
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.
164
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);
175 decode.setDecodeQueue(&decodeQueue);
176 rename.setDecodeQueue(&decodeQueue);
177 rename.setRenameQueue(&renameQueue);
178 iew.setRenameQueue(&renameQueue);
179 iew.setIEWQueue(&iewQueue);
180 commit.setIEWQueue(&iewQueue);
181 commit.setRenameQueue(&renameQueue);
182
183 // Setup the rename map for whichever stages need it.
184 rename.setRenameMap(&renameMap);
185 iew.setRenameMap(&renameMap);
186
187 // Setup the free list for whichever stages need it.
188 rename.setFreeList(&freeList);
189 renameMap.setFreeList(&freeList);
190
191 // Setup the ROB for whichever stages need it.
192 commit.setROB(&rob);
193 }
194
195 template <class Impl>
196 FullO3CPU<Impl>::~FullO3CPU()
197 {
198 }
199
200 template <class Impl>
201 void
202 FullO3CPU<Impl>::fullCPURegStats()
203 {
204 // Register any of the FullCPU's stats here.
205 }
206
207 template <class Impl>
208 void
209 FullO3CPU<Impl>::tick()
210 {
211 DPRINTF(FullCPU, "\n\nFullCPU: Ticking main, FullO3CPU.\n");
212
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.
216 fetch.tick();
217
218 decode.tick();
219
220 rename.tick();
221
222 iew.tick();
223
224 commit.tick();
225
226 // Now advance the time buffers, unless the stage is stalled.
227 timeBuffer.advance();
228
229 fetchQueue.advance();
230 decodeQueue.advance();
231 renameQueue.advance();
232 iewQueue.advance();
233
234 if (_status == Running && !tickEvent.scheduled())
235 tickEvent.schedule(curTick + 1);
236 }
237
238 template <class Impl>
239 void
240 FullO3CPU<Impl>::init()
241 {
242 if(!deferRegistration)
243 {
244 this->registerExecContexts();
245
246 // Need to do a copy of the xc->regs into the CPU's regfile so
247 // that it can start properly.
248 #if FULL_SYSTEM
249 ExecContext *src_xc = system->execContexts[0];
250 TheISA::initCPU(src_xc, src_xc->readCpuId());
251 #else
252 ExecContext *src_xc = thread[0]->getProxy();
253 #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);
258 }
259
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();
275 }
276 }
277
278 template <class Impl>
279 void
280 FullO3CPU<Impl>::activateContext(int thread_num, int delay)
281 {
282 // Needs to set each stage to running as well.
283
284 scheduleTickEvent(delay);
285
286 _status = Running;
287 }
288
289 template <class Impl>
290 void
291 FullO3CPU<Impl>::suspendContext(int thread_num)
292 {
293 panic("suspendContext unimplemented!");
294 }
295
296 template <class Impl>
297 void
298 FullO3CPU<Impl>::deallocateContext(int thread_num)
299 {
300 panic("deallocateContext unimplemented!");
301 }
302
303 template <class Impl>
304 void
305 FullO3CPU<Impl>::haltContext(int thread_num)
306 {
307 panic("haltContext unimplemented!");
308 }
309
310 template <class Impl>
311 void
312 FullO3CPU<Impl>::switchOut()
313 {
314 panic("FullO3CPU does not have a switch out function.\n");
315 }
316
317 template <class Impl>
318 void
319 FullO3CPU<Impl>::takeOverFrom(BaseCPU *oldCPU)
320 {
321 BaseCPU::takeOverFrom(oldCPU);
322
323 assert(!tickEvent.scheduled());
324
325 // Set all status's to active, schedule the
326 // CPU's tick event.
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 }
334 }
335
336 template <class Impl>
337 InstSeqNum
338 FullO3CPU<Impl>::getAndIncrementInstSeq()
339 {
340 // Hopefully this works right.
341 return globalSeqNum++;
342 }
343
344 template <class Impl>
345 uint64_t
346 FullO3CPU<Impl>::readIntReg(int reg_idx)
347 {
348 return regFile.readIntReg(reg_idx);
349 }
350
351 template <class Impl>
352 FloatReg
353 FullO3CPU<Impl>::readFloatReg(int reg_idx, int width)
354 {
355 return regFile.readFloatReg(reg_idx, width);
356 }
357
358 template <class Impl>
359 FloatReg
360 FullO3CPU<Impl>::readFloatReg(int reg_idx)
361 {
362 return regFile.readFloatReg(reg_idx);
363 }
364
365 template <class Impl>
366 FloatRegBits
367 FullO3CPU<Impl>::readFloatRegBits(int reg_idx, int width)
368 {
369 return regFile.readFloatRegBits(reg_idx, width);
370 }
371
372 template <class Impl>
373 FloatRegBits
374 FullO3CPU<Impl>::readFloatRegBits(int reg_idx)
375 {
376 return regFile.readFloatRegBits(reg_idx);
377 }
378
379 template <class Impl>
380 void
381 FullO3CPU<Impl>::setIntReg(int reg_idx, uint64_t val)
382 {
383 regFile.setIntReg(reg_idx, val);
384 }
385
386 template <class Impl>
387 void
388 FullO3CPU<Impl>::setFloatReg(int reg_idx, FloatReg val, int width)
389 {
390 regFile.setFloatReg(reg_idx, val, width);
391 }
392
393 template <class Impl>
394 void
395 FullO3CPU<Impl>::setFloatReg(int reg_idx, FloatReg val)
396 {
397 regFile.setFloatReg(reg_idx, val);
398 }
399
400 template <class Impl>
401 void
402 FullO3CPU<Impl>::setFloatRegBits(int reg_idx, FloatRegBits val, int width)
403 {
404 regFile.setFloatRegBits(reg_idx, val, width);
405 }
406
407 template <class Impl>
408 void
409 FullO3CPU<Impl>::setFloatRegBits(int reg_idx, FloatRegBits val)
410 {
411 regFile.setFloatRegBits(reg_idx, val);
412 }
413
414 template <class Impl>
415 uint64_t
416 FullO3CPU<Impl>::readPC()
417 {
418 return regFile.readPC();
419 }
420
421 template <class Impl>
422 void
423 FullO3CPU<Impl>::setNextPC(uint64_t val)
424 {
425 regFile.setNextPC(val);
426 }
427
428 template <class Impl>
429 void
430 FullO3CPU<Impl>::setPC(Addr new_PC)
431 {
432 regFile.setPC(new_PC);
433 }
434
435 template <class Impl>
436 void
437 FullO3CPU<Impl>::addInst(DynInstPtr &inst)
438 {
439 instList.push_back(inst);
440 }
441
442 template <class Impl>
443 void
444 FullO3CPU<Impl>::instDone()
445 {
446 // Keep an instruction count.
447 numInsts++;
448
449 // Check for instruction-count-based events.
450 comInstEventQueue[0]->serviceEvents(numInsts);
451 }
452
453 template <class Impl>
454 void
455 FullO3CPU<Impl>::removeBackInst(DynInstPtr &inst)
456 {
457 DynInstPtr inst_to_delete;
458
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());
464
465 // Obtain the pointer to the instruction.
466 inst_to_delete = instList.back();
467
468 DPRINTF(FullCPU, "FullCPU: Removing instruction %i, PC %#x\n",
469 inst_to_delete->seqNum, inst_to_delete->readPC());
470
471 // Remove the instruction from the list.
472 instList.pop_back();
473
474 // Mark it as squashed.
475 inst_to_delete->setSquashed();
476 }
477 }
478
479 template <class Impl>
480 void
481 FullO3CPU<Impl>::removeFrontInst(DynInstPtr &inst)
482 {
483 DynInstPtr inst_to_remove;
484
485 // The front instruction should be the same one being asked to be removed.
486 assert(instList.front() == inst);
487
488 // 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());
494 }
495
496 template <class Impl>
497 void
498 FullO3CPU<Impl>::removeInstsNotInROB()
499 {
500 DPRINTF(FullCPU, "FullCPU: Deleting instructions from instruction "
501 "list.\n");
502
503 DynInstPtr rob_tail = rob.readTailInst();
504
505 removeBackInst(rob_tail);
506 }
507
508 template <class Impl>
509 void
510 FullO3CPU<Impl>::removeInstsUntil(const InstSeqNum &seq_num)
511 {
512 DPRINTF(FullCPU, "FullCPU: Deleting instructions from instruction "
513 "list.\n");
514
515 DynInstPtr inst_to_delete;
516
517 while (instList.back()->seqNum > seq_num) {
518 assert(!instList.empty());
519
520 // Obtain the pointer to the instruction.
521 inst_to_delete = instList.back();
522
523 DPRINTF(FullCPU, "FullCPU: Removing instruction %i, PC %#x\n",
524 inst_to_delete->seqNum, inst_to_delete->readPC());
525
526 // Remove the instruction from the list.
527 instList.back() = NULL;
528 instList.pop_back();
529
530 // Mark it as squashed.
531 inst_to_delete->setSquashed();
532 }
533
534 }
535
536 template <class Impl>
537 void
538 FullO3CPU<Impl>::removeAllInsts()
539 {
540 instList.clear();
541 }
542
543 template <class Impl>
544 void
545 FullO3CPU<Impl>::dumpInsts()
546 {
547 int num = 0;
548 typename list<DynInstPtr>::iterator inst_list_it = instList.begin();
549
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());
555 inst_list_it++;
556 ++num;
557 }
558 }
559
560 template <class Impl>
561 void
562 FullO3CPU<Impl>::wakeDependents(DynInstPtr &inst)
563 {
564 iew.wakeDependents(inst);
565 }
566
567 // Forward declaration of FullO3CPU.
568 template class FullO3CPU<AlphaSimpleImpl>;