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.
31 #include "config/full_system.hh"
34 #include "sim/system.hh"
36 #include "sim/process.hh"
38 #include "sim/root.hh"
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"
48 BaseFullCPU::BaseFullCPU(Params
¶ms
)
49 : BaseCPU(¶ms
), cpu_id(0)
54 FullO3CPU
<Impl
>::TickEvent::TickEvent(FullO3CPU
<Impl
> *c
)
55 : Event(&mainEventQueue
, CPU_Tick_Pri
), cpu(c
)
61 FullO3CPU
<Impl
>::TickEvent::process()
68 FullO3CPU
<Impl
>::TickEvent::description()
70 return "FullO3CPU tick event";
73 //Call constructor to all the pipeline stages here
75 FullO3CPU
<Impl
>::FullO3CPU(Params
¶ms
)
77 : BaseFullCPU(params
),
79 : BaseFullCPU(params
),
88 regFile(params
.numPhysIntRegs
, params
.numPhysFloatRegs
),
90 freeList(TheISA::NumIntRegs
, params
.numPhysIntRegs
,
91 TheISA::NumFloatRegs
, params
.numPhysFloatRegs
),
93 renameMap(TheISA::NumIntRegs
, params
.numPhysIntRegs
,
94 TheISA::NumFloatRegs
, params
.numPhysFloatRegs
,
97 TheISA::ZeroReg
+ TheISA::NumIntRegs
),
99 rob(params
.numROBEntries
, params
.squashWidth
),
101 // What to pass to these time buffers?
102 // For now just have these time buffers be pretty big.
114 system(params
.system
),
115 memCtrl(system
->memctrl
),
116 physmem(system
->physmem
),
121 // Hardcoded for a single thread!!
122 mem(params
.workload
[0]->getMemory()),
123 #endif // FULL_SYSTEM
125 icacheInterface(params
.icacheInterface
),
126 dcacheInterface(params
.dcacheInterface
),
127 deferRegistration(params
.defReg
),
134 thread
.resize(this->number_of_threads
);
137 for (int i
= 0; i
< this->number_of_threads
; ++i
) {
140 thread
[i
] = new CPUExecContext(this, 0, system
, itb
, dtb
, mem
);
141 system
->execContexts
[i
] = thread
[i
]->getProxy();
143 execContexts
.push_back(system
->execContexts
[i
]);
145 if (i
< params
.workload
.size()) {
146 DPRINTF(FullCPU
, "FullCPU: Workload[%i]'s starting PC is %#x, "
148 i
, params
.workload
[i
]->prog_entry
, thread
[i
]);
149 thread
[i
] = new CPUExecContext(this, i
, params
.workload
[i
], i
);
151 assert(params
.workload
[i
]->getMemory() != NULL
);
153 execContexts
.push_back(thread
[i
]->getProxy());
154 #endif // !FULL_SYSTEM
157 // Note that this is a hack so that my code which still uses xc-> will
158 // still work. I should remove this eventually
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.
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
);
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
);
183 // Setup the rename map for whichever stages need it.
184 rename
.setRenameMap(&renameMap
);
185 iew
.setRenameMap(&renameMap
);
187 // Setup the free list for whichever stages need it.
188 rename
.setFreeList(&freeList
);
189 renameMap
.setFreeList(&freeList
);
191 // Setup the ROB for whichever stages need it.
195 template <class Impl
>
196 FullO3CPU
<Impl
>::~FullO3CPU()
200 template <class Impl
>
202 FullO3CPU
<Impl
>::fullCPURegStats()
204 // Register any of the FullCPU's stats here.
207 template <class Impl
>
209 FullO3CPU
<Impl
>::tick()
211 DPRINTF(FullCPU
, "\n\nFullCPU: Ticking main, FullO3CPU.\n");
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.
226 // Now advance the time buffers, unless the stage is stalled.
227 timeBuffer
.advance();
229 fetchQueue
.advance();
230 decodeQueue
.advance();
231 renameQueue
.advance();
234 if (_status
== Running
&& !tickEvent
.scheduled())
235 tickEvent
.schedule(curTick
+ 1);
238 template <class Impl
>
240 FullO3CPU
<Impl
>::init()
242 if(!deferRegistration
)
244 this->registerExecContexts();
246 // Need to do a copy of the xc->regs into the CPU's regfile so
247 // that it can start properly.
249 ExecContext
*src_xc
= system
->execContexts
[0];
250 TheISA::initCPU(src_xc
, src_xc
->readCpuId());
252 ExecContext
*src_xc
= thread
[0]->getProxy();
254 // First loop through the integer registers.
255 for (int i
= 0; i
< TheISA::NumIntRegs
; ++i
)
257 regFile
.intRegFile
[i
] = src_xc
->readIntReg(i
);
260 // Then loop through the floating point registers.
261 for (int i
= 0; i
< TheISA::NumFloatRegs
; ++i
)
263 regFile
.floatRegFile
.setRegBits(i
, src_xc
->readRegBits(i
))
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;
272 // Then finally set the PC and the next PC.
273 regFile
.pc
= src_xc
->readPC();
274 regFile
.npc
= src_xc
->readNextPC();
278 template <class Impl
>
280 FullO3CPU
<Impl
>::activateContext(int thread_num
, int delay
)
282 // Needs to set each stage to running as well.
284 scheduleTickEvent(delay
);
289 template <class Impl
>
291 FullO3CPU
<Impl
>::suspendContext(int thread_num
)
293 panic("suspendContext unimplemented!");
296 template <class Impl
>
298 FullO3CPU
<Impl
>::deallocateContext(int thread_num
)
300 panic("deallocateContext unimplemented!");
303 template <class Impl
>
305 FullO3CPU
<Impl
>::haltContext(int thread_num
)
307 panic("haltContext unimplemented!");
310 template <class Impl
>
312 FullO3CPU
<Impl
>::switchOut()
314 panic("FullO3CPU does not have a switch out function.\n");
317 template <class Impl
>
319 FullO3CPU
<Impl
>::takeOverFrom(BaseCPU
*oldCPU
)
321 BaseCPU::takeOverFrom(oldCPU
);
323 assert(!tickEvent
.scheduled());
325 // Set all status's to active, schedule the
327 for (int i
= 0; i
< execContexts
.size(); ++i
) {
328 ExecContext
*xc
= execContexts
[i
];
329 if (xc
->status() == ExecContext::Active
&& _status
!= Running
) {
331 tickEvent
.schedule(curTick
);
336 template <class Impl
>
338 FullO3CPU
<Impl
>::getAndIncrementInstSeq()
340 // Hopefully this works right.
341 return globalSeqNum
++;
344 template <class Impl
>
346 FullO3CPU
<Impl
>::readIntReg(int reg_idx
)
348 return regFile
.readIntReg(reg_idx
);
351 template <class Impl
>
353 FullO3CPU
<Impl
>::readFloatReg(int reg_idx
, int width
)
355 return regFile
.readFloatReg(reg_idx
, width
);
358 template <class Impl
>
360 FullO3CPU
<Impl
>::readFloatReg(int reg_idx
)
362 return regFile
.readFloatReg(reg_idx
);
365 template <class Impl
>
367 FullO3CPU
<Impl
>::readFloatRegBits(int reg_idx
, int width
)
369 return regFile
.readFloatRegBits(reg_idx
, width
);
372 template <class Impl
>
374 FullO3CPU
<Impl
>::readFloatRegBits(int reg_idx
)
376 return regFile
.readFloatRegBits(reg_idx
);
379 template <class Impl
>
381 FullO3CPU
<Impl
>::setIntReg(int reg_idx
, uint64_t val
)
383 regFile
.setIntReg(reg_idx
, val
);
386 template <class Impl
>
388 FullO3CPU
<Impl
>::setFloatReg(int reg_idx
, FloatReg val
, int width
)
390 regFile
.setFloatReg(reg_idx
, val
, width
);
393 template <class Impl
>
395 FullO3CPU
<Impl
>::setFloatReg(int reg_idx
, FloatReg val
)
397 regFile
.setFloatReg(reg_idx
, val
);
400 template <class Impl
>
402 FullO3CPU
<Impl
>::setFloatRegBits(int reg_idx
, FloatRegBits val
, int width
)
404 regFile
.setFloatRegBits(reg_idx
, val
, width
);
407 template <class Impl
>
409 FullO3CPU
<Impl
>::setFloatRegBits(int reg_idx
, FloatRegBits val
)
411 regFile
.setFloatRegBits(reg_idx
, val
);
414 template <class Impl
>
416 FullO3CPU
<Impl
>::readPC()
418 return regFile
.readPC();
421 template <class Impl
>
423 FullO3CPU
<Impl
>::setNextPC(uint64_t val
)
425 regFile
.setNextPC(val
);
428 template <class Impl
>
430 FullO3CPU
<Impl
>::setPC(Addr new_PC
)
432 regFile
.setPC(new_PC
);
435 template <class Impl
>
437 FullO3CPU
<Impl
>::addInst(DynInstPtr
&inst
)
439 instList
.push_back(inst
);
442 template <class Impl
>
444 FullO3CPU
<Impl
>::instDone()
446 // Keep an instruction count.
449 // Check for instruction-count-based events.
450 comInstEventQueue
[0]->serviceEvents(numInsts
);
453 template <class Impl
>
455 FullO3CPU
<Impl
>::removeBackInst(DynInstPtr
&inst
)
457 DynInstPtr inst_to_delete
;
459 // Walk through the instruction list, removing any instructions
460 // that were inserted after the given instruction, inst.
461 while (instList
.back() != inst
)
463 assert(!instList
.empty());
465 // Obtain the pointer to the instruction.
466 inst_to_delete
= instList
.back();
468 DPRINTF(FullCPU
, "FullCPU: Removing instruction %i, PC %#x\n",
469 inst_to_delete
->seqNum
, inst_to_delete
->readPC());
471 // Remove the instruction from the list.
474 // Mark it as squashed.
475 inst_to_delete
->setSquashed();
479 template <class Impl
>
481 FullO3CPU
<Impl
>::removeFrontInst(DynInstPtr
&inst
)
483 DynInstPtr inst_to_remove
;
485 // The front instruction should be the same one being asked to be removed.
486 assert(instList
.front() == inst
);
488 // Remove the front instruction.
489 inst_to_remove
= inst
;
490 instList
.pop_front();
492 DPRINTF(FullCPU
, "FullCPU: Removing committed instruction %#x, PC %#x\n",
493 inst_to_remove
, inst_to_remove
->readPC());
496 template <class Impl
>
498 FullO3CPU
<Impl
>::removeInstsNotInROB()
500 DPRINTF(FullCPU
, "FullCPU: Deleting instructions from instruction "
503 DynInstPtr rob_tail
= rob
.readTailInst();
505 removeBackInst(rob_tail
);
508 template <class Impl
>
510 FullO3CPU
<Impl
>::removeInstsUntil(const InstSeqNum
&seq_num
)
512 DPRINTF(FullCPU
, "FullCPU: Deleting instructions from instruction "
515 DynInstPtr inst_to_delete
;
517 while (instList
.back()->seqNum
> seq_num
) {
518 assert(!instList
.empty());
520 // Obtain the pointer to the instruction.
521 inst_to_delete
= instList
.back();
523 DPRINTF(FullCPU
, "FullCPU: Removing instruction %i, PC %#x\n",
524 inst_to_delete
->seqNum
, inst_to_delete
->readPC());
526 // Remove the instruction from the list.
527 instList
.back() = NULL
;
530 // Mark it as squashed.
531 inst_to_delete
->setSquashed();
536 template <class Impl
>
538 FullO3CPU
<Impl
>::removeAllInsts()
543 template <class Impl
>
545 FullO3CPU
<Impl
>::dumpInsts()
548 typename list
<DynInstPtr
>::iterator inst_list_it
= instList
.begin();
550 while (inst_list_it
!= instList
.end())
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());
560 template <class Impl
>
562 FullO3CPU
<Impl
>::wakeDependents(DynInstPtr
&inst
)
564 iew
.wakeDependents(inst
);
567 // Forward declaration of FullO3CPU.
568 template class FullO3CPU
<AlphaSimpleImpl
>;