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