From ff3d16ca1f7d83ce7932868d2bf1cb3e526562ea Mon Sep 17 00:00:00 2001 From: Kevin Lim Date: Tue, 23 May 2006 16:51:16 -0400 Subject: [PATCH] Move kernel stats out of CPU and into XC. arch/alpha/ev5.cc: Move kernel stats out of CPU and into XC. Also be sure to check if the kernel stats exist prior to using them. --HG-- extra : convert_revision : 565cd7026410fd7d8586f953d9b328c2e67a9473 --- arch/alpha/ev5.cc | 22 ++-- cpu/base.cc | 23 ---- cpu/base.hh | 10 +- cpu/checker/exec_context.hh | 44 +++++++- cpu/cpu_exec_context.cc | 9 +- cpu/cpu_exec_context.hh | 7 ++ cpu/exec_context.hh | 7 ++ cpu/o3/alpha_cpu.hh | 11 +- cpu/o3/alpha_cpu_impl.hh | 62 ++++++++--- cpu/ozone/cpu.hh | 28 ++--- cpu/ozone/cpu_impl.hh | 211 ++++++------------------------------ cpu/simple/cpu.cc | 2 +- cpu/thread_state.hh | 39 ++++++- kern/system_events.cc | 11 +- sim/pseudo_inst.cc | 15 ++- 15 files changed, 223 insertions(+), 278 deletions(-) diff --git a/arch/alpha/ev5.cc b/arch/alpha/ev5.cc index 019e83dd4..ad3a9ec4c 100644 --- a/arch/alpha/ev5.cc +++ b/arch/alpha/ev5.cc @@ -146,7 +146,7 @@ CPUExecContext::hwrei() setNextPC(readMiscReg(AlphaISA::IPR_EXC_ADDR)); if (!misspeculating()) { - cpu->kernelStats->hwrei(); + kernelStats->hwrei(); cpu->checkInterrupts = true; } @@ -336,7 +336,8 @@ AlphaISA::MiscRegFile::setIpr(int idx, uint64_t val, ExecContext *xc) // write entire quad w/ no side-effect old = ipr[idx]; ipr[idx] = val; - xc->getCpuPtr()->kernelStats->context(old, val, xc); + if (xc->getKernelStats()) + xc->getKernelStats()->context(old, val, xc); break; case AlphaISA::IPR_DTB_PTE: @@ -363,14 +364,19 @@ AlphaISA::MiscRegFile::setIpr(int idx, uint64_t val, ExecContext *xc) // only write least significant five bits - interrupt level ipr[idx] = val & 0x1f; - xc->getCpuPtr()->kernelStats->swpipl(ipr[idx]); + if (xc->getKernelStats()) + xc->getKernelStats()->swpipl(ipr[idx]); break; case AlphaISA::IPR_DTB_CM: - if (val & 0x18) - xc->getCpuPtr()->kernelStats->mode(Kernel::user, xc); - else - xc->getCpuPtr()->kernelStats->mode(Kernel::kernel, xc); + if (val & 0x18) { + if (xc->getKernelStats()) + xc->getKernelStats()->mode(Kernel::user, xc); + else { + if (xc->getKernelStats()) + xc->getKernelStats()->mode(Kernel::kernel, xc); + } + } case AlphaISA::IPR_ICM: // only write two mode bits - processor mode @@ -556,7 +562,7 @@ AlphaISA::MiscRegFile::copyIprs(ExecContext *xc) bool CPUExecContext::simPalCheck(int palFunc) { - cpu->kernelStats->callpal(palFunc, proxy); + kernelStats->callpal(palFunc, proxy); switch (palFunc) { case PAL::halt: diff --git a/cpu/base.cc b/cpu/base.cc index 74b679d5d..de03b9eab 100644 --- a/cpu/base.cc +++ b/cpu/base.cc @@ -45,10 +45,6 @@ #include "base/trace.hh" -#if FULL_SYSTEM -#include "kern/kernel_stats.hh" -#endif - using namespace std; vector BaseCPU::cpuList; @@ -153,8 +149,6 @@ BaseCPU::BaseCPU(Params *p) profileEvent = NULL; if (params->profile) profileEvent = new ProfileEvent(this, params->profile); - - kernelStats = new Kernel::Statistics(system); #endif } @@ -175,10 +169,6 @@ BaseCPU::enableFunctionTrace() BaseCPU::~BaseCPU() { -#if FULL_SYSTEM - if (kernelStats) - delete kernelStats; -#endif } void @@ -219,8 +209,6 @@ BaseCPU::regStats() execContexts[0]->regStats(name()); #if FULL_SYSTEM - if (kernelStats) - kernelStats->regStats(name() + ".kern"); #endif } @@ -348,12 +336,6 @@ BaseCPU::serialize(std::ostream &os) { SERIALIZE_ARRAY(interrupts, TheISA::NumInterruptLevels); SERIALIZE_SCALAR(intstatus); - -#if FULL_SYSTEM - if (kernelStats) - kernelStats->serialize(os); -#endif - } void @@ -361,11 +343,6 @@ BaseCPU::unserialize(Checkpoint *cp, const std::string §ion) { UNSERIALIZE_ARRAY(interrupts, TheISA::NumInterruptLevels); UNSERIALIZE_SCALAR(intstatus); - -#if FULL_SYSTEM - if (kernelStats) - kernelStats->unserialize(cp, section); -#endif } #endif // FULL_SYSTEM diff --git a/cpu/base.hh b/cpu/base.hh index 20166d7ee..dd776859d 100644 --- a/cpu/base.hh +++ b/cpu/base.hh @@ -38,14 +38,10 @@ #include "sim/sim_object.hh" #include "arch/isa_traits.hh" -#if FULL_SYSTEM -class System; -namespace Kernel { class Statistics; } -#endif - class BranchPred; class CheckerCPU; class ExecContext; +class System; class BaseCPU : public SimObject { @@ -237,10 +233,6 @@ class BaseCPU : public SimObject public: // Number of CPU cycles simulated Stats::Scalar<> numCycles; - -#if FULL_SYSTEM - Kernel::Statistics *kernelStats; -#endif }; #endif // __CPU_BASE_HH__ diff --git a/cpu/checker/exec_context.hh b/cpu/checker/exec_context.hh index 4843d1cf0..38784867d 100644 --- a/cpu/checker/exec_context.hh +++ b/cpu/checker/exec_context.hh @@ -1,3 +1,31 @@ +/* + * Copyright (c) 2006 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + #ifndef __CPU_CHECKER_EXEC_CONTEXT_HH__ #define __CPU_CHECKER_EXEC_CONTEXT_HH__ @@ -6,6 +34,9 @@ #include "cpu/exec_context.hh" class EndQuiesceEvent; +namespace Kernel { + class Statistics; +}; template class CheckerExecContext : public ExecContext @@ -13,7 +44,8 @@ class CheckerExecContext : public ExecContext public: CheckerExecContext(XC *actual_xc, CheckerCPU *checker_cpu) - : actualXC(actual_xc), checkerXC(checker_cpu->cpuXC), checkerCPU(checker_cpu) + : actualXC(actual_xc), checkerXC(checker_cpu->cpuXC), + checkerCPU(checker_cpu) { } private: @@ -43,6 +75,8 @@ class CheckerExecContext : public ExecContext AlphaITB *getITBPtr() { return actualXC->getITBPtr(); } AlphaDTB *getDTBPtr() { return actualXC->getDTBPtr(); } + + Kernel::Statistics *getKernelStats() { return actualXC->getKernelStats(); } #else Process *getProcessPtr() { return actualXC->getProcessPtr(); } #endif @@ -50,8 +84,10 @@ class CheckerExecContext : public ExecContext Status status() const { return actualXC->status(); } void setStatus(Status new_status) - { actualXC->setStatus(new_status); - checkerXC->setStatus(new_status); } + { + actualXC->setStatus(new_status); + checkerXC->setStatus(new_status); + } /// Set the status to Active. Optional delay indicates number of /// cycles to wait before beginning execution. @@ -216,8 +252,6 @@ class CheckerExecContext : public ExecContext actualXC->setSyscallReturn(return_value); } -// void syscall() { actualXC->syscall(); } - Counter readFuncExeInst() { return actualXC->readFuncExeInst(); } #endif }; diff --git a/cpu/cpu_exec_context.cc b/cpu/cpu_exec_context.cc index 24de6d450..78ce058e8 100644 --- a/cpu/cpu_exec_context.cc +++ b/cpu/cpu_exec_context.cc @@ -188,7 +188,8 @@ CPUExecContext::serialize(ostream &os) if (quiesceEvent->scheduled()) quiesceEndTick = quiesceEvent->when(); SERIALIZE_SCALAR(quiesceEndTick); - + if (kernelStats) + kernelStats->serialize(os); #endif } @@ -207,6 +208,8 @@ CPUExecContext::unserialize(Checkpoint *cp, const std::string §ion) UNSERIALIZE_SCALAR(quiesceEndTick); if (quiesceEndTick) quiesceEvent->schedule(quiesceEndTick); + if (kernelStats) + kernelStats->unserialize(cp, section); #endif } @@ -275,6 +278,10 @@ CPUExecContext::halt() void CPUExecContext::regStats(const string &name) { +#if FULL_SYSTEM + kernelStats = new Kernel::Statistics(system); + kernelStats->regStats(name + ".kern"); +#endif } void diff --git a/cpu/cpu_exec_context.hh b/cpu/cpu_exec_context.hh index cac006925..3d1428933 100644 --- a/cpu/cpu_exec_context.hh +++ b/cpu/cpu_exec_context.hh @@ -53,6 +53,10 @@ class FunctionProfile; class ProfileNode; class MemoryController; +namespace Kernel { + class Statistics; +}; + #else // !FULL_SYSTEM #include "sim/process.hh" @@ -147,6 +151,9 @@ class CPUExecContext void profileSample(); + Kernel::Statistics *getKernelStats() { return kernelStats; } + + Kernel::Statistics *kernelStats; #else Process *process; diff --git a/cpu/exec_context.hh b/cpu/exec_context.hh index 7bd7d5682..e1f1016e5 100644 --- a/cpu/exec_context.hh +++ b/cpu/exec_context.hh @@ -48,6 +48,9 @@ class FunctionalMemory; class PhysicalMemory; class Process; class System; +namespace Kernel { + class Statistics; +}; class ExecContext { @@ -98,6 +101,8 @@ class ExecContext virtual AlphaITB *getITBPtr() = 0; virtual AlphaDTB * getDTBPtr() = 0; + + virtual Kernel::Statistics *getKernelStats() = 0; #else virtual Process *getProcessPtr() = 0; #endif @@ -243,6 +248,8 @@ class ProxyExecContext : public ExecContext AlphaITB *getITBPtr() { return actualXC->getITBPtr(); } AlphaDTB *getDTBPtr() { return actualXC->getDTBPtr(); } + + Kernel::Statistics *getKernelStats() { return actualXC->getKernelStats(); } #else Process *getProcessPtr() { return actualXC->getProcessPtr(); } #endif diff --git a/cpu/o3/alpha_cpu.hh b/cpu/o3/alpha_cpu.hh index 78ad5f7d8..5c89e3462 100644 --- a/cpu/o3/alpha_cpu.hh +++ b/cpu/o3/alpha_cpu.hh @@ -35,6 +35,9 @@ #include "sim/byteswap.hh" class EndQuiesceEvent; +namespace Kernel { + class Statistics; +}; template class AlphaFullCPU : public FullO3CPU @@ -60,11 +63,6 @@ class AlphaFullCPU : public FullO3CPU O3ThreadState *thread; - Tick lastActivate; - Tick lastSuspend; - - EndQuiesceEvent *quiesceEvent; - virtual BaseCPU *getCpuPtr() { return cpu; } virtual void setCpuId(int id) { cpu->cpu_id = id; } @@ -81,6 +79,9 @@ class AlphaFullCPU : public FullO3CPU virtual AlphaITB *getITBPtr() { return cpu->itb; } virtual AlphaDTB * getDTBPtr() { return cpu->dtb; } + + virtual Kernel::Statistics *getKernelStats() + { return thread->kernelStats; } #else virtual Process *getProcessPtr() { return thread->process; } #endif diff --git a/cpu/o3/alpha_cpu_impl.hh b/cpu/o3/alpha_cpu_impl.hh index 58b2b3548..91cd3d9e6 100644 --- a/cpu/o3/alpha_cpu_impl.hh +++ b/cpu/o3/alpha_cpu_impl.hh @@ -31,7 +31,6 @@ #include "base/statistics.hh" #include "base/timebuf.hh" #include "cpu/checker/exec_context.hh" -#include "cpu/quiesce_event.hh" #include "mem/mem_interface.hh" #include "sim/sim_events.hh" #include "sim/stats.hh" @@ -44,6 +43,8 @@ #if FULL_SYSTEM #include "arch/alpha/osfpal.hh" #include "arch/isa_traits.hh" +#include "cpu/quiesce_event.hh" +#include "kern/kernel_stats.hh" #endif using namespace TheISA; @@ -101,11 +102,12 @@ AlphaFullCPU::AlphaFullCPU(Params *params) alpha_xc_proxy->cpu = this; alpha_xc_proxy->thread = this->thread[i]; - alpha_xc_proxy->quiesceEvent = +#if FULL_SYSTEM + this->thread[i]->quiesceEvent = new EndQuiesceEvent(xc_proxy); - alpha_xc_proxy->lastActivate = 0; - alpha_xc_proxy->lastSuspend = 0; - + this->thread[i]->lastActivate = 0; + this->thread[i]->lastSuspend = 0; +#endif this->thread[i]->xcProxy = xc_proxy; this->execContexts.push_back(xc_proxy); @@ -181,6 +183,9 @@ AlphaFullCPU::AlphaXC::takeOverFrom(ExecContext *old_context) if (thread->quiesceEvent) { thread->quiesceEvent->xc = this; } + + // Transfer kernel stats from one CPU to the other. + thread->kernelStats = old_context->getKernelStats(); // storeCondFailures = 0; cpu->lockFlag = false; #endif @@ -200,7 +205,9 @@ AlphaFullCPU::AlphaXC::activate(int delay) if (thread->status() == ExecContext::Active) return; - lastActivate = curTick; +#if FULL_SYSTEM + thread->lastActivate = curTick; +#endif if (thread->status() == ExecContext::Unallocated) { cpu->activateWhenReady(thread->tid); @@ -222,8 +229,10 @@ AlphaFullCPU::AlphaXC::suspend() if (thread->status() == ExecContext::Suspended) return; - lastActivate = curTick; - lastSuspend = curTick; +#if FULL_SYSTEM + thread->lastActivate = curTick; + thread->lastSuspend = curTick; +#endif /* #if FULL_SYSTEM // Don't change the status from active if there are pending interrupts @@ -266,38 +275,55 @@ AlphaFullCPU::AlphaXC::halt() template void AlphaFullCPU::AlphaXC::regStats(const std::string &name) -{} +{ +#if FULL_SYSTEM + thread->kernelStats = new Kernel::Statistics(cpu->system); + thread->kernelStats->regStats(name + ".kern"); +#endif +} template void AlphaFullCPU::AlphaXC::serialize(std::ostream &os) -{} +{ +#if FULL_SYSTEM + if (thread->kernelStats) + thread->kernelStats->serialize(os); +#endif + +} template void AlphaFullCPU::AlphaXC::unserialize(Checkpoint *cp, const std::string §ion) -{} +{ +#if FULL_SYSTEM + if (thread->kernelStats) + thread->kernelStats->unserialize(cp, section); +#endif + +} #if FULL_SYSTEM template EndQuiesceEvent * AlphaFullCPU::AlphaXC::getQuiesceEvent() { - return quiesceEvent; + return thread->quiesceEvent; } template Tick AlphaFullCPU::AlphaXC::readLastActivate() { - return lastActivate; + return thread->lastActivate; } template Tick AlphaFullCPU::AlphaXC::readLastSuspend() { - return lastSuspend; + return thread->lastSuspend; } template @@ -595,7 +621,7 @@ AlphaFullCPU::hwrei(unsigned tid) // Need to clear the lock flag upon returning from an interrupt. this->lockFlag = false; - this->kernelStats->hwrei(); + this->thread[tid]->kernelStats->hwrei(); this->checkInterrupts = true; @@ -607,9 +633,9 @@ template bool AlphaFullCPU::simPalCheck(int palFunc, unsigned tid) { - if (this->kernelStats) - this->kernelStats->callpal(palFunc, - this->execContexts[tid]); + if (this->thread[tid]->kernelStats) + this->thread[tid]->kernelStats->callpal(palFunc, + this->execContexts[tid]); switch (palFunc) { case PAL::halt: diff --git a/cpu/ozone/cpu.hh b/cpu/ozone/cpu.hh index 7e12e75e5..5af2b02b2 100644 --- a/cpu/ozone/cpu.hh +++ b/cpu/ozone/cpu.hh @@ -57,6 +57,10 @@ class Sampler; class RemoteGDB; class GDBListener; +namespace Kernel { + class Statistics; +}; + #else class Process; @@ -116,6 +120,8 @@ class OzoneCPU : public BaseCPU AlphaITB *getITBPtr() { return cpu->itb; } AlphaDTB * getDTBPtr() { return cpu->dtb; } + + Kernel::Statistics *getKernelStats() { return thread->kernelStats; } #else Process *getProcessPtr() { return thread->process; } #endif @@ -238,14 +244,7 @@ class OzoneCPU : public BaseCPU private: OzoneThreadState thread; -/* - // Squash event for when the XC needs to squash all inflight instructions. - struct XCSquashEvent : public Event - { - void process(); - const char *description(); - }; -*/ + public: // main simulation loop (one cycle) void tick(); @@ -288,7 +287,6 @@ class OzoneCPU : public BaseCPU void trace_data(T data); public: - // enum Status { Running, Idle, @@ -325,8 +323,6 @@ class OzoneCPU : public BaseCPU int readCpuId() { return cpuId; } -// FunctionalMemory *getMemPtr() { return mem; } - int cpuId; void switchOut(Sampler *sampler); @@ -369,8 +365,6 @@ class OzoneCPU : public BaseCPU Status status() const { return _status; } void setStatus(Status new_status) { _status = new_status; } - // Not sure what an activate() call on the CPU's proxy XC would mean... - virtual void activateContext(int thread_num, int delay); virtual void suspendContext(int thread_num); virtual void deallocateContext(int thread_num); @@ -384,7 +378,6 @@ class OzoneCPU : public BaseCPU public: Counter numInst; Counter startNumInst; -// Stats::Scalar<> numInsts; virtual Counter totalInstructions() const { @@ -392,9 +385,6 @@ class OzoneCPU : public BaseCPU } private: - // number of simulated memory references -// Stats::Scalar<> numMemRefs; - // number of simulated loads Counter numLoad; Counter startNumLoad; @@ -472,7 +462,6 @@ class OzoneCPU : public BaseCPU template Fault read(MemReqPtr &req, T &data) { -// panic("CPU READ NOT IMPLEMENTED W/NEW MEMORY\n"); #if 0 #if FULL_SYSTEM && defined(TARGET_ALPHA) if (req->flags & LOCKED) { @@ -483,7 +472,6 @@ class OzoneCPU : public BaseCPU #endif Fault error; if (req->flags & LOCKED) { -// lockAddr = req->paddr; lockAddrList.insert(req->paddr); lockFlag = true; } @@ -558,7 +546,7 @@ class OzoneCPU : public BaseCPU if (req->flags & UNCACHEABLE) { req->result = 2; } else { - if (this->lockFlag/* && this->lockAddr == req->paddr*/) { + if (this->lockFlag) { if (lockAddrList.find(req->paddr) != lockAddrList.end()) { req->result = 1; diff --git a/cpu/ozone/cpu_impl.hh b/cpu/ozone/cpu_impl.hh index 031b4b145..5675da3a8 100644 --- a/cpu/ozone/cpu_impl.hh +++ b/cpu/ozone/cpu_impl.hh @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005 The Regents of The University of Michigan + * Copyright (c) 2006 The Regents of The University of Michigan * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -26,8 +26,8 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include -#include +//#include +//#include #include "arch/isa_traits.hh" // For MachInst #include "base/trace.hh" @@ -39,7 +39,7 @@ #include "cpu/ozone/cpu.hh" #include "cpu/quiesce_event.hh" #include "cpu/static_inst.hh" -#include "mem/base_mem.hh" +//#include "mem/base_mem.hh" #include "mem/mem_interface.hh" #include "sim/sim_object.hh" #include "sim/stats.hh" @@ -50,7 +50,7 @@ #include "arch/alpha/tlb.hh" #include "arch/vtophys.hh" #include "base/callback.hh" -#include "base/remote_gdb.hh" +//#include "base/remote_gdb.hh" #include "cpu/profile.hh" #include "kern/kernel_stats.hh" #include "mem/functional/memory_control.hh" @@ -94,80 +94,26 @@ OzoneCPU::TickEvent::description() { return "OzoneCPU tick event"; } -/* -template -OzoneCPU::ICacheCompletionEvent::ICacheCompletionEvent(OzoneCPU *_cpu) - : Event(&mainEventQueue), - cpu(_cpu) -{ -} - -template -void -OzoneCPU::ICacheCompletionEvent::process() -{ - cpu->processICacheCompletion(); -} - -template -const char * -OzoneCPU::ICacheCompletionEvent::description() -{ - return "OzoneCPU I-cache completion event"; -} - -template -OzoneCPU::DCacheCompletionEvent:: -DCacheCompletionEvent(OzoneCPU *_cpu, - DynInstPtr &_inst, - DCacheCompEventIt &_dcceIt) - : Event(&mainEventQueue), - cpu(_cpu), - inst(_inst), - dcceIt(_dcceIt) -{ - this->setFlags(Event::AutoDelete); -} - -template -void -OzoneCPU::DCacheCompletionEvent::process() -{ - inst->setCompleted(); - - // Maybe remove the EA from the list of addrs? - cpu->eaList.clearAddr(inst->seqNum, inst->getEA()); - cpu->dCacheCompList.erase(this->dcceIt); -} -template -const char * -OzoneCPU::DCacheCompletionEvent::description() -{ - return "OzoneCPU D-cache completion event"; -} -*/ template OzoneCPU::OzoneCPU(Params *p) #if FULL_SYSTEM - : BaseCPU(p), thread(this, 0, p->mem), tickEvent(this, p->width), mem(p->mem), + : BaseCPU(p), thread(this, 0, p->mem), tickEvent(this, p->width), + mem(p->mem), #else : BaseCPU(p), thread(this, 0, p->workload[0], 0), tickEvent(this, p->width), mem(p->workload[0]->getMemory()), #endif comm(5, 5) { - if (p->checker) { - BaseCPU *temp_checker = p->checker; - checker = dynamic_cast *>(temp_checker); - } else { - checker = NULL; - } frontEnd = new FrontEnd(p); backEnd = new BackEnd(p); _status = Idle; - if (checker) { + + if (p->checker) { + BaseCPU *temp_checker = p->checker; + checker = dynamic_cast *>(temp_checker); checker->setMemory(mem); #if FULL_SYSTEM checker->setSystem(p->system); @@ -176,19 +122,18 @@ OzoneCPU::OzoneCPU(Params *p) thread.xcProxy = checkerXC; xcProxy = checkerXC; } else { + checker = NULL; thread.xcProxy = &ozoneXC; xcProxy = &ozoneXC; } - thread.inSyscall = false; - ozoneXC.cpu = this; ozoneXC.thread = &thread; + thread.inSyscall = false; + thread.setStatus(ExecContext::Suspended); #if FULL_SYSTEM -// xc = new ExecContext(this, 0, p->system, p->itb, p->dtb, p->mem); - /***** All thread state stuff *****/ thread.cpu = this; thread.tid = 0; @@ -217,31 +162,15 @@ OzoneCPU::OzoneCPU(Params *p) thread.profileNode = &dummyNode; thread.profilePC = 3; #else -// xc = new ExecContext(this, /* thread_num */ 0, p->workload[0], /* asid */ 0); thread.cpu = this; thread.tid = 0; thread.process = p->workload[0]; -// thread.mem = thread.process->getMemory(); thread.asid = 0; #endif // !FULL_SYSTEM -/* - icacheInterface = p->icache_interface; - dcacheInterface = p->dcache_interface; - - cacheMemReq = new MemReq(); - cacheMemReq->xc = xc; - cacheMemReq->asid = 0; - cacheMemReq->data = new uint8_t[64]; -*/ + numInst = 0; startNumInst = 0; -/* numLoad = 0; - startNumLoad = 0; - lastIcacheStall = 0; - lastDcacheStall = 0; - issueWidth = p->issueWidth; -*/ execContexts.push_back(xcProxy); frontEnd->setCPU(this); @@ -286,47 +215,7 @@ template OzoneCPU::~OzoneCPU() { } -/* -template -void -OzoneCPU::copyFromXC() -{ - for (int i = 0; i < TheISA::TotalNumRegs; ++i) { - if (i < TheISA::NumIntRegs) { - renameTable[i]->setIntResult(xc->readIntReg(i)); - } else if (i < TheISA::NumFloatRegs) { - renameTable[i]->setDoubleResult(xc->readFloatRegDouble(i)); - } - } - - DPRINTF(OzoneCPU, "Func Exe inst is: %i\n", xc->func_exe_inst); - backEnd->funcExeInst = xc->func_exe_inst; -// PC = xc->readPC(); -// nextPC = xc->regs.npc; -} - -template -void -OzoneCPU::copyToXC() -{ - for (int i = 0; i < TheISA::TotalNumRegs; ++i) { - if (i < TheISA::NumIntRegs) { - xc->setIntReg(i, renameTable[i]->readIntResult()); - } else if (i < TheISA::NumFloatRegs) { - xc->setFloatRegDouble(i, renameTable[i]->readDoubleResult()); - } - } - - this->xc->regs.miscRegs.fpcr = this->regFile.miscRegs[tid].fpcr; - this->xc->regs.miscRegs.uniq = this->regFile.miscRegs[tid].uniq; - this->xc->regs.miscRegs.lock_flag = this->regFile.miscRegs[tid].lock_flag; - this->xc->regs.miscRegs.lock_addr = this->regFile.miscRegs[tid].lock_addr; - xc->func_exe_inst = backEnd->funcExeInst; - xc->regs.pc = PC; - xc->regs.npc = nextPC; -} -*/ template void OzoneCPU::switchOut(Sampler *_sampler) @@ -394,7 +283,6 @@ OzoneCPU::activateContext(int thread_num, int delay) { // Eventually change this in SMT. assert(thread_num == 0); -// assert(xcProxy); assert(_status == Idle); notIdleFraction++; @@ -410,8 +298,8 @@ OzoneCPU::suspendContext(int thread_num) { // Eventually change this in SMT. assert(thread_num == 0); -// assert(xcProxy); - // @todo: Figure out how to initially set the status properly so this is running. + // @todo: Figure out how to initially set the status properly so + // this is running. // assert(_status == Running); notIdleFraction--; unscheduleTickEvent(); @@ -486,14 +374,7 @@ void OzoneCPU::init() { BaseCPU::init(); -/* - copyFromXC(); - // ALso copy over PC/nextPC. This isn't normally copied in "copyFromXC()" - // so that the XC doesn't mess up the PC when returning from a syscall. - PC = xc->readPC(); - nextPC = xc->regs.npc; -*/ // Mark this as in syscall so it won't need to squash thread.inSyscall = true; #if FULL_SYSTEM @@ -514,8 +395,6 @@ template void OzoneCPU::serialize(std::ostream &os) { - // At this point, all DCacheCompEvents should be processed. - BaseCPU::serialize(os); SERIALIZE_ENUM(_status); nameOut(os, csprintf("%s.xc", name())); @@ -631,31 +510,7 @@ OzoneCPU::dbg_vtophys(Addr addr) return vtophys(xcProxy, addr); } #endif // FULL_SYSTEM -/* -template -void -OzoneCPU::processICacheCompletion() -{ - switch (status()) { - case IcacheMiss: - DPRINTF(OzoneCPU, "OzoneCPU: Finished Icache miss.\n"); - - icacheStallCycles += curTick - lastIcacheStall; - _status = IcacheMissComplete; - cacheBlkValid = true; -// scheduleTickEvent(1); - break; - case SwitchedOut: - // If this CPU has been switched out due to sampling/warm-up, - // ignore any further status changes (e.g., due to cache - // misses outstanding at the time of the switch). - return; - default: - panic("OzoneCPU::processICacheCompletion: bad state"); - break; - } -} -*/ + #if FULL_SYSTEM template void @@ -663,7 +518,6 @@ OzoneCPU::post_interrupt(int int_num, int index) { BaseCPU::post_interrupt(int_num, index); -// if (thread._status == ExecContext::Suspended) { if (_status == Idle) { DPRINTF(IPI,"Suspended Processor awoke\n"); // thread.activate(); @@ -690,9 +544,6 @@ OzoneCPU::tick() frontEnd->tick(); backEnd->tick(); - // Do this here? For now the front end will control the PC. -// PC = nextPC; - // check for instruction-count-based events comInstEventQueue[0]->serviceEvents(numInst); @@ -742,11 +593,13 @@ OzoneCPU::setSyscallReturn(SyscallReturn return_value, int tid) if (return_value.successful()) { // no error thread.renameTable[SyscallSuccessReg]->setIntResult(0); - thread.renameTable[ReturnValueReg]->setIntResult(return_value.value()); + thread.renameTable[ReturnValueReg]->setIntResult( + return_value.value()); } else { // got an error, return details thread.renameTable[SyscallSuccessReg]->setIntResult((IntReg) -1); - thread.renameTable[ReturnValueReg]->setIntResult(-return_value.value()); + thread.renameTable[ReturnValueReg]->setIntResult( + -return_value.value()); } } #else @@ -756,15 +609,10 @@ OzoneCPU::hwrei() { // Need to move this to ISA code // May also need to make this per thread -/* - if (!inPalMode()) - return new UnimplementedOpcodeFault; - thread.setNextPC(thread.readMiscReg(AlphaISA::IPR_EXC_ADDR)); -*/ lockFlag = false; lockAddrList.clear(); - kernelStats->hwrei(); + thread.kernelStats->hwrei(); checkInterrupts = true; @@ -835,7 +683,7 @@ OzoneCPU::simPalCheck(int palFunc) { // Need to move this to ISA code // May also need to make this per thread - this->kernelStats->callpal(palFunc, xcProxy); + thread.kernelStats->callpal(palFunc, xcProxy); switch (palFunc) { case PAL::halt: @@ -874,7 +722,6 @@ template void OzoneCPU::OzoneXC::setStatus(Status new_status) { -// cpu->_status = new_status; thread->_status = new_status; } @@ -932,6 +779,7 @@ OzoneCPU::OzoneXC::takeOverFrom(ExecContext *old_context) setStatus(old_context->status()); copyArchRegs(old_context); setCpuId(old_context->readCpuId()); + #if !FULL_SYSTEM setFuncExeInst(old_context->readFuncExeInst()); #else @@ -944,6 +792,8 @@ OzoneCPU::OzoneXC::takeOverFrom(ExecContext *old_context) if (thread->quiesceEvent) { thread->quiesceEvent->xc = this; } + + thread->kernelStats = old_context->getKernelStats(); // storeCondFailures = 0; cpu->lockFlag = false; #endif @@ -954,7 +804,12 @@ OzoneCPU::OzoneXC::takeOverFrom(ExecContext *old_context) template void OzoneCPU::OzoneXC::regStats(const std::string &name) -{ } +{ +#if FULL_SYSTEM + thread->kernelStats = new Kernel::Statistics(cpu->system); + thread->kernelStats->regStats(name + ".kern"); +#endif +} template void diff --git a/cpu/simple/cpu.cc b/cpu/simple/cpu.cc index 07f9d0dad..c03945ffa 100644 --- a/cpu/simple/cpu.cc +++ b/cpu/simple/cpu.cc @@ -782,7 +782,7 @@ SimpleCPU::tick() #if FULL_SYSTEM if (system->kernelBinning->fnbin) { - assert(kernelStats); + assert(cpuXC->getKernelStats()); system->kernelBinning->execute(xcProxy, inst); } diff --git a/cpu/thread_state.hh b/cpu/thread_state.hh index e8381b9d3..e09cb12fd 100644 --- a/cpu/thread_state.hh +++ b/cpu/thread_state.hh @@ -1,3 +1,30 @@ +/* + * Copyright (c) 2006 The Regents of The University of Michigan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ #ifndef __CPU_THREAD_STATE_HH__ #define __CPU_THREAD_STATE_HH__ @@ -8,11 +35,20 @@ class EndQuiesceEvent; class FunctionProfile; class ProfileNode; +namespace Kernel { + class Statistics; +}; #else -class Process; class FunctionalMemory; +class Process; #endif +/** + * Struct for holding general thread state that is needed across CPU + * models. This includes things such as pointers to the process, + * memory, quiesce events, and certain stats. This can be expanded + * to hold more thread-specific stats within it. + */ struct ThreadState { #if FULL_SYSTEM ThreadState(int _cpuId, int _tid, FunctionalMemory *_mem) @@ -55,6 +91,7 @@ struct ThreadState { EndQuiesceEvent *quiesceEvent; + Kernel::Statistics *kernelStats; #else Process *process; diff --git a/kern/system_events.cc b/kern/system_events.cc index 9b9861497..221eb228d 100644 --- a/kern/system_events.cc +++ b/kern/system_events.cc @@ -67,15 +67,17 @@ FnEvent::process(ExecContext *xc) void IdleStartEvent::process(ExecContext *xc) { - xc->getCpuPtr()->kernelStats->setIdleProcess( - xc->readMiscReg(AlphaISA::IPR_PALtemp23), xc); + if (xc->getKernelStats()) + xc->getKernelStats()->setIdleProcess( + xc->readMiscReg(AlphaISA::IPR_PALtemp23), xc); remove(); } void InterruptStartEvent::process(ExecContext *xc) { - xc->getCpuPtr()->kernelStats->mode(Kernel::interrupt, xc); + if (xc->getKernelStats()) + xc->getKernelStats()->mode(Kernel::interrupt, xc); } void @@ -83,5 +85,6 @@ InterruptEndEvent::process(ExecContext *xc) { // We go back to kernel, if we are user, inside the rti // pal code we will get switched to user because of the ICM write - xc->getCpuPtr()->kernelStats->mode(Kernel::kernel, xc); + if (xc->getKernelStats()) + xc->getKernelStats()->mode(Kernel::kernel, xc); } diff --git a/sim/pseudo_inst.cc b/sim/pseudo_inst.cc index 4d9541b58..0c20a6a53 100644 --- a/sim/pseudo_inst.cc +++ b/sim/pseudo_inst.cc @@ -65,7 +65,8 @@ namespace AlphaPseudo void arm(ExecContext *xc) { - xc->getCpuPtr()->kernelStats->arm(); + if (xc->getKernelStats()) + xc->getKernelStats()->arm(); } void @@ -75,7 +76,8 @@ namespace AlphaPseudo return; xc->suspend(); - xc->getCpuPtr()->kernelStats->quiesce(); + if (xc->getKernelStats()) + xc->getKernelStats()->arm(); } void @@ -92,7 +94,8 @@ namespace AlphaPseudo quiesceEvent->schedule(curTick + Clock::Int::ns * ns); xc->suspend(); - xc->getCpuPtr()->kernelStats->quiesce(); + if (xc->getKernelStats()) + xc->getKernelStats()->quiesce(); } void @@ -111,7 +114,8 @@ namespace AlphaPseudo xc->getCpuPtr()->cycles(cycles)); xc->suspend(); - xc->getCpuPtr()->kernelStats->quiesce(); + if (xc->getKernelStats()) + xc->getKernelStats()->quiesce(); } uint64_t @@ -123,7 +127,8 @@ namespace AlphaPseudo void ivlb(ExecContext *xc) { - xc->getCpuPtr()->kernelStats->ivlb(); + if (xc->getKernelStats()) + xc->getKernelStats()->ivlb(); } void -- 2.30.2