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')
#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;
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);
// 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);
}
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]);
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;
resPool->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()
{
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)
{
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)
{
// Clear Non-Speculative Block Variable
nonSpecInstActive[tid] = false;
}
+#endif
void
InOrderCPU::prefetch(DynInstPtr inst)
#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"
/** 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
*/
ActivityRecorder activityRec;
public:
- void readFunctional(Addr addr, uint32_t &buffer);
-
/** Number of Active Threads in the CPU */
ThreadID numActiveThreads() { return activeThreads.size(); }
/** 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();
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];
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;
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)
#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"
#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
// Forward declaration.
class StaticInstPtr;
class ResourceRequest;
+class Packet;
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);
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;
}
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
;
}
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
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(); }
* 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; }
--- /dev/null
+/*
+ * 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
+
#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
*/
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;