2 * Copyright (c) 2004-2005 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.
29 #include "config/full_system.hh"
32 #include "sim/system.hh"
34 #include "sim/process.hh"
36 #include "sim/root.hh"
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"
45 BaseFullCPU::BaseFullCPU(Params
¶ms
)
46 : BaseCPU(¶ms
), cpu_id(0)
51 FullO3CPU
<Impl
>::TickEvent::TickEvent(FullO3CPU
<Impl
> *c
)
52 : Event(&mainEventQueue
, CPU_Tick_Pri
), cpu(c
)
58 FullO3CPU
<Impl
>::TickEvent::process()
65 FullO3CPU
<Impl
>::TickEvent::description()
67 return "FullO3CPU tick event";
70 //Call constructor to all the pipeline stages here
72 FullO3CPU
<Impl
>::FullO3CPU(Params
¶ms
)
74 : BaseFullCPU(params
),
76 : BaseFullCPU(params
),
85 regFile(params
.numPhysIntRegs
, params
.numPhysFloatRegs
),
87 freeList(TheISA::NumIntRegs
, params
.numPhysIntRegs
,
88 TheISA::NumFloatRegs
, params
.numPhysFloatRegs
),
90 renameMap(TheISA::NumIntRegs
, params
.numPhysIntRegs
,
91 TheISA::NumFloatRegs
, params
.numPhysFloatRegs
,
94 TheISA::ZeroReg
+ TheISA::NumIntRegs
),
96 rob(params
.numROBEntries
, params
.squashWidth
),
98 // What to pass to these time buffers?
99 // For now just have these time buffers be pretty big.
111 system(params
.system
),
112 memCtrl(system
->memctrl
),
113 physmem(system
->physmem
),
118 // Hardcoded for a single thread!!
119 mem(params
.workload
[0]->getMemory()),
120 #endif // FULL_SYSTEM
122 icacheInterface(params
.icacheInterface
),
123 dcacheInterface(params
.dcacheInterface
),
124 deferRegistration(params
.defReg
),
131 thread
.resize(this->number_of_threads
);
134 for (int i
= 0; i
< this->number_of_threads
; ++i
) {
137 system
->execContexts
[i
] =
138 new ExecContext(this, i
, system
, itb
, dtb
, mem
);
140 execContexts
.push_back(system
->execContexts
[i
]);
142 if (i
< params
.workload
.size()) {
143 DPRINTF(FullCPU
, "FullCPU: Workload[%i]'s starting PC is %#x, "
145 i
, params
.workload
[i
]->prog_entry
, thread
[i
]);
146 thread
[i
] = new ExecContext(this, i
, params
.workload
[i
], i
);
148 assert(params
.workload
[i
]->getMemory() != NULL
);
150 execContexts
.push_back(thread
[i
]);
151 #endif // !FULL_SYSTEM
154 // Note that this is a hack so that my code which still uses xc-> will
155 // still work. I should remove this eventually
157 xc
= system
->execContexts
[0];
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.
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
);
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
);
184 // Setup the rename map for whichever stages need it.
185 rename
.setRenameMap(&renameMap
);
186 iew
.setRenameMap(&renameMap
);
188 // Setup the free list for whichever stages need it.
189 rename
.setFreeList(&freeList
);
190 renameMap
.setFreeList(&freeList
);
192 // Setup the ROB for whichever stages need it.
196 template <class Impl
>
197 FullO3CPU
<Impl
>::~FullO3CPU()
201 template <class Impl
>
203 FullO3CPU
<Impl
>::fullCPURegStats()
205 // Register any of the FullCPU's stats here.
208 template <class Impl
>
210 FullO3CPU
<Impl
>::tick()
212 DPRINTF(FullCPU
, "\n\nFullCPU: Ticking main, FullO3CPU.\n");
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.
227 // Now advance the time buffers, unless the stage is stalled.
228 timeBuffer
.advance();
230 fetchQueue
.advance();
231 decodeQueue
.advance();
232 renameQueue
.advance();
235 if (_status
== Running
&& !tickEvent
.scheduled())
236 tickEvent
.schedule(curTick
+ 1);
239 template <class Impl
>
241 FullO3CPU
<Impl
>::init()
243 if(!deferRegistration
)
245 this->registerExecContexts();
247 // Need to do a copy of the xc->regs into the CPU's regfile so
248 // that it can start properly.
250 ExecContext
*src_xc
= system
->execContexts
[0];
251 TheISA::initCPU(&src_xc
->regs
, src_xc
->cpu_id
);
253 ExecContext
*src_xc
= thread
[0];
255 // First loop through the integer registers.
256 for (int i
= 0; i
< TheISA::NumIntRegs
; ++i
)
258 regFile
.intRegFile
[i
] = src_xc
->regs
.intRegFile
[i
];
261 // Then loop through the floating point registers.
262 for (int i
= 0; i
< TheISA::NumFloatRegs
; ++i
)
264 regFile
.floatRegFile
[i
].d
= src_xc
->regs
.floatRegFile
.d
[i
];
265 regFile
.floatRegFile
[i
].q
= src_xc
->regs
.floatRegFile
.q
[i
];
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;
274 // Then finally set the PC and the next PC.
275 regFile
.pc
= src_xc
->regs
.pc
;
276 regFile
.npc
= src_xc
->regs
.npc
;
280 template <class Impl
>
282 FullO3CPU
<Impl
>::activateContext(int thread_num
, int delay
)
284 // Needs to set each stage to running as well.
286 scheduleTickEvent(delay
);
291 template <class Impl
>
293 FullO3CPU
<Impl
>::suspendContext(int thread_num
)
295 panic("suspendContext unimplemented!");
298 template <class Impl
>
300 FullO3CPU
<Impl
>::deallocateContext(int thread_num
)
302 panic("deallocateContext unimplemented!");
305 template <class Impl
>
307 FullO3CPU
<Impl
>::haltContext(int thread_num
)
309 panic("haltContext unimplemented!");
312 template <class Impl
>
314 FullO3CPU
<Impl
>::switchOut()
316 panic("FullO3CPU does not have a switch out function.\n");
319 template <class Impl
>
321 FullO3CPU
<Impl
>::takeOverFrom(BaseCPU
*oldCPU
)
323 BaseCPU::takeOverFrom(oldCPU
);
325 assert(!tickEvent
.scheduled());
327 // Set all status's to active, schedule the
329 for (int i
= 0; i
< execContexts
.size(); ++i
) {
330 ExecContext
*xc
= execContexts
[i
];
331 if (xc
->status() == ExecContext::Active
&& _status
!= Running
) {
333 tickEvent
.schedule(curTick
);
338 template <class Impl
>
340 FullO3CPU
<Impl
>::getAndIncrementInstSeq()
342 // Hopefully this works right.
343 return globalSeqNum
++;
346 template <class Impl
>
348 FullO3CPU
<Impl
>::readIntReg(int reg_idx
)
350 return regFile
.readIntReg(reg_idx
);
353 template <class Impl
>
355 FullO3CPU
<Impl
>::readFloatRegSingle(int reg_idx
)
357 return regFile
.readFloatRegSingle(reg_idx
);
360 template <class Impl
>
362 FullO3CPU
<Impl
>::readFloatRegDouble(int reg_idx
)
364 return regFile
.readFloatRegDouble(reg_idx
);
367 template <class Impl
>
369 FullO3CPU
<Impl
>::readFloatRegInt(int reg_idx
)
371 return regFile
.readFloatRegInt(reg_idx
);
374 template <class Impl
>
376 FullO3CPU
<Impl
>::setIntReg(int reg_idx
, uint64_t val
)
378 regFile
.setIntReg(reg_idx
, val
);
381 template <class Impl
>
383 FullO3CPU
<Impl
>::setFloatRegSingle(int reg_idx
, float val
)
385 regFile
.setFloatRegSingle(reg_idx
, val
);
388 template <class Impl
>
390 FullO3CPU
<Impl
>::setFloatRegDouble(int reg_idx
, double val
)
392 regFile
.setFloatRegDouble(reg_idx
, val
);
395 template <class Impl
>
397 FullO3CPU
<Impl
>::setFloatRegInt(int reg_idx
, uint64_t val
)
399 regFile
.setFloatRegInt(reg_idx
, val
);
402 template <class Impl
>
404 FullO3CPU
<Impl
>::readPC()
406 return regFile
.readPC();
409 template <class Impl
>
411 FullO3CPU
<Impl
>::setNextPC(uint64_t val
)
413 regFile
.setNextPC(val
);
416 template <class Impl
>
418 FullO3CPU
<Impl
>::setPC(Addr new_PC
)
420 regFile
.setPC(new_PC
);
423 template <class Impl
>
425 FullO3CPU
<Impl
>::addInst(DynInstPtr
&inst
)
427 instList
.push_back(inst
);
430 template <class Impl
>
432 FullO3CPU
<Impl
>::instDone()
434 // Keep an instruction count.
437 // Check for instruction-count-based events.
438 comInstEventQueue
[0]->serviceEvents(numInsts
);
441 template <class Impl
>
443 FullO3CPU
<Impl
>::removeBackInst(DynInstPtr
&inst
)
445 DynInstPtr inst_to_delete
;
447 // Walk through the instruction list, removing any instructions
448 // that were inserted after the given instruction, inst.
449 while (instList
.back() != inst
)
451 assert(!instList
.empty());
453 // Obtain the pointer to the instruction.
454 inst_to_delete
= instList
.back();
456 DPRINTF(FullCPU
, "FullCPU: Removing instruction %i, PC %#x\n",
457 inst_to_delete
->seqNum
, inst_to_delete
->readPC());
459 // Remove the instruction from the list.
462 // Mark it as squashed.
463 inst_to_delete
->setSquashed();
467 template <class Impl
>
469 FullO3CPU
<Impl
>::removeFrontInst(DynInstPtr
&inst
)
471 DynInstPtr inst_to_remove
;
473 // The front instruction should be the same one being asked to be removed.
474 assert(instList
.front() == inst
);
476 // Remove the front instruction.
477 inst_to_remove
= inst
;
478 instList
.pop_front();
480 DPRINTF(FullCPU
, "FullCPU: Removing committed instruction %#x, PC %#x\n",
481 inst_to_remove
, inst_to_remove
->readPC());
484 template <class Impl
>
486 FullO3CPU
<Impl
>::removeInstsNotInROB()
488 DPRINTF(FullCPU
, "FullCPU: Deleting instructions from instruction "
491 DynInstPtr rob_tail
= rob
.readTailInst();
493 removeBackInst(rob_tail
);
496 template <class Impl
>
498 FullO3CPU
<Impl
>::removeInstsUntil(const InstSeqNum
&seq_num
)
500 DPRINTF(FullCPU
, "FullCPU: Deleting instructions from instruction "
503 DynInstPtr inst_to_delete
;
505 while (instList
.back()->seqNum
> seq_num
) {
506 assert(!instList
.empty());
508 // Obtain the pointer to the instruction.
509 inst_to_delete
= instList
.back();
511 DPRINTF(FullCPU
, "FullCPU: Removing instruction %i, PC %#x\n",
512 inst_to_delete
->seqNum
, inst_to_delete
->readPC());
514 // Remove the instruction from the list.
515 instList
.back() = NULL
;
518 // Mark it as squashed.
519 inst_to_delete
->setSquashed();
524 template <class Impl
>
526 FullO3CPU
<Impl
>::removeAllInsts()
531 template <class Impl
>
533 FullO3CPU
<Impl
>::dumpInsts()
536 typename list
<DynInstPtr
>::iterator inst_list_it
= instList
.begin();
538 while (inst_list_it
!= instList
.end())
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());
548 template <class Impl
>
550 FullO3CPU
<Impl
>::wakeDependents(DynInstPtr
&inst
)
552 iew
.wakeDependents(inst
);
555 // Forward declaration of FullO3CPU.
556 template class FullO3CPU
<AlphaSimpleImpl
>;