2 * Copyright (c) 2004-2006 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 "arch/alpha/faults.hh"
30 #include "base/cprintf.hh"
31 #include "base/statistics.hh"
32 #include "base/timebuf.hh"
33 #include "cpu/checker/exec_context.hh"
34 #include "cpu/quiesce_event.hh"
35 #include "mem/mem_interface.hh"
36 #include "sim/sim_events.hh"
37 #include "sim/stats.hh"
39 #include "cpu/o3/alpha_cpu.hh"
40 #include "cpu/o3/alpha_params.hh"
41 #include "cpu/o3/comm.hh"
42 #include "cpu/o3/thread_state.hh"
45 #include "arch/alpha/osfpal.hh"
46 #include "arch/isa_traits.hh"
49 using namespace TheISA;
52 AlphaFullCPU<Impl>::AlphaFullCPU(Params *params)
54 : FullO3CPU<Impl>(params), itb(params->itb), dtb(params->dtb)
56 : FullO3CPU<Impl>(params)
59 DPRINTF(FullCPU, "AlphaFullCPU: Creating AlphaFullCPU object.\n");
61 this->thread.resize(this->numThreads);
63 for (int i = 0; i < this->numThreads; ++i) {
65 assert(this->numThreads == 1);
66 this->thread[i] = new Thread(this, 0, params->mem);
67 this->thread[i]->setStatus(ExecContext::Suspended);
69 if (i < params->workload.size()) {
70 DPRINTF(FullCPU, "FullCPU: Workload[%i]'s starting PC is %#x, "
72 i, params->workload[i]->prog_entry, this->thread[i]);
73 this->thread[i] = new Thread(this, i, params->workload[i], i);
74 assert(params->workload[i]->getMemory() != NULL);
76 this->thread[i]->setStatus(ExecContext::Suspended);
80 //Allocate Empty execution context so M5 can use later
81 //when scheduling threads to CPU
82 Process* dummy_proc = NULL;
84 this->thread[i] = new Thread(this, i, dummy_proc, i);
85 //usedTids[i] = false;
87 #endif // !FULL_SYSTEM
89 this->thread[i]->numInst = 0;
91 ExecContext *xc_proxy;
93 AlphaXC *alpha_xc_proxy = new AlphaXC;
95 if (params->checker) {
96 xc_proxy = new CheckerExecContext<AlphaXC>(alpha_xc_proxy, this->checker);
98 xc_proxy = alpha_xc_proxy;
101 alpha_xc_proxy->cpu = this;
102 alpha_xc_proxy->thread = this->thread[i];
104 alpha_xc_proxy->quiesceEvent =
105 new EndQuiesceEvent(xc_proxy);
106 alpha_xc_proxy->lastActivate = 0;
107 alpha_xc_proxy->lastSuspend = 0;
109 this->thread[i]->xcProxy = xc_proxy;
111 this->execContexts.push_back(xc_proxy);
115 for (int i=0; i < this->numThreads; i++) {
116 this->thread[i]->funcExeInst = 0;
119 // Sets CPU pointers. These must be set at this level because the CPU
120 // pointers are defined to be the highest level of CPU class.
121 this->fetch.setCPU(this);
122 this->decode.setCPU(this);
123 this->rename.setCPU(this);
124 this->iew.setCPU(this);
125 this->commit.setCPU(this);
127 this->rob.setCPU(this);
128 this->regFile.setCPU(this);
134 template <class Impl>
136 AlphaFullCPU<Impl>::regStats()
138 // Register stats for everything that has stats.
139 this->fullCPURegStats();
140 this->fetch.regStats();
141 this->decode.regStats();
142 this->rename.regStats();
143 this->iew.regStats();
144 this->commit.regStats();
148 template <class Impl>
150 AlphaFullCPU<Impl>::AlphaXC::dumpFuncProfile()
152 // Currently not supported
156 template <class Impl>
158 AlphaFullCPU<Impl>::AlphaXC::takeOverFrom(ExecContext *old_context)
160 // some things should already be set up
161 assert(getMemPtr() == old_context->getMemPtr());
163 assert(getSystemPtr() == old_context->getSystemPtr());
165 assert(getProcessPtr() == old_context->getProcessPtr());
168 // copy over functional state
169 setStatus(old_context->status());
170 copyArchRegs(old_context);
171 setCpuId(old_context->readCpuId());
173 thread->funcExeInst = old_context->readFuncExeInst();
176 EndQuiesceEvent *other_quiesce = old_context->getQuiesceEvent();
178 // Point the quiesce event's XC at this XC so that it wakes up
180 other_quiesce->xc = this;
182 if (thread->quiesceEvent) {
183 thread->quiesceEvent->xc = this;
185 // storeCondFailures = 0;
186 cpu->lockFlag = false;
188 old_context->setStatus(ExecContext::Unallocated);
190 thread->inSyscall = false;
191 thread->trapPending = false;
194 template <class Impl>
196 AlphaFullCPU<Impl>::AlphaXC::activate(int delay)
198 DPRINTF(FullCPU, "Calling activate on AlphaXC\n");
200 if (thread->status() == ExecContext::Active)
203 lastActivate = curTick;
205 if (thread->status() == ExecContext::Unallocated) {
206 cpu->activateWhenReady(thread->tid);
210 thread->setStatus(ExecContext::Active);
212 // status() == Suspended
213 cpu->activateContext(thread->tid, delay);
216 template <class Impl>
218 AlphaFullCPU<Impl>::AlphaXC::suspend()
220 DPRINTF(FullCPU, "Calling suspend on AlphaXC\n");
222 if (thread->status() == ExecContext::Suspended)
225 lastActivate = curTick;
226 lastSuspend = curTick;
229 // Don't change the status from active if there are pending interrupts
230 if (cpu->check_interrupts()) {
231 assert(status() == ExecContext::Active);
236 thread->setStatus(ExecContext::Suspended);
237 cpu->suspendContext(thread->tid);
240 template <class Impl>
242 AlphaFullCPU<Impl>::AlphaXC::deallocate()
244 DPRINTF(FullCPU, "Calling deallocate on AlphaXC\n");
246 if (thread->status() == ExecContext::Unallocated)
249 thread->setStatus(ExecContext::Unallocated);
250 cpu->deallocateContext(thread->tid);
253 template <class Impl>
255 AlphaFullCPU<Impl>::AlphaXC::halt()
257 DPRINTF(FullCPU, "Calling halt on AlphaXC\n");
259 if (thread->status() == ExecContext::Halted)
262 thread->setStatus(ExecContext::Halted);
263 cpu->haltContext(thread->tid);
266 template <class Impl>
268 AlphaFullCPU<Impl>::AlphaXC::regStats(const std::string &name)
271 template <class Impl>
273 AlphaFullCPU<Impl>::AlphaXC::serialize(std::ostream &os)
276 template <class Impl>
278 AlphaFullCPU<Impl>::AlphaXC::unserialize(Checkpoint *cp, const std::string §ion)
282 template <class Impl>
284 AlphaFullCPU<Impl>::AlphaXC::getQuiesceEvent()
289 template <class Impl>
291 AlphaFullCPU<Impl>::AlphaXC::readLastActivate()
296 template <class Impl>
298 AlphaFullCPU<Impl>::AlphaXC::readLastSuspend()
303 template <class Impl>
305 AlphaFullCPU<Impl>::AlphaXC::profileClear()
308 template <class Impl>
310 AlphaFullCPU<Impl>::AlphaXC::profileSample()
314 template <class Impl>
316 AlphaFullCPU<Impl>::AlphaXC:: getInst()
321 template <class Impl>
323 AlphaFullCPU<Impl>::AlphaXC::copyArchRegs(ExecContext *xc)
325 // This function will mess things up unless the ROB is empty and
326 // there are no instructions in the pipeline.
327 unsigned tid = thread->tid;
328 PhysRegIndex renamed_reg;
330 // First loop through the integer registers.
331 for (int i = 0; i < AlphaISA::NumIntRegs; ++i) {
332 renamed_reg = cpu->renameMap[tid].lookup(i);
334 DPRINTF(FullCPU, "FullCPU: Copying over register %i, had data %lli, "
335 "now has data %lli.\n",
336 renamed_reg, cpu->readIntReg(renamed_reg),
339 cpu->setIntReg(renamed_reg, xc->readIntReg(i));
342 // Then loop through the floating point registers.
343 for (int i = 0; i < AlphaISA::NumFloatRegs; ++i) {
344 renamed_reg = cpu->renameMap[tid].lookup(i + AlphaISA::FP_Base_DepTag);
345 cpu->setFloatRegDouble(renamed_reg,
346 xc->readFloatRegDouble(i));
347 cpu->setFloatRegInt(renamed_reg,
348 xc->readFloatRegInt(i));
351 // Copy the misc regs.
352 cpu->regFile.miscRegs[tid].copyMiscRegs(xc);
354 // Then finally set the PC and the next PC.
355 cpu->setPC(xc->readPC(), tid);
356 cpu->setNextPC(xc->readNextPC(), tid);
358 this->thread->funcExeInst = xc->readFuncExeInst();
362 template <class Impl>
364 AlphaFullCPU<Impl>::AlphaXC::clearArchRegs()
367 template <class Impl>
369 AlphaFullCPU<Impl>::AlphaXC::readIntReg(int reg_idx)
371 DPRINTF(Fault, "Reading int register through the XC!\n");
372 return cpu->readArchIntReg(reg_idx, thread->tid);
375 template <class Impl>
377 AlphaFullCPU<Impl>::AlphaXC::readFloatRegSingle(int reg_idx)
379 DPRINTF(Fault, "Reading float register through the XC!\n");
380 return cpu->readArchFloatRegSingle(reg_idx, thread->tid);
383 template <class Impl>
385 AlphaFullCPU<Impl>::AlphaXC::readFloatRegDouble(int reg_idx)
387 DPRINTF(Fault, "Reading float register through the XC!\n");
388 return cpu->readArchFloatRegDouble(reg_idx, thread->tid);
391 template <class Impl>
393 AlphaFullCPU<Impl>::AlphaXC::readFloatRegInt(int reg_idx)
395 DPRINTF(Fault, "Reading floatint register through the XC!\n");
396 return cpu->readArchFloatRegInt(reg_idx, thread->tid);
399 template <class Impl>
401 AlphaFullCPU<Impl>::AlphaXC::setIntReg(int reg_idx, uint64_t val)
403 DPRINTF(Fault, "Setting int register through the XC!\n");
404 cpu->setArchIntReg(reg_idx, val, thread->tid);
406 if (!thread->trapPending && !thread->inSyscall) {
407 cpu->squashFromXC(thread->tid);
411 template <class Impl>
413 AlphaFullCPU<Impl>::AlphaXC::setFloatRegSingle(int reg_idx, float val)
415 DPRINTF(Fault, "Setting float register through the XC!\n");
416 cpu->setArchFloatRegSingle(reg_idx, val, thread->tid);
418 if (!thread->trapPending && !thread->inSyscall) {
419 cpu->squashFromXC(thread->tid);
423 template <class Impl>
425 AlphaFullCPU<Impl>::AlphaXC::setFloatRegDouble(int reg_idx, double val)
427 DPRINTF(Fault, "Setting float register through the XC!\n");
428 cpu->setArchFloatRegDouble(reg_idx, val, thread->tid);
430 if (!thread->trapPending && !thread->inSyscall) {
431 cpu->squashFromXC(thread->tid);
435 template <class Impl>
437 AlphaFullCPU<Impl>::AlphaXC::setFloatRegInt(int reg_idx, uint64_t val)
439 DPRINTF(Fault, "Setting floatint register through the XC!\n");
440 cpu->setArchFloatRegInt(reg_idx, val, thread->tid);
442 if (!thread->trapPending && !thread->inSyscall) {
443 cpu->squashFromXC(thread->tid);
447 template <class Impl>
449 AlphaFullCPU<Impl>::AlphaXC::setPC(uint64_t val)
451 cpu->setPC(val, thread->tid);
453 if (!thread->trapPending && !thread->inSyscall) {
454 cpu->squashFromXC(thread->tid);
458 template <class Impl>
460 AlphaFullCPU<Impl>::AlphaXC::setNextPC(uint64_t val)
462 cpu->setNextPC(val, thread->tid);
464 if (!thread->trapPending && !thread->inSyscall) {
465 cpu->squashFromXC(thread->tid);
469 template <class Impl>
471 AlphaFullCPU<Impl>::AlphaXC::setMiscReg(int misc_reg, const MiscReg &val)
473 DPRINTF(Fault, "Setting misc register through the XC!\n");
475 Fault ret_fault = cpu->setMiscReg(misc_reg, val, thread->tid);
477 if (!thread->trapPending && !thread->inSyscall) {
478 cpu->squashFromXC(thread->tid);
484 template <class Impl>
486 AlphaFullCPU<Impl>::AlphaXC::setMiscRegWithEffect(int misc_reg, const MiscReg &val)
488 DPRINTF(Fault, "Setting misc register through the XC!\n");
490 Fault ret_fault = cpu->setMiscRegWithEffect(misc_reg, val, thread->tid);
492 if (!thread->trapPending && !thread->inSyscall) {
493 cpu->squashFromXC(thread->tid);
501 template <class Impl>
503 AlphaFullCPU<Impl>::AlphaXC::getSyscallArg(int i)
505 return cpu->getSyscallArg(i, thread->tid);
508 template <class Impl>
510 AlphaFullCPU<Impl>::AlphaXC::setSyscallArg(int i, IntReg val)
512 cpu->setSyscallArg(i, val, thread->tid);
515 template <class Impl>
517 AlphaFullCPU<Impl>::AlphaXC::setSyscallReturn(SyscallReturn return_value)
519 cpu->setSyscallReturn(return_value, thread->tid);
522 #endif // FULL_SYSTEM
524 template <class Impl>
526 AlphaFullCPU<Impl>::readMiscReg(int misc_reg, unsigned tid)
528 return this->regFile.readMiscReg(misc_reg, tid);
531 template <class Impl>
533 AlphaFullCPU<Impl>::readMiscRegWithEffect(int misc_reg, Fault &fault,
536 return this->regFile.readMiscRegWithEffect(misc_reg, fault, tid);
539 template <class Impl>
541 AlphaFullCPU<Impl>::setMiscReg(int misc_reg, const MiscReg &val, unsigned tid)
543 return this->regFile.setMiscReg(misc_reg, val, tid);
546 template <class Impl>
548 AlphaFullCPU<Impl>::setMiscRegWithEffect(int misc_reg, const MiscReg &val,
551 return this->regFile.setMiscRegWithEffect(misc_reg, val, tid);
554 template <class Impl>
556 AlphaFullCPU<Impl>::squashFromXC(unsigned tid)
558 this->thread[tid]->inSyscall = true;
559 this->commit.generateXCEvent(tid);
564 template <class Impl>
566 AlphaFullCPU<Impl>::post_interrupt(int int_num, int index)
568 BaseCPU::post_interrupt(int_num, index);
570 if (this->thread[0]->status() == ExecContext::Suspended) {
571 DPRINTF(IPI,"Suspended Processor awoke\n");
572 // xcProxies[0]->activate();
573 this->execContexts[0]->activate();
577 template <class Impl>
579 AlphaFullCPU<Impl>::readIntrFlag()
581 return this->regFile.readIntrFlag();
584 template <class Impl>
586 AlphaFullCPU<Impl>::setIntrFlag(int val)
588 this->regFile.setIntrFlag(val);
591 template <class Impl>
593 AlphaFullCPU<Impl>::hwrei(unsigned tid)
595 // Need to clear the lock flag upon returning from an interrupt.
596 this->lockFlag = false;
598 this->kernelStats->hwrei();
600 this->checkInterrupts = true;
602 // FIXME: XXX check for interrupts? XXX
606 template <class Impl>
608 AlphaFullCPU<Impl>::simPalCheck(int palFunc, unsigned tid)
610 if (this->kernelStats)
611 this->kernelStats->callpal(palFunc,
612 this->execContexts[tid]);
617 if (--System::numSystemsRunning == 0)
618 new SimExitEvent("all cpus halted");
623 if (this->system->breakpoint())
631 template <class Impl>
633 AlphaFullCPU<Impl>::trap(Fault fault, unsigned tid)
635 fault->invoke(this->execContexts[tid]);
638 template <class Impl>
640 AlphaFullCPU<Impl>::processInterrupts()
642 // Check for interrupts here. For now can copy the code that
643 // exists within isa_fullsys_traits.hh. Also assume that thread 0
644 // is the one that handles the interrupts.
645 // @todo: Possibly consolidate the interrupt checking code.
646 // @todo: Allow other threads to handle interrupts.
648 // Check if there are any outstanding interrupts
649 //Handle the interrupts
653 this->checkInterrupts = false;
655 if (this->readMiscReg(IPR_ASTRR, 0))
656 panic("asynchronous traps not implemented\n");
658 if (this->readMiscReg(IPR_SIRR, 0)) {
659 for (int i = INTLEVEL_SOFTWARE_MIN;
660 i < INTLEVEL_SOFTWARE_MAX; i++) {
661 if (this->readMiscReg(IPR_SIRR, 0) & (ULL(1) << i)) {
662 // See table 4-19 of the 21164 hardware reference
663 ipl = (i - INTLEVEL_SOFTWARE_MIN) + 1;
664 summary |= (ULL(1) << i);
669 uint64_t interrupts = this->intr_status();
672 for (int i = INTLEVEL_EXTERNAL_MIN;
673 i < INTLEVEL_EXTERNAL_MAX; i++) {
674 if (interrupts & (ULL(1) << i)) {
675 // See table 4-19 of the 21164 hardware reference
677 summary |= (ULL(1) << i);
682 if (ipl && ipl > this->readMiscReg(IPR_IPLR, 0)) {
683 this->setMiscReg(IPR_ISR, summary, 0);
684 this->setMiscReg(IPR_INTID, ipl, 0);
686 this->checker->cpuXCBase()->setMiscReg(IPR_ISR, summary);
687 this->checker->cpuXCBase()->setMiscReg(IPR_INTID, ipl);
689 this->trap(Fault(new InterruptFault), 0);
690 DPRINTF(Flow, "Interrupt! IPLR=%d ipl=%d summary=%x\n",
691 this->readMiscReg(IPR_IPLR, 0), ipl, summary);
695 #endif // FULL_SYSTEM
699 template <class Impl>
701 AlphaFullCPU<Impl>::syscall(int tid)
703 DPRINTF(FullCPU, "AlphaFullCPU: [tid:%i] Executing syscall().\n\n", tid);
705 DPRINTF(Activity,"Activity: syscall() called.\n");
707 // Temporarily increase this by one to account for the syscall
709 ++(this->thread[tid]->funcExeInst);
711 // Execute the actual syscall.
712 this->thread[tid]->syscall();
714 // Decrease funcExeInst by one as the normal commit will handle
716 --(this->thread[tid]->funcExeInst);
719 template <class Impl>
721 AlphaFullCPU<Impl>::getSyscallArg(int i, int tid)
723 return this->readArchIntReg(AlphaISA::ArgumentReg0 + i, tid);
726 template <class Impl>
728 AlphaFullCPU<Impl>::setSyscallArg(int i, IntReg val, int tid)
730 this->setArchIntReg(AlphaISA::ArgumentReg0 + i, val, tid);
733 template <class Impl>
735 AlphaFullCPU<Impl>::setSyscallReturn(SyscallReturn return_value, int tid)
737 // check for error condition. Alpha syscall convention is to
738 // indicate success/failure in reg a3 (r19) and put the
739 // return value itself in the standard return value reg (v0).
740 if (return_value.successful()) {
742 this->setArchIntReg(SyscallSuccessReg, 0, tid);
743 this->setArchIntReg(ReturnValueReg, return_value.value(), tid);
745 // got an error, return details
746 this->setArchIntReg(SyscallSuccessReg, (IntReg) -1, tid);
747 this->setArchIntReg(ReturnValueReg, -return_value.value(), tid);