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/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"
46 BaseFullCPU::BaseFullCPU(Params
¶ms
)
47 : BaseCPU(¶ms
), cpu_id(0)
52 FullO3CPU
<Impl
>::TickEvent::TickEvent(FullO3CPU
<Impl
> *c
)
53 : Event(&mainEventQueue
, CPU_Tick_Pri
), cpu(c
)
59 FullO3CPU
<Impl
>::TickEvent::process()
66 FullO3CPU
<Impl
>::TickEvent::description()
68 return "FullO3CPU tick event";
71 //Call constructor to all the pipeline stages here
73 FullO3CPU
<Impl
>::FullO3CPU(Params
¶ms
)
75 : BaseFullCPU(params
),
77 : BaseFullCPU(params
),
86 regFile(params
.numPhysIntRegs
, params
.numPhysFloatRegs
),
88 freeList(TheISA::NumIntRegs
, params
.numPhysIntRegs
,
89 TheISA::NumFloatRegs
, params
.numPhysFloatRegs
),
91 renameMap(TheISA::NumIntRegs
, params
.numPhysIntRegs
,
92 TheISA::NumFloatRegs
, params
.numPhysFloatRegs
,
95 TheISA::ZeroReg
+ TheISA::NumIntRegs
),
97 rob(params
.numROBEntries
, params
.squashWidth
),
99 // What to pass to these time buffers?
100 // For now just have these time buffers be pretty big.
112 system(params
.system
),
113 memCtrl(system
->memctrl
),
114 physmem(system
->physmem
),
119 // Hardcoded for a single thread!!
120 mem(params
.workload
[0]->getMemory()),
121 #endif // FULL_SYSTEM
123 icacheInterface(params
.icacheInterface
),
124 dcacheInterface(params
.dcacheInterface
),
125 deferRegistration(params
.defReg
),
132 thread
.resize(this->number_of_threads
);
135 for (int i
= 0; i
< this->number_of_threads
; ++i
) {
138 thread
[i
] = new CPUExecContext(this, 0, system
, itb
, dtb
, mem
);
139 system
->execContexts
[i
] = thread
[i
]->getProxy();
141 execContexts
.push_back(system
->execContexts
[i
]);
143 if (i
< params
.workload
.size()) {
144 DPRINTF(FullCPU
, "FullCPU: Workload[%i]'s starting PC is %#x, "
146 i
, params
.workload
[i
]->prog_entry
, thread
[i
]);
147 thread
[i
] = new CPUExecContext(this, i
, params
.workload
[i
], i
);
149 assert(params
.workload
[i
]->getMemory() != NULL
);
151 execContexts
.push_back(thread
[i
]->getProxy());
152 #endif // !FULL_SYSTEM
155 // Note that this is a hack so that my code which still uses xc-> will
156 // still work. I should remove this eventually
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.
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
);
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
);
181 // Setup the rename map for whichever stages need it.
182 rename
.setRenameMap(&renameMap
);
183 iew
.setRenameMap(&renameMap
);
185 // Setup the free list for whichever stages need it.
186 rename
.setFreeList(&freeList
);
187 renameMap
.setFreeList(&freeList
);
189 // Setup the ROB for whichever stages need it.
193 template <class Impl
>
194 FullO3CPU
<Impl
>::~FullO3CPU()
198 template <class Impl
>
200 FullO3CPU
<Impl
>::fullCPURegStats()
202 // Register any of the FullCPU's stats here.
205 template <class Impl
>
207 FullO3CPU
<Impl
>::tick()
209 DPRINTF(FullCPU
, "\n\nFullCPU: Ticking main, FullO3CPU.\n");
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.
224 // Now advance the time buffers, unless the stage is stalled.
225 timeBuffer
.advance();
227 fetchQueue
.advance();
228 decodeQueue
.advance();
229 renameQueue
.advance();
232 if (_status
== Running
&& !tickEvent
.scheduled())
233 tickEvent
.schedule(curTick
+ 1);
236 template <class Impl
>
238 FullO3CPU
<Impl
>::init()
240 if(!deferRegistration
)
242 this->registerExecContexts();
244 // Need to do a copy of the xc->regs into the CPU's regfile so
245 // that it can start properly.
247 ExecContext
*src_xc
= system
->execContexts
[0];
248 TheISA::initCPU(src_xc
, src_xc
->readCpuId());
250 ExecContext
*src_xc
= thread
[0]->getProxy();
252 // First loop through the integer registers.
253 for (int i
= 0; i
< TheISA::NumIntRegs
; ++i
)
255 regFile
.intRegFile
[i
] = src_xc
->readIntReg(i
);
258 // Then loop through the floating point registers.
259 for (int i
= 0; i
< TheISA::NumFloatRegs
; ++i
)
261 regFile
.floatRegFile
.setRegBits(i
, src_xc
->readRegBits(i
))
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;
270 // Then finally set the PC and the next PC.
271 regFile
.pc
= src_xc
->readPC();
272 regFile
.npc
= src_xc
->readNextPC();
276 template <class Impl
>
278 FullO3CPU
<Impl
>::activateContext(int thread_num
, int delay
)
280 // Needs to set each stage to running as well.
282 scheduleTickEvent(delay
);
287 template <class Impl
>
289 FullO3CPU
<Impl
>::suspendContext(int thread_num
)
291 panic("suspendContext unimplemented!");
294 template <class Impl
>
296 FullO3CPU
<Impl
>::deallocateContext(int thread_num
)
298 panic("deallocateContext unimplemented!");
301 template <class Impl
>
303 FullO3CPU
<Impl
>::haltContext(int thread_num
)
305 panic("haltContext unimplemented!");
308 template <class Impl
>
310 FullO3CPU
<Impl
>::switchOut()
312 panic("FullO3CPU does not have a switch out function.\n");
315 template <class Impl
>
317 FullO3CPU
<Impl
>::takeOverFrom(BaseCPU
*oldCPU
)
319 BaseCPU::takeOverFrom(oldCPU
);
321 assert(!tickEvent
.scheduled());
323 // Set all status's to active, schedule the
325 for (int i
= 0; i
< execContexts
.size(); ++i
) {
326 ExecContext
*xc
= execContexts
[i
];
327 if (xc
->status() == ExecContext::Active
&& _status
!= Running
) {
329 tickEvent
.schedule(curTick
);
334 template <class Impl
>
336 FullO3CPU
<Impl
>::getAndIncrementInstSeq()
338 // Hopefully this works right.
339 return globalSeqNum
++;
342 template <class Impl
>
344 FullO3CPU
<Impl
>::readIntReg(int reg_idx
)
346 return regFile
.readIntReg(reg_idx
);
349 template <class Impl
>
351 FullO3CPU
<Impl
>::readFloatReg(int reg_idx
, int width
)
353 return regFile
.readFloatReg(reg_idx
, width
);
356 template <class Impl
>
358 FullO3CPU
<Impl
>::readFloatReg(int reg_idx
)
360 return regFile
.readFloatReg(reg_idx
);
363 template <class Impl
>
365 FullO3CPU
<Impl
>::readFloatRegBits(int reg_idx
, int width
)
367 return regFile
.readFloatRegBits(reg_idx
, width
);
370 template <class Impl
>
372 FullO3CPU
<Impl
>::readFloatRegBits(int reg_idx
)
374 return regFile
.readFloatRegBits(reg_idx
);
377 template <class Impl
>
379 FullO3CPU
<Impl
>::setIntReg(int reg_idx
, uint64_t val
)
381 regFile
.setIntReg(reg_idx
, val
);
384 template <class Impl
>
386 FullO3CPU
<Impl
>::setFloatReg(int reg_idx
, FloatReg val
, int width
)
388 regFile
.setFloatReg(reg_idx
, val
, width
);
391 template <class Impl
>
393 FullO3CPU
<Impl
>::setFloatReg(int reg_idx
, FloatReg val
)
395 regFile
.setFloatReg(reg_idx
, val
);
398 template <class Impl
>
400 FullO3CPU
<Impl
>::setFloatRegBits(int reg_idx
, FloatRegBits val
, int width
)
402 regFile
.setFloatRegBits(reg_idx
, val
, width
);
405 template <class Impl
>
407 FullO3CPU
<Impl
>::setFloatRegBits(int reg_idx
, FloatRegBits val
)
409 regFile
.setFloatRegBits(reg_idx
, val
);
412 template <class Impl
>
414 FullO3CPU
<Impl
>::readPC()
416 return regFile
.readPC();
419 template <class Impl
>
421 FullO3CPU
<Impl
>::setNextPC(uint64_t val
)
423 regFile
.setNextPC(val
);
426 template <class Impl
>
428 FullO3CPU
<Impl
>::setPC(Addr new_PC
)
430 regFile
.setPC(new_PC
);
433 template <class Impl
>
435 FullO3CPU
<Impl
>::addInst(DynInstPtr
&inst
)
437 instList
.push_back(inst
);
440 template <class Impl
>
442 FullO3CPU
<Impl
>::instDone()
444 // Keep an instruction count.
447 // Check for instruction-count-based events.
448 comInstEventQueue
[0]->serviceEvents(numInsts
);
451 template <class Impl
>
453 FullO3CPU
<Impl
>::removeBackInst(DynInstPtr
&inst
)
455 DynInstPtr inst_to_delete
;
457 // Walk through the instruction list, removing any instructions
458 // that were inserted after the given instruction, inst.
459 while (instList
.back() != inst
)
461 assert(!instList
.empty());
463 // Obtain the pointer to the instruction.
464 inst_to_delete
= instList
.back();
466 DPRINTF(FullCPU
, "FullCPU: Removing instruction %i, PC %#x\n",
467 inst_to_delete
->seqNum
, inst_to_delete
->readPC());
469 // Remove the instruction from the list.
472 // Mark it as squashed.
473 inst_to_delete
->setSquashed();
477 template <class Impl
>
479 FullO3CPU
<Impl
>::removeFrontInst(DynInstPtr
&inst
)
481 DynInstPtr inst_to_remove
;
483 // The front instruction should be the same one being asked to be removed.
484 assert(instList
.front() == inst
);
486 // Remove the front instruction.
487 inst_to_remove
= inst
;
488 instList
.pop_front();
490 DPRINTF(FullCPU
, "FullCPU: Removing committed instruction %#x, PC %#x\n",
491 inst_to_remove
, inst_to_remove
->readPC());
494 template <class Impl
>
496 FullO3CPU
<Impl
>::removeInstsNotInROB()
498 DPRINTF(FullCPU
, "FullCPU: Deleting instructions from instruction "
501 DynInstPtr rob_tail
= rob
.readTailInst();
503 removeBackInst(rob_tail
);
506 template <class Impl
>
508 FullO3CPU
<Impl
>::removeInstsUntil(const InstSeqNum
&seq_num
)
510 DPRINTF(FullCPU
, "FullCPU: Deleting instructions from instruction "
513 DynInstPtr inst_to_delete
;
515 while (instList
.back()->seqNum
> seq_num
) {
516 assert(!instList
.empty());
518 // Obtain the pointer to the instruction.
519 inst_to_delete
= instList
.back();
521 DPRINTF(FullCPU
, "FullCPU: Removing instruction %i, PC %#x\n",
522 inst_to_delete
->seqNum
, inst_to_delete
->readPC());
524 // Remove the instruction from the list.
525 instList
.back() = NULL
;
528 // Mark it as squashed.
529 inst_to_delete
->setSquashed();
534 template <class Impl
>
536 FullO3CPU
<Impl
>::removeAllInsts()
541 template <class Impl
>
543 FullO3CPU
<Impl
>::dumpInsts()
546 typename list
<DynInstPtr
>::iterator inst_list_it
= instList
.begin();
548 while (inst_list_it
!= instList
.end())
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());
558 template <class Impl
>
560 FullO3CPU
<Impl
>::wakeDependents(DynInstPtr
&inst
)
562 iew
.wakeDependents(inst
);
565 // Forward declaration of FullO3CPU.
566 template class FullO3CPU
<AlphaSimpleImpl
>;