diff options
-rw-r--r-- | src/cpu/inorder/SConscript | 1 | ||||
-rw-r--r-- | src/cpu/inorder/cpu.cc | 105 | ||||
-rw-r--r-- | src/cpu/inorder/cpu.hh | 41 | ||||
-rw-r--r-- | src/cpu/inorder/inorder_cpu_builder.cc | 5 | ||||
-rw-r--r-- | src/cpu/inorder/inorder_dyn_inst.cc | 28 | ||||
-rw-r--r-- | src/cpu/inorder/inorder_dyn_inst.hh | 16 | ||||
-rw-r--r-- | src/cpu/inorder/thread_context.cc | 69 | ||||
-rw-r--r-- | src/cpu/inorder/thread_context.hh | 40 | ||||
-rw-r--r-- | src/cpu/inorder/thread_state.cc | 47 | ||||
-rw-r--r-- | src/cpu/inorder/thread_state.hh | 26 |
10 files changed, 354 insertions, 24 deletions
diff --git a/src/cpu/inorder/SConscript b/src/cpu/inorder/SConscript index 64f1b5481..82a1028c2 100644 --- a/src/cpu/inorder/SConscript +++ b/src/cpu/inorder/SConscript @@ -79,6 +79,7 @@ if 'InOrderCPU' in env['CPU_MODELS']: Source('resources/mult_div_unit.cc') Source('resource_pool.cc') Source('reg_dep_map.cc') + Source('thread_state.cc') Source('thread_context.cc') Source('cpu.cc') diff --git a/src/cpu/inorder/cpu.cc b/src/cpu/inorder/cpu.cc index a2367db63..4107ac3b4 100644 --- a/src/cpu/inorder/cpu.cc +++ b/src/cpu/inorder/cpu.cc @@ -51,6 +51,15 @@ #include "sim/process.hh" #include "sim/stat_control.hh" +#if FULL_SYSTEM +#include "cpu/quiesce_event.hh" +#include "sim/system.hh" +#endif + +#if THE_ISA == ALPHA_ISA +#include "arch/alpha/osfpal.hh" +#endif + using namespace std; using namespace TheISA; using namespace ThePipeline; @@ -171,11 +180,16 @@ InOrderCPU::InOrderCPU(Params *params) timeBuffer(2 , 2), removeInstsThisCycle(false), activityRec(params->name, NumStages, 10, params->activity), +#if FULL_SYSTEM + system(params->system), + physmem(system->physmem), +#endif // FULL_SYSTEM switchCount(0), deferRegistration(false/*params->deferRegistration*/), stageTracing(params->stageTracing), numVirtProcs(1) { + ThreadID active_threads; cpu_params = params; resPool = new ResourcePool(this, params); @@ -183,13 +197,17 @@ InOrderCPU::InOrderCPU(Params *params) // Resize for Multithreading CPUs thread.resize(numThreads); - ThreadID active_threads = params->workload.size(); +#if FULL_SYSTEM + active_threads = 1; +#else + active_threads = params->workload.size(); if (active_threads > MaxThreads) { panic("Workload Size too large. Increase the 'MaxThreads'" "in your InOrder implementation or " "edit your workload size."); } +#endif // Bind the fetch & data ports from the resource pool. fetchPortIdx = resPool->getPortIdx(params->fetchMemPort); @@ -203,6 +221,11 @@ InOrderCPU::InOrderCPU(Params *params) } for (ThreadID tid = 0; tid < numThreads; ++tid) { +#if FULL_SYSTEM + // SMT is not supported in FS mode yet. + assert(this->numThreads == 1); + this->thread[tid] = new Thread(this, 0); +#else if (tid < (ThreadID)params->workload.size()) { DPRINTF(InOrderCPU, "Workload[%i] process is %#x\n", tid, this->thread[tid]); @@ -214,6 +237,7 @@ InOrderCPU::InOrderCPU(Params *params) Process* dummy_proc = params->workload[0]; this->thread[tid] = new Thread(this, tid, dummy_proc); } +#endif // Setup the TC that will serve as the interface to the threads/CPU. InOrderThreadContext *tc = new InOrderThreadContext; @@ -447,13 +471,6 @@ InOrderCPU::init() } void -InOrderCPU::readFunctional(Addr addr, uint32_t &buffer) -{ - tcBase()->getMemPort()->readBlob(addr, (uint8_t*)&buffer, sizeof(uint32_t)); - buffer = gtoh(buffer); -} - -void InOrderCPU::reset() { for (int i = 0; i < numThreads; i++) { @@ -468,6 +485,61 @@ InOrderCPU::getPort(const std::string &if_name, int idx) return resPool->getPort(if_name, idx); } +#if FULL_SYSTEM +Fault +InOrderCPU::hwrei(ThreadID tid) +{ + panic("hwrei: Unimplemented"); + + return NoFault; +} + + +bool +InOrderCPU::simPalCheck(int palFunc, ThreadID tid) +{ + panic("simPalCheck: Unimplemented"); + + return true; +} + + +Fault +InOrderCPU::getInterrupts() +{ + // Check if there are any outstanding interrupts + return this->interrupts->getInterrupt(this->threadContexts[0]); +} + + +void +InOrderCPU::processInterrupts(Fault interrupt) +{ + // Check for interrupts here. For now can copy the code that + // exists within isa_fullsys_traits.hh. Also assume that thread 0 + // is the one that handles the interrupts. + // @todo: Possibly consolidate the interrupt checking code. + // @todo: Allow other threads to handle interrupts. + + assert(interrupt != NoFault); + this->interrupts->updateIntrInfo(this->threadContexts[0]); + + DPRINTF(InOrderCPU, "Interrupt %s being handled\n", interrupt->name()); + this->trap(interrupt, 0); +} + + +void +InOrderCPU::updateMemPorts() +{ + // Update all ThreadContext's memory ports (Functional/Virtual + // Ports) + ThreadID size = thread.size(); + for (ThreadID i = 0; i < size; ++i) + thread[i]->connectMemPorts(thread[i]->getTC()); +} +#endif + void InOrderCPU::trap(Fault fault, ThreadID tid, int delay) { @@ -1230,6 +1302,22 @@ InOrderCPU::wakeCPU() mainEventQueue.schedule(&tickEvent, curTick); } +#if FULL_SYSTEM + +void +InOrderCPU::wakeup() +{ + if (this->thread[0]->status() != ThreadContext::Suspended) + return; + + this->wakeCPU(); + + DPRINTF(Quiesce, "Suspended Processor woken\n"); + this->threadContexts[0]->activate(); +} +#endif + +#if !FULL_SYSTEM void InOrderCPU::syscall(int64_t callnum, ThreadID tid) { @@ -1251,6 +1339,7 @@ InOrderCPU::syscall(int64_t callnum, ThreadID tid) // Clear Non-Speculative Block Variable nonSpecInstActive[tid] = false; } +#endif void InOrderCPU::prefetch(DynInstPtr inst) diff --git a/src/cpu/inorder/cpu.hh b/src/cpu/inorder/cpu.hh index 75d77c818..9fb8e0df4 100644 --- a/src/cpu/inorder/cpu.hh +++ b/src/cpu/inorder/cpu.hh @@ -40,6 +40,7 @@ #include "arch/isa_traits.hh" #include "arch/types.hh" +#include "arch/registers.hh" #include "base/statistics.hh" #include "base/timebuf.hh" #include "base/types.hh" @@ -297,6 +298,32 @@ class InOrderCPU : public BaseCPU /** Get a Memory Port */ Port* getPort(const std::string &if_name, int idx = 0); +#if FULL_SYSTEM + /** HW return from error interrupt. */ + Fault hwrei(ThreadID tid); + + bool simPalCheck(int palFunc, ThreadID tid); + + /** Returns the Fault for any valid interrupt. */ + Fault getInterrupts(); + + /** Processes any an interrupt fault. */ + void processInterrupts(Fault interrupt); + + /** Halts the CPU. */ + void halt() { panic("Halt not implemented!\n"); } + + /** Update the Virt and Phys ports of all ThreadContexts to + * reflect change in memory connections. */ + void updateMemPorts(); + + /** Check if this address is a valid instruction address. */ + bool validInstAddr(Addr addr) { return true; } + + /** Check if this address is a valid data address. */ + bool validDataAddr(Addr addr) { return true; } +#endif + /** trap() - sets up a trap event on the cpuTraps to handle given fault. * trapCPU() - Traps to handle given fault */ @@ -578,8 +605,6 @@ class InOrderCPU : public BaseCPU ActivityRecorder activityRec; public: - void readFunctional(Addr addr, uint32_t &buffer); - /** Number of Active Threads in the CPU */ ThreadID numActiveThreads() { return activeThreads.size(); } @@ -597,6 +622,10 @@ class InOrderCPU : public BaseCPU /** Wakes the CPU, rescheduling the CPU if it's not already active. */ void wakeCPU(); +#if FULL_SYSTEM + virtual void wakeup(); +#endif + /** Gets a free thread id. Use if thread ids change across system. */ ThreadID getFreeTid(); @@ -622,6 +651,14 @@ class InOrderCPU : public BaseCPU return total; } +#if FULL_SYSTEM + /** Pointer to the system. */ + System *system; + + /** Pointer to physical memory. */ + PhysicalMemory *physmem; +#endif + /** The global sequence number counter. */ InstSeqNum globalSeqNum[ThePipeline::MaxThreads]; diff --git a/src/cpu/inorder/inorder_cpu_builder.cc b/src/cpu/inorder/inorder_cpu_builder.cc index 5ee7b31db..a19137dd8 100644 --- a/src/cpu/inorder/inorder_cpu_builder.cc +++ b/src/cpu/inorder/inorder_cpu_builder.cc @@ -42,12 +42,17 @@ InOrderCPU * InOrderCPUParams::create() { +#if FULL_SYSTEM + // Full-system only supports a single thread for the moment. + ThreadID actual_num_threads = 1; +#else ThreadID actual_num_threads = (numThreads >= workload.size()) ? numThreads : workload.size(); if (workload.size() == 0) { fatal("Must specify at least one workload!"); } +#endif numThreads = actual_num_threads; diff --git a/src/cpu/inorder/inorder_dyn_inst.cc b/src/cpu/inorder/inorder_dyn_inst.cc index a6abb28b2..9f0927b2f 100644 --- a/src/cpu/inorder/inorder_dyn_inst.cc +++ b/src/cpu/inorder/inorder_dyn_inst.cc @@ -297,11 +297,39 @@ InOrderDynInst::memAccess() return initiateAcc(); } + +#if FULL_SYSTEM + +Fault +InOrderDynInst::hwrei() +{ + panic("InOrderDynInst: hwrei: unimplemented\n"); + return NoFault; +} + + +void +InOrderDynInst::trap(Fault fault) +{ + this->cpu->trap(fault, this->threadNumber); +} + + +bool +InOrderDynInst::simPalCheck(int palFunc) +{ +#if THE_ISA != ALPHA_ISA + panic("simPalCheck called, but PAL only exists in Alpha!\n"); +#endif + return this->cpu->simPalCheck(palFunc, this->threadNumber); +} +#else void InOrderDynInst::syscall(int64_t callnum) { cpu->syscall(callnum, this->threadNumber); } +#endif void InOrderDynInst::prefetch(Addr addr, unsigned flags) diff --git a/src/cpu/inorder/inorder_dyn_inst.hh b/src/cpu/inorder/inorder_dyn_inst.hh index e95a6d039..a91c6a763 100644 --- a/src/cpu/inorder/inorder_dyn_inst.hh +++ b/src/cpu/inorder/inorder_dyn_inst.hh @@ -43,6 +43,7 @@ #include "arch/mt.hh" #include "base/fast_alloc.hh" #include "base/trace.hh" +#include "base/types.hh" #include "cpu/inorder/inorder_trace.hh" #include "config/full_system.hh" #include "cpu/thread_context.hh" @@ -55,6 +56,11 @@ #include "cpu/inorder/pipeline_traits.hh" #include "mem/packet.hh" #include "sim/system.hh" +#include "sim/faults.hh" + +#if THE_ISA==ALPHA_ISA +#include "arch/alpha/ev5.hh" +#endif /** * @file @@ -64,6 +70,7 @@ // Forward declaration. class StaticInstPtr; class ResourceRequest; +class Packet; class InOrderDynInst : public FastAlloc, public RefCounted { @@ -486,7 +493,16 @@ class InOrderDynInst : public FastAlloc, public RefCounted void setCurResSlot(unsigned slot_num) { curResSlot = slot_num; } /** Calls a syscall. */ +#if FULL_SYSTEM + /** Calls hardware return from error interrupt. */ + Fault hwrei(); + /** Traps to handle specified fault. */ + void trap(Fault fault); + bool simPalCheck(int palFunc); +#else + /** Calls a syscall. */ void syscall(int64_t callnum); +#endif void prefetch(Addr addr, unsigned flags); void writeHint(Addr addr, int size, unsigned flags); Fault copySrcTranslate(Addr src); diff --git a/src/cpu/inorder/thread_context.cc b/src/cpu/inorder/thread_context.cc index fe1a0faa1..8247bf1fb 100644 --- a/src/cpu/inorder/thread_context.cc +++ b/src/cpu/inorder/thread_context.cc @@ -35,18 +35,71 @@ using namespace TheISA; +#if FULL_SYSTEM + +VirtualPort * +InOrderThreadContext::getVirtPort() +{ + return thread->getVirtPort(); +} + + +void +InOrderThreadContext::dumpFuncProfile() +{ + thread->dumpFuncProfile(); +} + + +Tick +InOrderThreadContext::readLastActivate() +{ + return thread->lastActivate; +} + + +Tick +InOrderThreadContext::readLastSuspend() +{ + return thread->lastSuspend; +} + + +void +InOrderThreadContext::profileClear() +{ + thread->profileClear(); +} + + +void +InOrderThreadContext::profileSample() +{ + thread->profileSample(); +} +#endif + void InOrderThreadContext::takeOverFrom(ThreadContext *old_context) { // some things should already be set up + assert(getSystemPtr() == old_context->getSystemPtr()); +#if !FULL_SYSTEM assert(getProcessPtr() == old_context->getProcessPtr()); +#endif + + // copy over functional state setStatus(old_context->status()); copyArchRegs(old_context); +#if !FULL_SYSTEM thread->funcExeInst = old_context->readFuncExeInst(); +#endif + old_context->setStatus(ThreadContext::Halted); + thread->inSyscall = false; thread->trapPending = false; } @@ -97,8 +150,8 @@ void InOrderThreadContext::regStats(const std::string &name) { #if FULL_SYSTEM - thread->kernelStats = new Kernel::Statistics(cpu->system); - thread->kernelStats->regStats(name + ".kern"); + //thread->kernelStats = new Kernel::Statistics(cpu->system); + //thread->kernelStats->regStats(name + ".kern"); #endif ; } @@ -107,22 +160,14 @@ InOrderThreadContext::regStats(const std::string &name) void InOrderThreadContext::serialize(std::ostream &os) { -#if FULL_SYSTEM - if (thread->kernelStats) - thread->kernelStats->serialize(os); -#endif - ; + panic("serialize unimplemented"); } void InOrderThreadContext::unserialize(Checkpoint *cp, const std::string §ion) { -#if FULL_SYSTEM - if (thread->kernelStats) - thread->kernelStats->unserialize(cp, section); -#endif - ; + panic("unserialize unimplemented"); } TheISA::MachInst diff --git a/src/cpu/inorder/thread_context.hh b/src/cpu/inorder/thread_context.hh index 327f8ac71..2489c525f 100644 --- a/src/cpu/inorder/thread_context.hh +++ b/src/cpu/inorder/thread_context.hh @@ -101,10 +101,48 @@ class InOrderThreadContext : public ThreadContext virtual void setNextMicroPC(uint64_t val) { }; +#if FULL_SYSTEM + /** Returns a pointer to physical memory. */ + virtual PhysicalMemory *getPhysMemPtr() + { assert(0); return 0; /*return cpu->physmem;*/ } + + /** Returns a pointer to this thread's kernel statistics. */ + virtual TheISA::Kernel::Statistics *getKernelStats() + { return thread->kernelStats; } + + virtual FunctionalPort *getPhysPort() { return thread->getPhysPort(); } + + virtual VirtualPort *getVirtPort(); + + virtual void connectMemPorts(ThreadContext *tc) { thread->connectMemPorts(tc); } + + /** Dumps the function profiling information. + * @todo: Implement. + */ + virtual void dumpFuncProfile(); + + /** Reads the last tick that this thread was activated on. */ + virtual Tick readLastActivate(); + /** Reads the last tick that this thread was suspended on. */ + virtual Tick readLastSuspend(); + + /** Clears the function profiling information. */ + virtual void profileClear(); + + /** Samples the function profiling information. */ + virtual void profileSample(); + + /** Returns pointer to the quiesce event. */ + virtual EndQuiesceEvent *getQuiesceEvent() + { + return this->thread->quiesceEvent; + } +#else virtual TranslatingPort *getMemPort() { return thread->getMemPort(); } /** Returns a pointer to this thread's process. */ virtual Process *getProcessPtr() { return thread->getProcessPtr(); } +#endif /** Returns this thread's status. */ virtual Status status() const { return thread->status(); } @@ -232,9 +270,11 @@ class InOrderThreadContext : public ThreadContext * misspeculating, this is set as false. */ virtual bool misspeculating() { return false; } +#if !FULL_SYSTEM /** Executes a syscall in SE mode. */ virtual void syscall(int64_t callnum) { return cpu->syscall(callnum, thread->readTid()); } +#endif /** Reads the funcExeInst counter. */ virtual Counter readFuncExeInst() { return thread->funcExeInst; } diff --git a/src/cpu/inorder/thread_state.cc b/src/cpu/inorder/thread_state.cc new file mode 100644 index 000000000..b3a54efb1 --- /dev/null +++ b/src/cpu/inorder/thread_state.cc @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2007 MIPS Technologies, Inc. + * 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. + * + * Authors: Korey Sewell + * + */ + +#include "arch/isa_traits.hh" +#include "cpu/exetrace.hh" +#include "cpu/inorder/thread_state.hh" +#include "cpu/inorder/cpu.hh" + +using namespace TheISA; + +#if FULL_SYSTEM +void +InOrderThreadState::dumpFuncProfile() +{ + std::ostream *os = simout.create(csprintf("profile.%s.dat", cpu->name())); + profile->dump(tc, *os); +} +#endif + diff --git a/src/cpu/inorder/thread_state.hh b/src/cpu/inorder/thread_state.hh index 9b3b39fcb..0571b6e04 100644 --- a/src/cpu/inorder/thread_state.hh +++ b/src/cpu/inorder/thread_state.hh @@ -33,13 +33,23 @@ #include "arch/faults.hh" #include "arch/isa_traits.hh" +#include "base/callback.hh" +#include "base/output.hh" #include "cpu/thread_context.hh" #include "cpu/thread_state.hh" +#include "sim/sim_exit.hh" class Event; +class InOrderCPU; + +#if FULL_SYSTEM +class EndQuiesceEvent; +class FunctionProfile; +class ProfileNode; +#else class FunctionalMemory; class Process; -class InOrderCPU; +#endif /** * Class that has various thread state, such as the status, the @@ -66,16 +76,28 @@ class InOrderThreadState : public ThreadState { */ bool trapPending; - +#if FULL_SYSTEM + InOrderThreadState(InOrderCPU *_cpu, ThreadID _thread_num) + : ThreadState(reinterpret_cast<BaseCPU*>(_cpu), 0/*_thread_num*/), + cpu(_cpu), inSyscall(0), trapPending(0) + { } +#else InOrderThreadState(InOrderCPU *_cpu, ThreadID _thread_num, Process *_process) : ThreadState(reinterpret_cast<BaseCPU*>(_cpu), 0/*_thread_num*/, _process), cpu(_cpu), inSyscall(0), trapPending(0) { } +#endif +#if !FULL_SYSTEM /** Handles the syscall. */ void syscall(int64_t callnum) { process->syscall(callnum, tc); } +#endif + +#if FULL_SYSTEM + void dumpFuncProfile(); +#endif /** Pointer to the ThreadContext of this thread. */ ThreadContext *tc; |