O3: Generalize the O3 CPU object so it isn't split out by ISA.
This commit is contained in:
@@ -29,10 +29,9 @@
|
||||
*/
|
||||
|
||||
#include "cpu/o3/alpha/impl.hh"
|
||||
#include "cpu/o3/alpha/cpu_impl.hh"
|
||||
#include "cpu/o3/alpha/dyn_inst.hh"
|
||||
#include "cpu/o3/cpu.hh"
|
||||
|
||||
// Force instantiation of AlphaO3CPU for all the implemntations that are
|
||||
// needed. Consider merging this and alpha_dyn_inst.cc, and maybe all
|
||||
// classes that depend on a certain impl, into one file (alpha_impl.cc?).
|
||||
template class AlphaO3CPU<AlphaSimpleImpl>;
|
||||
template class FullO3CPU<AlphaSimpleImpl>;
|
||||
|
||||
@@ -1,149 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2004-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.
|
||||
*
|
||||
* Authors: Kevin Lim
|
||||
*/
|
||||
|
||||
#ifndef __CPU_O3_ALPHA_CPU_HH__
|
||||
#define __CPU_O3_ALPHA_CPU_HH__
|
||||
|
||||
#include "arch/regfile.hh"
|
||||
#include "arch/types.hh"
|
||||
#include "cpu/thread_context.hh"
|
||||
#include "cpu/o3/cpu.hh"
|
||||
#include "sim/byteswap.hh"
|
||||
|
||||
class DerivO3CPUParams;
|
||||
class EndQuiesceEvent;
|
||||
namespace Kernel {
|
||||
class Statistics;
|
||||
};
|
||||
|
||||
class TranslatingPort;
|
||||
|
||||
/**
|
||||
* AlphaO3CPU class. Derives from the FullO3CPU class, and
|
||||
* implements all ISA and implementation specific functions of the
|
||||
* CPU. This is the CPU class that is used for the SimObjects, and is
|
||||
* what is given to the DynInsts. Most of its state exists in the
|
||||
* FullO3CPU; the state is has is mainly for ISA specific
|
||||
* functionality.
|
||||
*/
|
||||
template <class Impl>
|
||||
class AlphaO3CPU : public FullO3CPU<Impl>
|
||||
{
|
||||
public:
|
||||
typedef O3ThreadState<Impl> ImplState;
|
||||
typedef O3ThreadState<Impl> Thread;
|
||||
|
||||
/** Constructs an AlphaO3CPU with the given parameters. */
|
||||
AlphaO3CPU(DerivO3CPUParams *params);
|
||||
|
||||
/** Registers statistics. */
|
||||
void regStats();
|
||||
|
||||
/** Reads a miscellaneous register. */
|
||||
TheISA::MiscReg readMiscRegNoEffect(int misc_reg, unsigned tid);
|
||||
|
||||
/** Reads a misc. register, including any side effects the read
|
||||
* might have as defined by the architecture.
|
||||
*/
|
||||
TheISA::MiscReg readMiscReg(int misc_reg, unsigned tid);
|
||||
|
||||
/** Sets a miscellaneous register. */
|
||||
void setMiscRegNoEffect(int misc_reg, const TheISA::MiscReg &val,
|
||||
unsigned tid);
|
||||
|
||||
/** Sets a misc. register, including any side effects the write
|
||||
* might have as defined by the architecture.
|
||||
*/
|
||||
void setMiscReg(int misc_reg, const TheISA::MiscReg &val,
|
||||
unsigned tid);
|
||||
|
||||
/** Initiates a squash of all in-flight instructions for a given
|
||||
* thread. The source of the squash is an external update of
|
||||
* state through the TC.
|
||||
*/
|
||||
void squashFromTC(unsigned tid);
|
||||
|
||||
#if FULL_SYSTEM
|
||||
/** Posts an interrupt. */
|
||||
void post_interrupt(int int_num, int index);
|
||||
/** HW return from error interrupt. */
|
||||
Fault hwrei(unsigned tid);
|
||||
|
||||
bool simPalCheck(int palFunc, unsigned 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"); }
|
||||
#endif
|
||||
|
||||
/** Traps to handle given fault. */
|
||||
void trap(Fault fault, unsigned tid);
|
||||
|
||||
#if !FULL_SYSTEM
|
||||
/** Executes a syscall.
|
||||
* @todo: Determine if this needs to be virtual.
|
||||
*/
|
||||
void syscall(int64_t callnum, int tid);
|
||||
/** Gets a syscall argument. */
|
||||
TheISA::IntReg getSyscallArg(int i, int tid);
|
||||
|
||||
/** Used to shift args for indirect syscall. */
|
||||
void setSyscallArg(int i, TheISA::IntReg val, int tid);
|
||||
|
||||
/** Sets the return value of a syscall. */
|
||||
void setSyscallReturn(SyscallReturn return_value, int tid);
|
||||
#endif
|
||||
|
||||
/** CPU read function, forwards read to LSQ. */
|
||||
template <class T>
|
||||
Fault read(RequestPtr &req, T &data, int load_idx)
|
||||
{
|
||||
return this->iew.ldstQueue.read(req, data, load_idx);
|
||||
}
|
||||
|
||||
/** CPU write function, forwards write to LSQ. */
|
||||
template <class T>
|
||||
Fault write(RequestPtr &req, T &data, int store_idx)
|
||||
{
|
||||
return this->iew.ldstQueue.write(req, data, store_idx);
|
||||
}
|
||||
|
||||
Addr lockAddr;
|
||||
|
||||
/** Temporary fix for the lock flag, works in the UP case. */
|
||||
bool lockFlag;
|
||||
};
|
||||
|
||||
#endif // __CPU_O3_ALPHA_CPU_HH__
|
||||
@@ -30,18 +30,17 @@
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "config/full_system.hh"
|
||||
#include "config/use_checker.hh"
|
||||
#include "cpu/base.hh"
|
||||
#include "cpu/o3/alpha/cpu.hh"
|
||||
#include "cpu/o3/cpu.hh"
|
||||
#include "cpu/o3/alpha/impl.hh"
|
||||
#include "cpu/o3/fu_pool.hh"
|
||||
#include "params/DerivO3CPU.hh"
|
||||
|
||||
class DerivO3CPU : public AlphaO3CPU<AlphaSimpleImpl>
|
||||
class DerivO3CPU : public FullO3CPU<AlphaSimpleImpl>
|
||||
{
|
||||
public:
|
||||
DerivO3CPU(DerivO3CPUParams *p)
|
||||
: AlphaO3CPU<AlphaSimpleImpl>(p)
|
||||
: FullO3CPU<AlphaSimpleImpl>(p)
|
||||
{ }
|
||||
};
|
||||
|
||||
|
||||
@@ -1,316 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2004-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.
|
||||
*
|
||||
* Authors: Kevin Lim
|
||||
*/
|
||||
|
||||
#include "config/use_checker.hh"
|
||||
|
||||
#include "arch/alpha/faults.hh"
|
||||
#include "arch/alpha/isa_traits.hh"
|
||||
#include "base/cprintf.hh"
|
||||
#include "base/statistics.hh"
|
||||
#include "base/timebuf.hh"
|
||||
#include "cpu/checker/thread_context.hh"
|
||||
#include "sim/sim_events.hh"
|
||||
#include "sim/stats.hh"
|
||||
|
||||
#include "cpu/o3/alpha/cpu.hh"
|
||||
#include "cpu/o3/alpha/thread_context.hh"
|
||||
#include "cpu/o3/comm.hh"
|
||||
#include "cpu/o3/thread_state.hh"
|
||||
|
||||
#if FULL_SYSTEM
|
||||
#include "arch/alpha/osfpal.hh"
|
||||
#include "arch/isa_traits.hh"
|
||||
#include "arch/kernel_stats.hh"
|
||||
#include "cpu/quiesce_event.hh"
|
||||
#include "sim/sim_exit.hh"
|
||||
#include "sim/system.hh"
|
||||
#endif
|
||||
|
||||
#include "params/DerivO3CPU.hh"
|
||||
|
||||
template <class Impl>
|
||||
AlphaO3CPU<Impl>::AlphaO3CPU(DerivO3CPUParams *params) :
|
||||
FullO3CPU<Impl>(this, params)
|
||||
{
|
||||
DPRINTF(O3CPU, "Creating AlphaO3CPU object.\n");
|
||||
|
||||
// Setup any thread state.
|
||||
this->thread.resize(this->numThreads);
|
||||
|
||||
for (int i = 0; i < this->numThreads; ++i) {
|
||||
#if FULL_SYSTEM
|
||||
// SMT is not supported in FS mode yet.
|
||||
assert(this->numThreads == 1);
|
||||
this->thread[i] = new Thread(this, 0);
|
||||
this->thread[i]->setStatus(ThreadContext::Suspended);
|
||||
#else
|
||||
if (i < params->workload.size()) {
|
||||
DPRINTF(O3CPU, "Workload[%i] process is %#x",
|
||||
i, this->thread[i]);
|
||||
this->thread[i] = new Thread(this, i, params->workload[i], i);
|
||||
|
||||
this->thread[i]->setStatus(ThreadContext::Suspended);
|
||||
|
||||
//usedTids[i] = true;
|
||||
//threadMap[i] = i;
|
||||
} else {
|
||||
//Allocate Empty thread so M5 can use later
|
||||
//when scheduling threads to CPU
|
||||
Process* dummy_proc = NULL;
|
||||
|
||||
this->thread[i] = new Thread(this, i, dummy_proc, i);
|
||||
//usedTids[i] = false;
|
||||
}
|
||||
#endif // !FULL_SYSTEM
|
||||
|
||||
ThreadContext *tc;
|
||||
|
||||
// Setup the TC that will serve as the interface to the threads/CPU.
|
||||
AlphaTC<Impl> *alpha_tc =
|
||||
new AlphaTC<Impl>;
|
||||
|
||||
tc = alpha_tc;
|
||||
|
||||
// If we're using a checker, then the TC should be the
|
||||
// CheckerThreadContext.
|
||||
#if USE_CHECKER
|
||||
if (params->checker) {
|
||||
tc = new CheckerThreadContext<AlphaTC<Impl> >(
|
||||
alpha_tc, this->checker);
|
||||
}
|
||||
#endif
|
||||
|
||||
alpha_tc->cpu = this;
|
||||
alpha_tc->thread = this->thread[i];
|
||||
|
||||
#if FULL_SYSTEM
|
||||
// Setup quiesce event.
|
||||
this->thread[i]->quiesceEvent = new EndQuiesceEvent(tc);
|
||||
#endif
|
||||
// Give the thread the TC.
|
||||
this->thread[i]->tc = tc;
|
||||
this->thread[i]->setCpuId(params->cpu_id);
|
||||
|
||||
// Add the TC to the CPU's list of TC's.
|
||||
this->threadContexts.push_back(tc);
|
||||
}
|
||||
|
||||
for (int i=0; i < this->numThreads; i++) {
|
||||
this->thread[i]->setFuncExeInst(0);
|
||||
}
|
||||
|
||||
lockAddr = 0;
|
||||
lockFlag = false;
|
||||
}
|
||||
|
||||
template <class Impl>
|
||||
void
|
||||
AlphaO3CPU<Impl>::regStats()
|
||||
{
|
||||
// Register stats for everything that has stats.
|
||||
this->fullCPURegStats();
|
||||
this->fetch.regStats();
|
||||
this->decode.regStats();
|
||||
this->rename.regStats();
|
||||
this->iew.regStats();
|
||||
this->commit.regStats();
|
||||
}
|
||||
|
||||
|
||||
template <class Impl>
|
||||
TheISA::MiscReg
|
||||
AlphaO3CPU<Impl>::readMiscRegNoEffect(int misc_reg, unsigned tid)
|
||||
{
|
||||
return this->regFile.readMiscRegNoEffect(misc_reg, tid);
|
||||
}
|
||||
|
||||
template <class Impl>
|
||||
TheISA::MiscReg
|
||||
AlphaO3CPU<Impl>::readMiscReg(int misc_reg, unsigned tid)
|
||||
{
|
||||
return this->regFile.readMiscReg(misc_reg, tid);
|
||||
}
|
||||
|
||||
template <class Impl>
|
||||
void
|
||||
AlphaO3CPU<Impl>::setMiscRegNoEffect(int misc_reg, const TheISA::MiscReg &val,
|
||||
unsigned tid)
|
||||
{
|
||||
this->regFile.setMiscRegNoEffect(misc_reg, val, tid);
|
||||
}
|
||||
|
||||
template <class Impl>
|
||||
void
|
||||
AlphaO3CPU<Impl>::setMiscReg(int misc_reg,
|
||||
const TheISA::MiscReg &val, unsigned tid)
|
||||
{
|
||||
this->regFile.setMiscReg(misc_reg, val, tid);
|
||||
}
|
||||
|
||||
template <class Impl>
|
||||
void
|
||||
AlphaO3CPU<Impl>::squashFromTC(unsigned tid)
|
||||
{
|
||||
this->thread[tid]->inSyscall = true;
|
||||
this->commit.generateTCEvent(tid);
|
||||
}
|
||||
|
||||
#if FULL_SYSTEM
|
||||
|
||||
template <class Impl>
|
||||
void
|
||||
AlphaO3CPU<Impl>::post_interrupt(int int_num, int index)
|
||||
{
|
||||
BaseCPU::post_interrupt(int_num, index);
|
||||
|
||||
if (this->thread[0]->status() == ThreadContext::Suspended) {
|
||||
DPRINTF(IPI,"Suspended Processor awoke\n");
|
||||
this->threadContexts[0]->activate();
|
||||
}
|
||||
}
|
||||
|
||||
template <class Impl>
|
||||
Fault
|
||||
AlphaO3CPU<Impl>::hwrei(unsigned tid)
|
||||
{
|
||||
// Need to clear the lock flag upon returning from an interrupt.
|
||||
this->setMiscRegNoEffect(AlphaISA::MISCREG_LOCKFLAG, false, tid);
|
||||
|
||||
this->thread[tid]->kernelStats->hwrei();
|
||||
|
||||
// FIXME: XXX check for interrupts? XXX
|
||||
return NoFault;
|
||||
}
|
||||
|
||||
template <class Impl>
|
||||
bool
|
||||
AlphaO3CPU<Impl>::simPalCheck(int palFunc, unsigned tid)
|
||||
{
|
||||
if (this->thread[tid]->kernelStats)
|
||||
this->thread[tid]->kernelStats->callpal(palFunc,
|
||||
this->threadContexts[tid]);
|
||||
|
||||
switch (palFunc) {
|
||||
case PAL::halt:
|
||||
halt();
|
||||
if (--System::numSystemsRunning == 0)
|
||||
exitSimLoop("all cpus halted");
|
||||
break;
|
||||
|
||||
case PAL::bpt:
|
||||
case PAL::bugchk:
|
||||
if (this->system->breakpoint())
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template <class Impl>
|
||||
Fault
|
||||
AlphaO3CPU<Impl>::getInterrupts()
|
||||
{
|
||||
// Check if there are any outstanding interrupts
|
||||
return this->interrupts.getInterrupt(this->threadContexts[0]);
|
||||
}
|
||||
|
||||
template <class Impl>
|
||||
void
|
||||
AlphaO3CPU<Impl>::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(O3CPU, "Interrupt %s being handled\n", interrupt->name());
|
||||
this->trap(interrupt, 0);
|
||||
}
|
||||
|
||||
#endif // FULL_SYSTEM
|
||||
|
||||
template <class Impl>
|
||||
void
|
||||
AlphaO3CPU<Impl>::trap(Fault fault, unsigned tid)
|
||||
{
|
||||
// Pass the thread's TC into the invoke method.
|
||||
fault->invoke(this->threadContexts[tid]);
|
||||
}
|
||||
|
||||
#if !FULL_SYSTEM
|
||||
|
||||
template <class Impl>
|
||||
void
|
||||
AlphaO3CPU<Impl>::syscall(int64_t callnum, int tid)
|
||||
{
|
||||
DPRINTF(O3CPU, "[tid:%i] Executing syscall().\n\n", tid);
|
||||
|
||||
DPRINTF(Activity,"Activity: syscall() called.\n");
|
||||
|
||||
// Temporarily increase this by one to account for the syscall
|
||||
// instruction.
|
||||
++(this->thread[tid]->funcExeInst);
|
||||
|
||||
// Execute the actual syscall.
|
||||
this->thread[tid]->syscall(callnum);
|
||||
|
||||
// Decrease funcExeInst by one as the normal commit will handle
|
||||
// incrementing it.
|
||||
--(this->thread[tid]->funcExeInst);
|
||||
}
|
||||
|
||||
template <class Impl>
|
||||
TheISA::IntReg
|
||||
AlphaO3CPU<Impl>::getSyscallArg(int i, int tid)
|
||||
{
|
||||
assert(i < TheISA::NumArgumentRegs);
|
||||
return this->readArchIntReg(AlphaISA::ArgumentReg[i], tid);
|
||||
}
|
||||
|
||||
template <class Impl>
|
||||
void
|
||||
AlphaO3CPU<Impl>::setSyscallArg(int i, TheISA::IntReg val, int tid)
|
||||
{
|
||||
assert(i < TheISA::NumArgumentRegs);
|
||||
this->setArchIntReg(AlphaISA::ArgumentReg[i], val, tid);
|
||||
}
|
||||
|
||||
template <class Impl>
|
||||
void
|
||||
AlphaO3CPU<Impl>::setSyscallReturn(SyscallReturn return_value, int tid)
|
||||
{
|
||||
TheISA::setSyscallReturn(return_value, this->tcBase(tid));
|
||||
}
|
||||
#endif
|
||||
@@ -34,8 +34,8 @@
|
||||
#include "arch/isa_traits.hh"
|
||||
#include "cpu/base_dyn_inst.hh"
|
||||
#include "cpu/inst_seq.hh"
|
||||
#include "cpu/o3/alpha/cpu.hh"
|
||||
#include "cpu/o3/alpha/impl.hh"
|
||||
#include "cpu/o3/cpu.hh"
|
||||
|
||||
class Packet;
|
||||
|
||||
|
||||
@@ -41,7 +41,7 @@ template <class Impl>
|
||||
class AlphaDynInst;
|
||||
|
||||
template <class Impl>
|
||||
class AlphaO3CPU;
|
||||
class FullO3CPU;
|
||||
|
||||
/** Implementation specific struct that defines several key types to the
|
||||
* CPU, the stages within the CPU, the time buffers, and the DynInst.
|
||||
@@ -68,7 +68,7 @@ struct AlphaSimpleImpl
|
||||
typedef RefCountingPtr<DynInst> DynInstPtr;
|
||||
|
||||
/** The O3CPU type to be used. */
|
||||
typedef AlphaO3CPU<AlphaSimpleImpl> O3CPU;
|
||||
typedef FullO3CPU<AlphaSimpleImpl> O3CPU;
|
||||
|
||||
/** Same typedef, but for CPUType. BaseDynInst may not always use
|
||||
* an O3 CPU, so it's clearer to call it CPUType instead in that
|
||||
|
||||
@@ -1,76 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2004-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.
|
||||
*
|
||||
* Authors: Kevin Lim
|
||||
*/
|
||||
|
||||
#include "arch/alpha/types.hh"
|
||||
#include "cpu/o3/thread_context.hh"
|
||||
|
||||
template <class Impl>
|
||||
class AlphaTC : public O3ThreadContext<Impl>
|
||||
{
|
||||
public:
|
||||
#if FULL_SYSTEM
|
||||
/** Returns pointer to the quiesce event. */
|
||||
virtual EndQuiesceEvent *getQuiesceEvent()
|
||||
{
|
||||
return this->thread->quiesceEvent;
|
||||
}
|
||||
#endif
|
||||
|
||||
virtual uint64_t readNextNPC()
|
||||
{
|
||||
return this->readNextPC() + sizeof(TheISA::MachInst);
|
||||
}
|
||||
|
||||
virtual void setNextNPC(uint64_t val)
|
||||
{
|
||||
panic("Alpha has no NextNPC!");
|
||||
}
|
||||
|
||||
virtual void changeRegFileContext(TheISA::RegContextParam param,
|
||||
TheISA::RegContextVal val)
|
||||
{ panic("Not supported on Alpha!"); }
|
||||
|
||||
|
||||
/** This function exits the thread context in the CPU and returns
|
||||
* 1 if the CPU has no more active threads (meaning it's OK to exit);
|
||||
* Used in syscall-emulation mode when a thread executes the 'exit'
|
||||
* syscall.
|
||||
*/
|
||||
virtual int exit()
|
||||
{
|
||||
this->deallocate();
|
||||
|
||||
// If there are still threads executing in the system
|
||||
if (this->cpu->numActiveThreads())
|
||||
return 0; // don't exit simulation
|
||||
else
|
||||
return 1; // exit simulation
|
||||
}
|
||||
};
|
||||
@@ -29,6 +29,7 @@
|
||||
*/
|
||||
|
||||
#include "cpu/base_dyn_inst_impl.hh"
|
||||
#include "cpu/o3/cpu.hh"
|
||||
#include "cpu/o3/isa_specific.hh"
|
||||
|
||||
// Explicit instantiation
|
||||
|
||||
@@ -37,6 +37,7 @@
|
||||
#include "cpu/thread_context.hh"
|
||||
#include "cpu/o3/isa_specific.hh"
|
||||
#include "cpu/o3/cpu.hh"
|
||||
#include "cpu/o3/thread_context.hh"
|
||||
#include "enums/MemoryMode.hh"
|
||||
#include "sim/core.hh"
|
||||
#include "sim/stat_control.hh"
|
||||
@@ -52,6 +53,10 @@
|
||||
#include "cpu/checker/cpu.hh"
|
||||
#endif
|
||||
|
||||
#if THE_ISA == ALPHA_ISA
|
||||
#include "arch/alpha/osfpal.hh"
|
||||
#endif
|
||||
|
||||
class BaseCPUParams;
|
||||
|
||||
using namespace TheISA;
|
||||
@@ -149,26 +154,26 @@ FullO3CPU<Impl>::DeallocateContextEvent::description() const
|
||||
}
|
||||
|
||||
template <class Impl>
|
||||
FullO3CPU<Impl>::FullO3CPU(O3CPU *o3_cpu, DerivO3CPUParams *params)
|
||||
FullO3CPU<Impl>::FullO3CPU(DerivO3CPUParams *params)
|
||||
: BaseO3CPU(params),
|
||||
itb(params->itb),
|
||||
dtb(params->dtb),
|
||||
tickEvent(this),
|
||||
removeInstsThisCycle(false),
|
||||
fetch(o3_cpu, params),
|
||||
decode(o3_cpu, params),
|
||||
rename(o3_cpu, params),
|
||||
iew(o3_cpu, params),
|
||||
commit(o3_cpu, params),
|
||||
fetch(this, params),
|
||||
decode(this, params),
|
||||
rename(this, params),
|
||||
iew(this, params),
|
||||
commit(this, params),
|
||||
|
||||
regFile(o3_cpu, params->numPhysIntRegs,
|
||||
regFile(this, params->numPhysIntRegs,
|
||||
params->numPhysFloatRegs),
|
||||
|
||||
freeList(params->numThreads,
|
||||
TheISA::NumIntRegs, params->numPhysIntRegs,
|
||||
TheISA::NumFloatRegs, params->numPhysFloatRegs),
|
||||
|
||||
rob(o3_cpu,
|
||||
rob(this,
|
||||
params->numROBEntries, params->squashWidth,
|
||||
params->smtROBPolicy, params->smtROBThreshold,
|
||||
params->numThreads),
|
||||
@@ -338,8 +343,109 @@ FullO3CPU<Impl>::FullO3CPU(O3CPU *o3_cpu, DerivO3CPUParams *params)
|
||||
//}
|
||||
|
||||
contextSwitch = false;
|
||||
DPRINTF(O3CPU, "Creating O3CPU object.\n");
|
||||
|
||||
// Setup any thread state.
|
||||
this->thread.resize(this->numThreads);
|
||||
|
||||
for (int i = 0; i < this->numThreads; ++i) {
|
||||
#if FULL_SYSTEM
|
||||
// SMT is not supported in FS mode yet.
|
||||
assert(this->numThreads == 1);
|
||||
this->thread[i] = new Thread(this, 0);
|
||||
this->thread[i]->setStatus(ThreadContext::Suspended);
|
||||
#else
|
||||
if (i < params->workload.size()) {
|
||||
DPRINTF(O3CPU, "Workload[%i] process is %#x",
|
||||
i, this->thread[i]);
|
||||
this->thread[i] = new typename FullO3CPU<Impl>::Thread(
|
||||
(typename Impl::O3CPU *)(this),
|
||||
i, params->workload[i], i);
|
||||
|
||||
this->thread[i]->setStatus(ThreadContext::Suspended);
|
||||
|
||||
//usedTids[i] = true;
|
||||
//threadMap[i] = i;
|
||||
} else {
|
||||
//Allocate Empty thread so M5 can use later
|
||||
//when scheduling threads to CPU
|
||||
Process* dummy_proc = NULL;
|
||||
|
||||
this->thread[i] = new typename FullO3CPU<Impl>::Thread(
|
||||
(typename Impl::O3CPU *)(this),
|
||||
i, dummy_proc, i);
|
||||
//usedTids[i] = false;
|
||||
}
|
||||
#endif // !FULL_SYSTEM
|
||||
|
||||
ThreadContext *tc;
|
||||
|
||||
// Setup the TC that will serve as the interface to the threads/CPU.
|
||||
O3ThreadContext<Impl> *o3_tc = new O3ThreadContext<Impl>;
|
||||
|
||||
tc = o3_tc;
|
||||
|
||||
// If we're using a checker, then the TC should be the
|
||||
// CheckerThreadContext.
|
||||
#if USE_CHECKER
|
||||
if (params->checker) {
|
||||
tc = new CheckerThreadContext<O3ThreadContext<Impl> >(
|
||||
o3_tc, this->checker);
|
||||
}
|
||||
#endif
|
||||
|
||||
o3_tc->cpu = (typename Impl::O3CPU *)(this);
|
||||
assert(o3_tc->cpu);
|
||||
o3_tc->thread = this->thread[i];
|
||||
|
||||
#if FULL_SYSTEM
|
||||
// Setup quiesce event.
|
||||
this->thread[i]->quiesceEvent = new EndQuiesceEvent(tc);
|
||||
#endif
|
||||
// Give the thread the TC.
|
||||
this->thread[i]->tc = tc;
|
||||
this->thread[i]->setCpuId(params->cpu_id);
|
||||
|
||||
// Add the TC to the CPU's list of TC's.
|
||||
this->threadContexts.push_back(tc);
|
||||
}
|
||||
|
||||
for (int i=0; i < this->numThreads; i++) {
|
||||
this->thread[i]->setFuncExeInst(0);
|
||||
}
|
||||
|
||||
lockAddr = 0;
|
||||
lockFlag = false;
|
||||
}
|
||||
|
||||
#if !FULL_SYSTEM
|
||||
|
||||
template <class Impl>
|
||||
TheISA::IntReg
|
||||
FullO3CPU<Impl>::getSyscallArg(int i, int tid)
|
||||
{
|
||||
assert(i < TheISA::NumArgumentRegs);
|
||||
TheISA::IntReg idx = TheISA::flattenIntIndex(this->tcBase(tid),
|
||||
TheISA::ArgumentReg[i]);
|
||||
TheISA::IntReg val = this->readArchIntReg(idx, tid);
|
||||
#if THE_ISA == SPARC_ISA
|
||||
if (bits(this->readMiscRegNoEffect(SparcISA::MISCREG_PSTATE, tid), 3, 3))
|
||||
val = bits(val, 31, 0);
|
||||
#endif
|
||||
return val;
|
||||
}
|
||||
|
||||
template <class Impl>
|
||||
void
|
||||
FullO3CPU<Impl>::setSyscallArg(int i, TheISA::IntReg val, int tid)
|
||||
{
|
||||
assert(i < TheISA::NumArgumentRegs);
|
||||
TheISA::IntReg idx = TheISA::flattenIntIndex(this->tcBase(tid),
|
||||
TheISA::ArgumentReg[i]);
|
||||
this->setArchIntReg(idx, val, tid);
|
||||
}
|
||||
#endif
|
||||
|
||||
template <class Impl>
|
||||
FullO3CPU<Impl>::~FullO3CPU()
|
||||
{
|
||||
@@ -347,7 +453,7 @@ FullO3CPU<Impl>::~FullO3CPU()
|
||||
|
||||
template <class Impl>
|
||||
void
|
||||
FullO3CPU<Impl>::fullCPURegStats()
|
||||
FullO3CPU<Impl>::regStats()
|
||||
{
|
||||
BaseO3CPU::regStats();
|
||||
|
||||
@@ -401,6 +507,11 @@ FullO3CPU<Impl>::fullCPURegStats()
|
||||
.precision(6);
|
||||
totalIpc = totalCommittedInsts / numCycles;
|
||||
|
||||
this->fetch.regStats();
|
||||
this->decode.regStats();
|
||||
this->rename.regStats();
|
||||
this->iew.regStats();
|
||||
this->commit.regStats();
|
||||
}
|
||||
|
||||
template <class Impl>
|
||||
@@ -783,6 +894,84 @@ FullO3CPU<Impl>::activateWhenReady(int tid)
|
||||
}
|
||||
|
||||
#if FULL_SYSTEM
|
||||
template <class Impl>
|
||||
void
|
||||
FullO3CPU<Impl>::post_interrupt(int int_num, int index)
|
||||
{
|
||||
BaseCPU::post_interrupt(int_num, index);
|
||||
|
||||
if (this->thread[0]->status() == ThreadContext::Suspended) {
|
||||
DPRINTF(IPI,"Suspended Processor awoke\n");
|
||||
this->threadContexts[0]->activate();
|
||||
}
|
||||
}
|
||||
|
||||
template <class Impl>
|
||||
Fault
|
||||
FullO3CPU<Impl>::hwrei(unsigned tid)
|
||||
{
|
||||
#if THE_ISA == ALPHA_ISA
|
||||
// Need to clear the lock flag upon returning from an interrupt.
|
||||
this->setMiscRegNoEffect(AlphaISA::MISCREG_LOCKFLAG, false, tid);
|
||||
|
||||
this->thread[tid]->kernelStats->hwrei();
|
||||
|
||||
// FIXME: XXX check for interrupts? XXX
|
||||
#endif
|
||||
return NoFault;
|
||||
}
|
||||
|
||||
template <class Impl>
|
||||
bool
|
||||
FullO3CPU<Impl>::simPalCheck(int palFunc, unsigned tid)
|
||||
{
|
||||
#if THE_ISA == ALPHA_ISA
|
||||
if (this->thread[tid]->kernelStats)
|
||||
this->thread[tid]->kernelStats->callpal(palFunc,
|
||||
this->threadContexts[tid]);
|
||||
|
||||
switch (palFunc) {
|
||||
case PAL::halt:
|
||||
halt();
|
||||
if (--System::numSystemsRunning == 0)
|
||||
exitSimLoop("all cpus halted");
|
||||
break;
|
||||
|
||||
case PAL::bpt:
|
||||
case PAL::bugchk:
|
||||
if (this->system->breakpoint())
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
template <class Impl>
|
||||
Fault
|
||||
FullO3CPU<Impl>::getInterrupts()
|
||||
{
|
||||
// Check if there are any outstanding interrupts
|
||||
return this->interrupts.getInterrupt(this->threadContexts[0]);
|
||||
}
|
||||
|
||||
template <class Impl>
|
||||
void
|
||||
FullO3CPU<Impl>::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(O3CPU, "Interrupt %s being handled\n", interrupt->name());
|
||||
this->trap(interrupt, 0);
|
||||
}
|
||||
|
||||
template <class Impl>
|
||||
void
|
||||
FullO3CPU<Impl>::updateMemPorts()
|
||||
@@ -794,6 +983,45 @@ FullO3CPU<Impl>::updateMemPorts()
|
||||
}
|
||||
#endif
|
||||
|
||||
template <class Impl>
|
||||
void
|
||||
FullO3CPU<Impl>::trap(Fault fault, unsigned tid)
|
||||
{
|
||||
// Pass the thread's TC into the invoke method.
|
||||
fault->invoke(this->threadContexts[tid]);
|
||||
}
|
||||
|
||||
#if !FULL_SYSTEM
|
||||
|
||||
template <class Impl>
|
||||
void
|
||||
FullO3CPU<Impl>::syscall(int64_t callnum, int tid)
|
||||
{
|
||||
DPRINTF(O3CPU, "[tid:%i] Executing syscall().\n\n", tid);
|
||||
|
||||
DPRINTF(Activity,"Activity: syscall() called.\n");
|
||||
|
||||
// Temporarily increase this by one to account for the syscall
|
||||
// instruction.
|
||||
++(this->thread[tid]->funcExeInst);
|
||||
|
||||
// Execute the actual syscall.
|
||||
this->thread[tid]->syscall(callnum);
|
||||
|
||||
// Decrease funcExeInst by one as the normal commit will handle
|
||||
// incrementing it.
|
||||
--(this->thread[tid]->funcExeInst);
|
||||
}
|
||||
|
||||
template <class Impl>
|
||||
void
|
||||
FullO3CPU<Impl>::setSyscallReturn(SyscallReturn return_value, int tid)
|
||||
{
|
||||
TheISA::setSyscallReturn(return_value, this->tcBase(tid));
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
template <class Impl>
|
||||
void
|
||||
FullO3CPU<Impl>::serialize(std::ostream &os)
|
||||
@@ -993,6 +1221,36 @@ FullO3CPU<Impl>::takeOverFrom(BaseCPU *oldCPU)
|
||||
tickEvent.schedule(nextCycle());
|
||||
}
|
||||
|
||||
template <class Impl>
|
||||
TheISA::MiscReg
|
||||
FullO3CPU<Impl>::readMiscRegNoEffect(int misc_reg, unsigned tid)
|
||||
{
|
||||
return this->regFile.readMiscRegNoEffect(misc_reg, tid);
|
||||
}
|
||||
|
||||
template <class Impl>
|
||||
TheISA::MiscReg
|
||||
FullO3CPU<Impl>::readMiscReg(int misc_reg, unsigned tid)
|
||||
{
|
||||
return this->regFile.readMiscReg(misc_reg, tid);
|
||||
}
|
||||
|
||||
template <class Impl>
|
||||
void
|
||||
FullO3CPU<Impl>::setMiscRegNoEffect(int misc_reg,
|
||||
const TheISA::MiscReg &val, unsigned tid)
|
||||
{
|
||||
this->regFile.setMiscRegNoEffect(misc_reg, val, tid);
|
||||
}
|
||||
|
||||
template <class Impl>
|
||||
void
|
||||
FullO3CPU<Impl>::setMiscReg(int misc_reg,
|
||||
const TheISA::MiscReg &val, unsigned tid)
|
||||
{
|
||||
this->regFile.setMiscReg(misc_reg, val, tid);
|
||||
}
|
||||
|
||||
template <class Impl>
|
||||
uint64_t
|
||||
FullO3CPU<Impl>::readIntReg(int reg_idx)
|
||||
@@ -1211,6 +1469,14 @@ FullO3CPU<Impl>::setNextMicroPC(Addr new_PC,unsigned tid)
|
||||
commit.setNextMicroPC(new_PC, tid);
|
||||
}
|
||||
|
||||
template <class Impl>
|
||||
void
|
||||
FullO3CPU<Impl>::squashFromTC(unsigned tid)
|
||||
{
|
||||
this->thread[tid]->inSyscall = true;
|
||||
this->commit.generateTCEvent(tid);
|
||||
}
|
||||
|
||||
template <class Impl>
|
||||
typename FullO3CPU<Impl>::ListIt
|
||||
FullO3CPU<Impl>::addInst(DynInstPtr &inst)
|
||||
|
||||
@@ -99,6 +99,7 @@ class FullO3CPU : public BaseO3CPU
|
||||
typedef typename Impl::DynInstPtr DynInstPtr;
|
||||
typedef typename Impl::O3CPU O3CPU;
|
||||
|
||||
typedef O3ThreadState<Impl> ImplState;
|
||||
typedef O3ThreadState<Impl> Thread;
|
||||
|
||||
typedef typename std::list<DynInstPtr>::iterator ListIt;
|
||||
@@ -201,6 +202,13 @@ class FullO3CPU : public BaseO3CPU
|
||||
activateThreadEvent[tid].squash();
|
||||
}
|
||||
|
||||
#if !FULL_SYSTEM
|
||||
TheISA::IntReg getSyscallArg(int i, int tid);
|
||||
|
||||
/** Used to shift args for indirect syscall. */
|
||||
void setSyscallArg(int i, TheISA::IntReg val, int tid);
|
||||
#endif
|
||||
|
||||
/** The tick event used for scheduling CPU ticks. */
|
||||
ActivateThreadEvent activateThreadEvent[Impl::MaxThreads];
|
||||
|
||||
@@ -257,12 +265,12 @@ class FullO3CPU : public BaseO3CPU
|
||||
|
||||
public:
|
||||
/** Constructs a CPU with the given parameters. */
|
||||
FullO3CPU(O3CPU *o3_cpu, DerivO3CPUParams *params);
|
||||
FullO3CPU(DerivO3CPUParams *params);
|
||||
/** Destructor. */
|
||||
~FullO3CPU();
|
||||
|
||||
/** Registers statistics. */
|
||||
void fullCPURegStats();
|
||||
void regStats();
|
||||
|
||||
void demapPage(Addr vaddr, uint64_t asn)
|
||||
{
|
||||
@@ -368,12 +376,16 @@ class FullO3CPU : public BaseO3CPU
|
||||
virtual void unserialize(Checkpoint *cp, const std::string §ion);
|
||||
|
||||
public:
|
||||
/** Executes a syscall on this cycle.
|
||||
* ---------------------------------------
|
||||
* Note: this is a virtual function. CPU-Specific
|
||||
* functionality defined in derived classes
|
||||
#if !FULL_SYSTEM
|
||||
/** Executes a syscall.
|
||||
* @todo: Determine if this needs to be virtual.
|
||||
*/
|
||||
virtual void syscall(int tid) { panic("Unimplemented!"); }
|
||||
void syscall(int64_t callnum, int tid);
|
||||
|
||||
/** Sets the return value of a syscall. */
|
||||
void setSyscallReturn(SyscallReturn return_value, int tid);
|
||||
|
||||
#endif
|
||||
|
||||
/** Starts draining the CPU's pipeline of all instructions in
|
||||
* order to stop all memory accesses. */
|
||||
@@ -395,7 +407,27 @@ class FullO3CPU : public BaseO3CPU
|
||||
InstSeqNum getAndIncrementInstSeq()
|
||||
{ return globalSeqNum++; }
|
||||
|
||||
/** Traps to handle given fault. */
|
||||
void trap(Fault fault, unsigned tid);
|
||||
|
||||
#if FULL_SYSTEM
|
||||
/** Posts an interrupt. */
|
||||
void post_interrupt(int int_num, int index);
|
||||
|
||||
/** HW return from error interrupt. */
|
||||
Fault hwrei(unsigned tid);
|
||||
|
||||
bool simPalCheck(int palFunc, unsigned 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();
|
||||
@@ -425,6 +457,24 @@ class FullO3CPU : public BaseO3CPU
|
||||
#endif
|
||||
|
||||
/** Register accessors. Index refers to the physical register index. */
|
||||
|
||||
/** Reads a miscellaneous register. */
|
||||
TheISA::MiscReg readMiscRegNoEffect(int misc_reg, unsigned tid);
|
||||
|
||||
/** Reads a misc. register, including any side effects the read
|
||||
* might have as defined by the architecture.
|
||||
*/
|
||||
TheISA::MiscReg readMiscReg(int misc_reg, unsigned tid);
|
||||
|
||||
/** Sets a miscellaneous register. */
|
||||
void setMiscRegNoEffect(int misc_reg, const TheISA::MiscReg &val, unsigned tid);
|
||||
|
||||
/** Sets a misc. register, including any side effects the write
|
||||
* might have as defined by the architecture.
|
||||
*/
|
||||
void setMiscReg(int misc_reg, const TheISA::MiscReg &val,
|
||||
unsigned tid);
|
||||
|
||||
uint64_t readIntReg(int reg_idx);
|
||||
|
||||
TheISA::FloatReg readFloatReg(int reg_idx);
|
||||
@@ -496,6 +546,12 @@ class FullO3CPU : public BaseO3CPU
|
||||
/** Sets the commit next micro PC of a specific thread. */
|
||||
void setNextMicroPC(Addr val, unsigned tid);
|
||||
|
||||
/** Initiates a squash of all in-flight instructions for a given
|
||||
* thread. The source of the squash is an external update of
|
||||
* state through the TC.
|
||||
*/
|
||||
void squashFromTC(unsigned tid);
|
||||
|
||||
/** Function to add instruction onto the head of the list of the
|
||||
* instructions. Used when new instructions are fetched.
|
||||
*/
|
||||
@@ -711,6 +767,25 @@ class FullO3CPU : public BaseO3CPU
|
||||
/** Available thread ids in the cpu*/
|
||||
std::vector<unsigned> tids;
|
||||
|
||||
/** CPU read function, forwards read to LSQ. */
|
||||
template <class T>
|
||||
Fault read(RequestPtr &req, T &data, int load_idx)
|
||||
{
|
||||
return this->iew.ldstQueue.read(req, data, load_idx);
|
||||
}
|
||||
|
||||
/** CPU write function, forwards write to LSQ. */
|
||||
template <class T>
|
||||
Fault write(RequestPtr &req, T &data, int store_idx)
|
||||
{
|
||||
return this->iew.ldstQueue.write(req, data, store_idx);
|
||||
}
|
||||
|
||||
Addr lockAddr;
|
||||
|
||||
/** Temporary fix for the lock flag, works in the UP case. */
|
||||
bool lockFlag;
|
||||
|
||||
/** Stat for total number of times the CPU is descheduled. */
|
||||
Stats::Scalar<> timesIdled;
|
||||
/** Stat for total number of cycles the CPU spends descheduled. */
|
||||
|
||||
@@ -31,15 +31,12 @@
|
||||
#include "cpu/base.hh"
|
||||
|
||||
#if THE_ISA == ALPHA_ISA
|
||||
#include "cpu/o3/alpha/cpu.hh"
|
||||
#include "cpu/o3/alpha/impl.hh"
|
||||
#include "cpu/o3/alpha/dyn_inst.hh"
|
||||
#elif THE_ISA == MIPS_ISA
|
||||
#include "cpu/o3/mips/cpu.hh"
|
||||
#include "cpu/o3/mips/impl.hh"
|
||||
#include "cpu/o3/mips/dyn_inst.hh"
|
||||
#elif THE_ISA == SPARC_ISA
|
||||
#include "cpu/o3/sparc/cpu.hh"
|
||||
#include "cpu/o3/sparc/impl.hh"
|
||||
#include "cpu/o3/sparc/dyn_inst.hh"
|
||||
#else
|
||||
|
||||
@@ -29,11 +29,10 @@
|
||||
* Korey Sewell
|
||||
*/
|
||||
|
||||
#include "cpu/o3/cpu.hh"
|
||||
#include "cpu/o3/mips/impl.hh"
|
||||
#include "cpu/o3/mips/cpu_impl.hh"
|
||||
#include "cpu/o3/mips/dyn_inst.hh"
|
||||
|
||||
// Force instantiation of MipsO3CPU for all the implemntations that are
|
||||
// needed. Consider merging this and mips_dyn_inst.cc, and maybe all
|
||||
// classes that depend on a certain impl, into one file (mips_impl.cc?).
|
||||
template class MipsO3CPU<MipsSimpleImpl>;
|
||||
template class FullO3CPU<MipsSimpleImpl>;
|
||||
|
||||
@@ -1,130 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* Authors: Kevin Lim
|
||||
* Korey Sewell
|
||||
*/
|
||||
|
||||
#ifndef __CPU_O3_MIPS_CPU_HH__
|
||||
#define __CPU_O3_MIPS_CPU_HH__
|
||||
|
||||
#include "arch/mips/regfile.hh"
|
||||
#include "arch/mips/syscallreturn.hh"
|
||||
#include "cpu/thread_context.hh"
|
||||
#include "cpu/o3/cpu.hh"
|
||||
#include "sim/byteswap.hh"
|
||||
#include "sim/faults.hh"
|
||||
|
||||
class DerivO3CPUParams;
|
||||
class EndQuiesceEvent;
|
||||
namespace Kernel {
|
||||
class Statistics;
|
||||
};
|
||||
|
||||
class TranslatingPort;
|
||||
|
||||
/**
|
||||
* MipsO3CPU class. Derives from the FullO3CPU class, and
|
||||
* implements all ISA and implementation specific functions of the
|
||||
* CPU. This is the CPU class that is used for the SimObjects, and is
|
||||
* what is given to the DynInsts. Most of its state exists in the
|
||||
* FullO3CPU; the state is has is mainly for ISA specific
|
||||
* functionality.
|
||||
*/
|
||||
template <class Impl>
|
||||
class MipsO3CPU : public FullO3CPU<Impl>
|
||||
{
|
||||
public:
|
||||
typedef O3ThreadState<Impl> ImplState;
|
||||
typedef O3ThreadState<Impl> Thread;
|
||||
|
||||
/** Constructs an MipsO3CPU with the given parameters. */
|
||||
MipsO3CPU(DerivO3CPUParams *params);
|
||||
|
||||
/** Registers statistics. */
|
||||
void regStats();
|
||||
|
||||
/** Reads a miscellaneous register. */
|
||||
TheISA::MiscReg readMiscRegNoEffect(int misc_reg, unsigned tid);
|
||||
|
||||
/** Reads a misc. register, including any side effects the read
|
||||
* might have as defined by the architecture.
|
||||
*/
|
||||
TheISA::MiscReg readMiscReg(int misc_reg, unsigned tid);
|
||||
|
||||
/** Sets a miscellaneous register. */
|
||||
void setMiscRegNoEffect(int misc_reg, const TheISA::MiscReg &val, unsigned tid);
|
||||
|
||||
/** Sets a misc. register, including any side effects the write
|
||||
* might have as defined by the architecture.
|
||||
*/
|
||||
void setMiscReg(int misc_reg,
|
||||
const TheISA::MiscReg &val, unsigned tid);
|
||||
|
||||
/** Initiates a squash of all in-flight instructions for a given
|
||||
* thread. The source of the squash is an external update of
|
||||
* state through the TC.
|
||||
*/
|
||||
void squashFromTC(unsigned tid);
|
||||
|
||||
/** Traps to handle given fault. */
|
||||
void trap(Fault fault, unsigned tid);
|
||||
|
||||
/** Executes a syscall.
|
||||
* @todo: Determine if this needs to be virtual.
|
||||
*/
|
||||
void syscall(int64_t callnum, int tid);
|
||||
/** Gets a syscall argument. */
|
||||
TheISA::IntReg getSyscallArg(int i, int tid);
|
||||
|
||||
/** Used to shift args for indirect syscall. */
|
||||
void setSyscallArg(int i, TheISA::IntReg val, int tid);
|
||||
|
||||
/** Sets the return value of a syscall. */
|
||||
void setSyscallReturn(SyscallReturn return_value, int tid);
|
||||
|
||||
/** CPU read function, forwards read to LSQ. */
|
||||
template <class T>
|
||||
Fault read(RequestPtr &req, T &data, int load_idx)
|
||||
{
|
||||
return this->iew.ldstQueue.read(req, data, load_idx);
|
||||
}
|
||||
|
||||
/** CPU write function, forwards write to LSQ. */
|
||||
template <class T>
|
||||
Fault write(RequestPtr &req, T &data, int store_idx)
|
||||
{
|
||||
return this->iew.ldstQueue.write(req, data, store_idx);
|
||||
}
|
||||
|
||||
Addr lockAddr;
|
||||
|
||||
/** Temporary fix for the lock flag, works in the UP case. */
|
||||
bool lockFlag;
|
||||
};
|
||||
|
||||
#endif // __CPU_O3_MIPS_CPU_HH__
|
||||
@@ -31,18 +31,17 @@
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "config/full_system.hh"
|
||||
#include "config/use_checker.hh"
|
||||
#include "cpu/base.hh"
|
||||
#include "cpu/o3/mips/cpu.hh"
|
||||
#include "cpu/o3/cpu.hh"
|
||||
#include "cpu/o3/mips/impl.hh"
|
||||
#include "cpu/o3/fu_pool.hh"
|
||||
#include "params/DerivO3CPU.hh"
|
||||
|
||||
class DerivO3CPU : public MipsO3CPU<MipsSimpleImpl>
|
||||
class DerivO3CPU : public FullO3CPU<MipsSimpleImpl>
|
||||
{
|
||||
public:
|
||||
DerivO3CPU(DerivO3CPUParams *p)
|
||||
: MipsO3CPU<MipsSimpleImpl>(p)
|
||||
: FullO3CPU<MipsSimpleImpl>(p)
|
||||
{ }
|
||||
};
|
||||
|
||||
|
||||
@@ -1,218 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* Authors: Kevin Lim
|
||||
* Korey Sewell
|
||||
*/
|
||||
|
||||
#include "config/use_checker.hh"
|
||||
|
||||
#include "arch/mips/faults.hh"
|
||||
#include "base/cprintf.hh"
|
||||
#include "base/statistics.hh"
|
||||
#include "base/timebuf.hh"
|
||||
#include "cpu/checker/thread_context.hh"
|
||||
#include "sim/sim_events.hh"
|
||||
#include "sim/stats.hh"
|
||||
|
||||
#include "cpu/o3/mips/cpu.hh"
|
||||
#include "cpu/o3/mips/thread_context.hh"
|
||||
#include "cpu/o3/comm.hh"
|
||||
#include "cpu/o3/thread_state.hh"
|
||||
|
||||
#include "params/DerivO3CPU.hh"
|
||||
|
||||
template <class Impl>
|
||||
MipsO3CPU<Impl>::MipsO3CPU(DerivO3CPUParams *params)
|
||||
: FullO3CPU<Impl>(this, params)
|
||||
{
|
||||
DPRINTF(O3CPU, "Creating MipsO3CPU object.\n");
|
||||
|
||||
// Setup any thread state.
|
||||
this->thread.resize(this->numThreads);
|
||||
|
||||
for (int i = 0; i < this->numThreads; ++i) {
|
||||
if (i < params->workload.size()) {
|
||||
DPRINTF(O3CPU, "Workload[%i] process is %#x",
|
||||
i, this->thread[i]);
|
||||
this->thread[i] = new Thread(this, i, params->workload[i], i);
|
||||
|
||||
this->thread[i]->setStatus(ThreadContext::Suspended);
|
||||
|
||||
//usedTids[i] = true;
|
||||
//threadMap[i] = i;
|
||||
} else {
|
||||
//Allocate Empty thread so M5 can use later
|
||||
//when scheduling threads to CPU
|
||||
Process* dummy_proc = NULL;
|
||||
|
||||
this->thread[i] = new Thread(this, i, dummy_proc, i);
|
||||
//usedTids[i] = false;
|
||||
}
|
||||
|
||||
ThreadContext *tc;
|
||||
|
||||
// Setup the TC that will serve as the interface to the threads/CPU.
|
||||
MipsTC<Impl> *mips_tc =
|
||||
new MipsTC<Impl>;
|
||||
|
||||
tc = mips_tc;
|
||||
|
||||
// If we're using a checker, then the TC should be the
|
||||
// CheckerThreadContext.
|
||||
#if USE_CHECKER
|
||||
if (params->checker) {
|
||||
tc = new CheckerThreadContext<MipsTC<Impl> >(
|
||||
mips_tc, this->checker);
|
||||
}
|
||||
#endif
|
||||
|
||||
mips_tc->cpu = this;
|
||||
mips_tc->thread = this->thread[i];
|
||||
|
||||
// Give the thread the TC.
|
||||
this->thread[i]->tc = tc;
|
||||
this->thread[i]->setCpuId(params->cpu_id);
|
||||
|
||||
// Add the TC to the CPU's list of TC's.
|
||||
this->threadContexts.push_back(tc);
|
||||
}
|
||||
|
||||
for (int i=0; i < this->numThreads; i++) {
|
||||
this->thread[i]->setFuncExeInst(0);
|
||||
}
|
||||
|
||||
lockAddr = 0;
|
||||
lockFlag = false;
|
||||
}
|
||||
|
||||
template <class Impl>
|
||||
void
|
||||
MipsO3CPU<Impl>::regStats()
|
||||
{
|
||||
// Register stats for everything that has stats.
|
||||
this->fullCPURegStats();
|
||||
this->fetch.regStats();
|
||||
this->decode.regStats();
|
||||
this->rename.regStats();
|
||||
this->iew.regStats();
|
||||
this->commit.regStats();
|
||||
}
|
||||
|
||||
|
||||
template <class Impl>
|
||||
MiscReg
|
||||
MipsO3CPU<Impl>::readMiscRegNoEffect(int misc_reg, unsigned tid)
|
||||
{
|
||||
return this->regFile.readMiscRegNoEffect(misc_reg, tid);
|
||||
}
|
||||
|
||||
template <class Impl>
|
||||
MiscReg
|
||||
MipsO3CPU<Impl>::readMiscReg(int misc_reg, unsigned tid)
|
||||
{
|
||||
return this->regFile.readMiscReg(misc_reg, tid);
|
||||
}
|
||||
|
||||
template <class Impl>
|
||||
void
|
||||
MipsO3CPU<Impl>::setMiscRegNoEffect(int misc_reg, const MiscReg &val, unsigned tid)
|
||||
{
|
||||
this->regFile.setMiscRegNoEffect(misc_reg, val, tid);
|
||||
}
|
||||
|
||||
template <class Impl>
|
||||
void
|
||||
MipsO3CPU<Impl>::setMiscReg(int misc_reg, const MiscReg &val,
|
||||
unsigned tid)
|
||||
{
|
||||
this->regFile.setMiscReg(misc_reg, val, tid);
|
||||
}
|
||||
|
||||
template <class Impl>
|
||||
void
|
||||
MipsO3CPU<Impl>::squashFromTC(unsigned tid)
|
||||
{
|
||||
this->thread[tid]->inSyscall = true;
|
||||
this->commit.generateTCEvent(tid);
|
||||
}
|
||||
|
||||
template <class Impl>
|
||||
void
|
||||
MipsO3CPU<Impl>::trap(Fault fault, unsigned tid)
|
||||
{
|
||||
// Pass the thread's TC into the invoke method.
|
||||
fault->invoke(this->threadContexts[tid]);
|
||||
}
|
||||
|
||||
#if !FULL_SYSTEM
|
||||
|
||||
template <class Impl>
|
||||
void
|
||||
MipsO3CPU<Impl>::syscall(int64_t callnum, int tid)
|
||||
{
|
||||
DPRINTF(O3CPU, "[tid:%i] Executing syscall().\n\n", tid);
|
||||
|
||||
DPRINTF(Activity,"Activity: syscall() called.\n");
|
||||
|
||||
// Temporarily increase this by one to account for the syscall
|
||||
// instruction.
|
||||
++(this->thread[tid]->funcExeInst);
|
||||
|
||||
// Execute the actual syscall.
|
||||
this->thread[tid]->syscall(callnum);
|
||||
|
||||
// Decrease funcExeInst by one as the normal commit will handle
|
||||
// incrementing it.
|
||||
--(this->thread[tid]->funcExeInst);
|
||||
|
||||
DPRINTF(O3CPU, "[tid:%i] Register 2 is %i ", tid, this->readIntReg(2));
|
||||
}
|
||||
|
||||
template <class Impl>
|
||||
TheISA::IntReg
|
||||
MipsO3CPU<Impl>::getSyscallArg(int i, int tid)
|
||||
{
|
||||
assert(i < TheISA::NumArgumentRegs);
|
||||
return this->readArchIntReg(MipsISA::ArgumentReg[i], tid);
|
||||
}
|
||||
|
||||
template <class Impl>
|
||||
void
|
||||
MipsO3CPU<Impl>::setSyscallArg(int i, IntReg val, int tid)
|
||||
{
|
||||
assert(i < TheISA::NumArgumentRegs);
|
||||
this->setArchIntReg(MipsISA::ArgumentReg[i], val, tid);
|
||||
}
|
||||
|
||||
template <class Impl>
|
||||
void
|
||||
MipsO3CPU<Impl>::setSyscallReturn(SyscallReturn return_value, int tid)
|
||||
{
|
||||
TheISA::setSyscallReturn(return_value, this->tcBase(tid));
|
||||
}
|
||||
#endif
|
||||
@@ -35,7 +35,7 @@
|
||||
#include "arch/isa_traits.hh"
|
||||
#include "cpu/base_dyn_inst.hh"
|
||||
#include "cpu/inst_seq.hh"
|
||||
#include "cpu/o3/mips/cpu.hh"
|
||||
#include "cpu/o3/cpu.hh"
|
||||
#include "cpu/o3/mips/impl.hh"
|
||||
|
||||
class Packet;
|
||||
|
||||
@@ -42,7 +42,7 @@ template <class Impl>
|
||||
class MipsDynInst;
|
||||
|
||||
template <class Impl>
|
||||
class MipsO3CPU;
|
||||
class FullO3CPU;
|
||||
|
||||
/** Implementation specific struct that defines several key types to the
|
||||
* CPU, the stages within the CPU, the time buffers, and the DynInst.
|
||||
@@ -69,7 +69,7 @@ struct MipsSimpleImpl
|
||||
typedef RefCountingPtr<DynInst> DynInstPtr;
|
||||
|
||||
/** The O3CPU type to be used. */
|
||||
typedef MipsO3CPU<MipsSimpleImpl> O3CPU;
|
||||
typedef FullO3CPU<MipsSimpleImpl> O3CPU;
|
||||
|
||||
/** Same typedef, but for CPUType. BaseDynInst may not always use
|
||||
* an O3 CPU, so it's clearer to call it CPUType instead in that
|
||||
|
||||
@@ -1,68 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* Authors: Kevin Lim
|
||||
* Korey Sewell
|
||||
*/
|
||||
|
||||
#include "arch/mips/types.hh"
|
||||
#include "cpu/o3/thread_context.hh"
|
||||
|
||||
template <class Impl>
|
||||
class MipsTC : public O3ThreadContext<Impl>
|
||||
{
|
||||
public:
|
||||
virtual uint64_t readNextNPC()
|
||||
{
|
||||
return this->cpu->readNextNPC(this->thread->readTid());
|
||||
}
|
||||
|
||||
virtual void setNextNPC(uint64_t val)
|
||||
{
|
||||
this->cpu->setNextNPC(val, this->thread->readTid());
|
||||
}
|
||||
|
||||
virtual void changeRegFileContext(TheISA::RegContextParam param,
|
||||
TheISA::RegContextVal val)
|
||||
{ panic("Not supported on Mips!"); }
|
||||
|
||||
/** This function exits the thread context in the CPU and returns
|
||||
* 1 if the CPU has no more active threads (meaning it's OK to exit);
|
||||
* Used in syscall-emulation mode when a thread executes the 'exit'
|
||||
* syscall.
|
||||
*/
|
||||
virtual int exit()
|
||||
{
|
||||
this->deallocate();
|
||||
|
||||
// If there are still threads executing in the system
|
||||
if (this->cpu->numActiveThreads())
|
||||
return 0; // don't exit simulation
|
||||
else
|
||||
return 1; // exit simulation
|
||||
}
|
||||
};
|
||||
@@ -28,11 +28,10 @@
|
||||
* Authors: Gabe Black
|
||||
*/
|
||||
|
||||
#include "cpu/o3/cpu.hh"
|
||||
#include "cpu/o3/sparc/impl.hh"
|
||||
#include "cpu/o3/sparc/cpu_impl.hh"
|
||||
#include "cpu/o3/sparc/dyn_inst.hh"
|
||||
|
||||
// Force instantiation of SparcO3CPU for all the implementations that are
|
||||
// needed. Consider merging this and sparc_dyn_inst.cc, and maybe all
|
||||
// classes that depend on a certain impl, into one file (sparc_impl.cc?).
|
||||
template class SparcO3CPU<SparcSimpleImpl>;
|
||||
template class FullO3CPU<SparcSimpleImpl>;
|
||||
|
||||
@@ -1,148 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2004-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.
|
||||
*
|
||||
* Authors: Kevin Lim
|
||||
*/
|
||||
|
||||
#ifndef __CPU_O3_SPARC_CPU_HH__
|
||||
#define __CPU_O3_SPARC_CPU_HH__
|
||||
|
||||
#include "arch/sparc/regfile.hh"
|
||||
#include "arch/sparc/types.hh"
|
||||
#include "cpu/thread_context.hh"
|
||||
#include "cpu/o3/cpu.hh"
|
||||
#include "sim/byteswap.hh"
|
||||
|
||||
class DerivO3CPUParams;
|
||||
class EndQuiesceEvent;
|
||||
namespace Kernel {
|
||||
class Statistics;
|
||||
};
|
||||
|
||||
class TranslatingPort;
|
||||
|
||||
/**
|
||||
* SparcO3CPU class. Derives from the FullO3CPU class, and
|
||||
* implements all ISA and implementation specific functions of the
|
||||
* CPU. This is the CPU class that is used for the SimObjects, and is
|
||||
* what is given to the DynInsts. Most of its state exists in the
|
||||
* FullO3CPU; the state is has is mainly for ISA specific
|
||||
* functionality.
|
||||
*/
|
||||
template <class Impl>
|
||||
class SparcO3CPU : public FullO3CPU<Impl>
|
||||
{
|
||||
public:
|
||||
typedef O3ThreadState<Impl> ImplState;
|
||||
typedef O3ThreadState<Impl> Thread;
|
||||
|
||||
/** Constructs an AlphaO3CPU with the given parameters. */
|
||||
SparcO3CPU(DerivO3CPUParams *params);
|
||||
|
||||
/** Registers statistics. */
|
||||
void regStats();
|
||||
|
||||
/** Reads a miscellaneous register. */
|
||||
TheISA::MiscReg readMiscRegNoEffect(int misc_reg, unsigned tid);
|
||||
|
||||
/** Reads a misc. register, including any side effects the read
|
||||
* might have as defined by the architecture.
|
||||
*/
|
||||
TheISA::MiscReg readMiscReg(int misc_reg, unsigned tid);
|
||||
|
||||
/** Sets a miscellaneous register. */
|
||||
void setMiscRegNoEffect(int misc_reg, const TheISA::MiscReg &val, unsigned tid);
|
||||
|
||||
/** Sets a misc. register, including any side effects the write
|
||||
* might have as defined by the architecture.
|
||||
*/
|
||||
void setMiscReg(int misc_reg, const TheISA::MiscReg &val,
|
||||
unsigned tid);
|
||||
|
||||
/** Initiates a squash of all in-flight instructions for a given
|
||||
* thread. The source of the squash is an external update of
|
||||
* state through the TC.
|
||||
*/
|
||||
void squashFromTC(unsigned tid);
|
||||
|
||||
#if FULL_SYSTEM
|
||||
/** Posts an interrupt. */
|
||||
void post_interrupt(int int_num, int index);
|
||||
/** HW return from error interrupt. */
|
||||
Fault hwrei(unsigned tid);
|
||||
|
||||
bool simPalCheck(int palFunc, unsigned 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"); }
|
||||
#endif
|
||||
|
||||
/** Traps to handle given fault. */
|
||||
void trap(Fault fault, unsigned tid);
|
||||
|
||||
#if !FULL_SYSTEM
|
||||
/** Executes a syscall.
|
||||
* @todo: Determine if this needs to be virtual.
|
||||
*/
|
||||
void syscall(int64_t callnum, int tid);
|
||||
/** Gets a syscall argument. */
|
||||
TheISA::IntReg getSyscallArg(int i, int tid);
|
||||
|
||||
/** Used to shift args for indirect syscall. */
|
||||
void setSyscallArg(int i, TheISA::IntReg val, int tid);
|
||||
|
||||
/** Sets the return value of a syscall. */
|
||||
void setSyscallReturn(SyscallReturn return_value, int tid);
|
||||
#endif
|
||||
|
||||
/** CPU read function, forwards read to LSQ. */
|
||||
template <class T>
|
||||
Fault read(RequestPtr &req, T &data, int load_idx)
|
||||
{
|
||||
return this->iew.ldstQueue.read(req, data, load_idx);
|
||||
}
|
||||
|
||||
/** CPU write function, forwards write to LSQ. */
|
||||
template <class T>
|
||||
Fault write(RequestPtr &req, T &data, int store_idx)
|
||||
{
|
||||
return this->iew.ldstQueue.write(req, data, store_idx);
|
||||
}
|
||||
|
||||
Addr lockAddr;
|
||||
|
||||
/** Temporary fix for the lock flag, works in the UP case. */
|
||||
bool lockFlag;
|
||||
};
|
||||
|
||||
#endif // __CPU_O3_SPARC_CPU_HH__
|
||||
@@ -32,17 +32,15 @@
|
||||
|
||||
#include "config/full_system.hh"
|
||||
#include "config/use_checker.hh"
|
||||
#include "cpu/base.hh"
|
||||
#include "cpu/o3/sparc/cpu.hh"
|
||||
#include "cpu/o3/cpu.hh"
|
||||
#include "cpu/o3/sparc/impl.hh"
|
||||
#include "cpu/o3/fu_pool.hh"
|
||||
#include "params/DerivO3CPU.hh"
|
||||
|
||||
class DerivO3CPU : public SparcO3CPU<SparcSimpleImpl>
|
||||
class DerivO3CPU : public FullO3CPU<SparcSimpleImpl>
|
||||
{
|
||||
public:
|
||||
DerivO3CPU(DerivO3CPUParams *p)
|
||||
: SparcO3CPU<SparcSimpleImpl>(p)
|
||||
: FullO3CPU<SparcSimpleImpl>(p)
|
||||
{ }
|
||||
};
|
||||
|
||||
|
||||
@@ -1,300 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2004-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.
|
||||
*
|
||||
* Authors: Gabe Black
|
||||
*/
|
||||
|
||||
#include "config/use_checker.hh"
|
||||
|
||||
#include "arch/sparc/faults.hh"
|
||||
#include "arch/sparc/isa_traits.hh"
|
||||
#include "arch/sparc/miscregfile.hh"
|
||||
#include "base/cprintf.hh"
|
||||
#include "base/statistics.hh"
|
||||
#include "base/timebuf.hh"
|
||||
#include "cpu/checker/thread_context.hh"
|
||||
#include "sim/sim_events.hh"
|
||||
#include "sim/stats.hh"
|
||||
|
||||
#include "cpu/o3/sparc/cpu.hh"
|
||||
#include "cpu/o3/sparc/thread_context.hh"
|
||||
#include "cpu/o3/comm.hh"
|
||||
#include "cpu/o3/thread_state.hh"
|
||||
|
||||
#if FULL_SYSTEM
|
||||
#include "arch/sparc/isa_traits.hh"
|
||||
#include "arch/sparc/kernel_stats.hh"
|
||||
#include "cpu/quiesce_event.hh"
|
||||
#include "sim/sim_exit.hh"
|
||||
#include "sim/system.hh"
|
||||
#endif
|
||||
|
||||
#include "params/DerivO3CPU.hh"
|
||||
|
||||
template <class Impl>
|
||||
SparcO3CPU<Impl>::SparcO3CPU(DerivO3CPUParams *params) :
|
||||
FullO3CPU<Impl>(this, params)
|
||||
{
|
||||
DPRINTF(O3CPU, "Creating SparcO3CPU object.\n");
|
||||
|
||||
// Setup any thread state.
|
||||
this->thread.resize(this->numThreads);
|
||||
|
||||
for (int i = 0; i < this->numThreads; ++i) {
|
||||
#if FULL_SYSTEM
|
||||
// SMT is not supported in FS mode yet.
|
||||
assert(this->numThreads == 1);
|
||||
this->thread[i] = new Thread(this, 0);
|
||||
this->thread[i]->setStatus(ThreadContext::Suspended);
|
||||
#else
|
||||
if (i < params->workload.size()) {
|
||||
DPRINTF(O3CPU, "Workload[%i] process is %#x",
|
||||
i, this->thread[i]);
|
||||
this->thread[i] = new Thread(this, i, params->workload[i], i);
|
||||
|
||||
this->thread[i]->setStatus(ThreadContext::Suspended);
|
||||
|
||||
//usedTids[i] = true;
|
||||
//threadMap[i] = i;
|
||||
} else {
|
||||
//Allocate Empty thread so M5 can use later
|
||||
//when scheduling threads to CPU
|
||||
Process* dummy_proc = NULL;
|
||||
|
||||
this->thread[i] = new Thread(this, i, dummy_proc, i);
|
||||
//usedTids[i] = false;
|
||||
}
|
||||
#endif // !FULL_SYSTEM
|
||||
|
||||
ThreadContext *tc;
|
||||
|
||||
// Setup the TC that will serve as the interface to the threads/CPU.
|
||||
SparcTC<Impl> *sparc_tc = new SparcTC<Impl>;
|
||||
|
||||
tc = sparc_tc;
|
||||
|
||||
// If we're using a checker, then the TC should be the
|
||||
// CheckerThreadContext.
|
||||
#if USE_CHECKER
|
||||
if (params->checker) {
|
||||
tc = new CheckerThreadContext<SparcTC<Impl> >(
|
||||
sparc_tc, this->checker);
|
||||
}
|
||||
#endif
|
||||
|
||||
sparc_tc->cpu = this;
|
||||
sparc_tc->thread = this->thread[i];
|
||||
|
||||
#if FULL_SYSTEM
|
||||
// Setup quiesce event.
|
||||
this->thread[i]->quiesceEvent = new EndQuiesceEvent(tc);
|
||||
#endif
|
||||
// Give the thread the TC.
|
||||
this->thread[i]->tc = tc;
|
||||
this->thread[i]->setCpuId(params->cpu_id);
|
||||
|
||||
// Add the TC to the CPU's list of TC's.
|
||||
this->threadContexts.push_back(tc);
|
||||
}
|
||||
|
||||
for (int i=0; i < this->numThreads; i++) {
|
||||
this->thread[i]->setFuncExeInst(0);
|
||||
}
|
||||
|
||||
lockAddr = 0;
|
||||
lockFlag = false;
|
||||
}
|
||||
|
||||
template <class Impl>
|
||||
void
|
||||
SparcO3CPU<Impl>::regStats()
|
||||
{
|
||||
// Register stats for everything that has stats.
|
||||
this->fullCPURegStats();
|
||||
this->fetch.regStats();
|
||||
this->decode.regStats();
|
||||
this->rename.regStats();
|
||||
this->iew.regStats();
|
||||
this->commit.regStats();
|
||||
}
|
||||
|
||||
|
||||
template <class Impl>
|
||||
TheISA::MiscReg
|
||||
SparcO3CPU<Impl>::readMiscRegNoEffect(int misc_reg, unsigned tid)
|
||||
{
|
||||
return this->regFile.readMiscRegNoEffect(misc_reg, tid);
|
||||
}
|
||||
|
||||
template <class Impl>
|
||||
TheISA::MiscReg
|
||||
SparcO3CPU<Impl>::readMiscReg(int misc_reg, unsigned tid)
|
||||
{
|
||||
return this->regFile.readMiscReg(misc_reg, tid);
|
||||
}
|
||||
|
||||
template <class Impl>
|
||||
void
|
||||
SparcO3CPU<Impl>::setMiscRegNoEffect(int misc_reg,
|
||||
const SparcISA::MiscReg &val, unsigned tid)
|
||||
{
|
||||
this->regFile.setMiscRegNoEffect(misc_reg, val, tid);
|
||||
}
|
||||
|
||||
template <class Impl>
|
||||
void
|
||||
SparcO3CPU<Impl>::setMiscReg(int misc_reg,
|
||||
const SparcISA::MiscReg &val, unsigned tid)
|
||||
{
|
||||
this->regFile.setMiscReg(misc_reg, val, tid);
|
||||
}
|
||||
|
||||
template <class Impl>
|
||||
void
|
||||
SparcO3CPU<Impl>::squashFromTC(unsigned tid)
|
||||
{
|
||||
this->thread[tid]->inSyscall = true;
|
||||
this->commit.generateTCEvent(tid);
|
||||
}
|
||||
|
||||
#if FULL_SYSTEM
|
||||
|
||||
template <class Impl>
|
||||
void
|
||||
SparcO3CPU<Impl>::post_interrupt(int int_num, int index)
|
||||
{
|
||||
BaseCPU::post_interrupt(int_num, index);
|
||||
|
||||
if (this->thread[0]->status() == ThreadContext::Suspended) {
|
||||
DPRINTF(IPI,"Suspended Processor awoke\n");
|
||||
this->threadContexts[0]->activate();
|
||||
}
|
||||
}
|
||||
|
||||
template <class Impl>
|
||||
Fault
|
||||
SparcO3CPU<Impl>::hwrei(unsigned tid)
|
||||
{
|
||||
panic("This doesn't make sense for SPARC\n");
|
||||
return NoFault;
|
||||
}
|
||||
|
||||
template <class Impl>
|
||||
bool
|
||||
SparcO3CPU<Impl>::simPalCheck(int palFunc, unsigned tid)
|
||||
{
|
||||
panic("This doesn't make sense for SPARC\n");
|
||||
return true;
|
||||
}
|
||||
|
||||
template <class Impl>
|
||||
Fault
|
||||
SparcO3CPU<Impl>::getInterrupts()
|
||||
{
|
||||
// Check if there are any outstanding interrupts
|
||||
return this->interrupts.getInterrupt(this->threadContexts[0]);
|
||||
}
|
||||
|
||||
template <class Impl>
|
||||
void
|
||||
SparcO3CPU<Impl>::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(O3CPU, "Interrupt %s being handled\n", interrupt->name());
|
||||
this->trap(interrupt, 0);
|
||||
}
|
||||
|
||||
#endif // FULL_SYSTEM
|
||||
|
||||
template <class Impl>
|
||||
void
|
||||
SparcO3CPU<Impl>::trap(Fault fault, unsigned tid)
|
||||
{
|
||||
// Pass the thread's TC into the invoke method.
|
||||
fault->invoke(this->threadContexts[tid]);
|
||||
}
|
||||
|
||||
#if !FULL_SYSTEM
|
||||
|
||||
template <class Impl>
|
||||
void
|
||||
SparcO3CPU<Impl>::syscall(int64_t callnum, int tid)
|
||||
{
|
||||
DPRINTF(O3CPU, "[tid:%i] Executing syscall().\n\n", tid);
|
||||
|
||||
DPRINTF(Activity,"Activity: syscall() called.\n");
|
||||
|
||||
// Temporarily increase this by one to account for the syscall
|
||||
// instruction.
|
||||
++(this->thread[tid]->funcExeInst);
|
||||
|
||||
// Execute the actual syscall.
|
||||
this->thread[tid]->syscall(callnum);
|
||||
|
||||
// Decrease funcExeInst by one as the normal commit will handle
|
||||
// incrementing it.
|
||||
--(this->thread[tid]->funcExeInst);
|
||||
}
|
||||
|
||||
template <class Impl>
|
||||
TheISA::IntReg
|
||||
SparcO3CPU<Impl>::getSyscallArg(int i, int tid)
|
||||
{
|
||||
assert(i < TheISA::NumArgumentRegs);
|
||||
TheISA::IntReg idx = TheISA::flattenIntIndex(this->tcBase(tid),
|
||||
SparcISA::ArgumentReg[i]);
|
||||
TheISA::IntReg val = this->readArchIntReg(idx, tid);
|
||||
if (bits(this->readMiscRegNoEffect(SparcISA::MISCREG_PSTATE, tid), 3, 3))
|
||||
val = bits(val, 31, 0);
|
||||
return val;
|
||||
}
|
||||
|
||||
template <class Impl>
|
||||
void
|
||||
SparcO3CPU<Impl>::setSyscallArg(int i, TheISA::IntReg val, int tid)
|
||||
{
|
||||
assert(i < TheISA::NumArgumentRegs);
|
||||
TheISA::IntReg idx = TheISA::flattenIntIndex(this->tcBase(tid),
|
||||
SparcISA::ArgumentReg[i]);
|
||||
this->setArchIntReg(idx, val, tid);
|
||||
}
|
||||
|
||||
template <class Impl>
|
||||
void
|
||||
SparcO3CPU<Impl>::setSyscallReturn(SyscallReturn return_value, int tid)
|
||||
{
|
||||
TheISA::setSyscallReturn(return_value, this->tcBase(tid));
|
||||
}
|
||||
#endif
|
||||
@@ -35,7 +35,7 @@
|
||||
#include "arch/sparc/types.hh"
|
||||
#include "cpu/base_dyn_inst.hh"
|
||||
#include "cpu/inst_seq.hh"
|
||||
#include "cpu/o3/sparc/cpu.hh"
|
||||
#include "cpu/o3/cpu.hh"
|
||||
#include "cpu/o3/sparc/impl.hh"
|
||||
|
||||
class Packet;
|
||||
|
||||
@@ -41,7 +41,7 @@ template <class Impl>
|
||||
class SparcDynInst;
|
||||
|
||||
template <class Impl>
|
||||
class SparcO3CPU;
|
||||
class FullO3CPU;
|
||||
|
||||
/** Implementation specific struct that defines several key types to the
|
||||
* CPU, the stages within the CPU, the time buffers, and the DynInst.
|
||||
@@ -68,7 +68,7 @@ struct SparcSimpleImpl
|
||||
typedef RefCountingPtr<DynInst> DynInstPtr;
|
||||
|
||||
/** The O3CPU type to be used. */
|
||||
typedef SparcO3CPU<SparcSimpleImpl> O3CPU;
|
||||
typedef FullO3CPU<SparcSimpleImpl> O3CPU;
|
||||
|
||||
/** Same typedef, but for CPUType. BaseDynInst may not always use
|
||||
* an O3 CPU, so it's clearer to call it CPUType instead in that
|
||||
|
||||
@@ -1,78 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2004-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.
|
||||
*
|
||||
* Authors: Gabe Black
|
||||
*/
|
||||
|
||||
#include "arch/sparc/types.hh"
|
||||
#include "cpu/o3/thread_context.hh"
|
||||
|
||||
template <class Impl>
|
||||
class SparcTC : public O3ThreadContext<Impl>
|
||||
{
|
||||
public:
|
||||
#if FULL_SYSTEM
|
||||
/** Returns pointer to the quiesce event. */
|
||||
virtual EndQuiesceEvent *getQuiesceEvent()
|
||||
{
|
||||
return this->thread->quiesceEvent;
|
||||
}
|
||||
#endif
|
||||
|
||||
virtual uint64_t readNextNPC()
|
||||
{
|
||||
return this->cpu->readNextNPC(this->thread->readTid());
|
||||
}
|
||||
|
||||
virtual void setNextNPC(uint64_t val)
|
||||
{
|
||||
this->cpu->setNextNPC(val, this->thread->readTid());
|
||||
}
|
||||
|
||||
virtual void changeRegFileContext(TheISA::RegContextParam param,
|
||||
TheISA::RegContextVal val)
|
||||
{
|
||||
//XXX Ignore this for now. This -really- needs to get fixed.
|
||||
}
|
||||
|
||||
|
||||
/** This function exits the thread context in the CPU and returns
|
||||
* 1 if the CPU has no more active threads (meaning it's OK to exit);
|
||||
* Used in syscall-emulation mode when a thread executes the 'exit'
|
||||
* syscall.
|
||||
*/
|
||||
virtual int exit()
|
||||
{
|
||||
this->deallocate();
|
||||
|
||||
// If there are still threads executing in the system
|
||||
if (this->cpu->numActiveThreads())
|
||||
return 0; // don't exit simulation
|
||||
else
|
||||
return 1; // exit simulation
|
||||
}
|
||||
};
|
||||
@@ -260,7 +260,51 @@ class O3ThreadContext : public ThreadContext
|
||||
|
||||
/** Reads the funcExeInst counter. */
|
||||
virtual Counter readFuncExeInst() { return thread->funcExeInst; }
|
||||
#else
|
||||
/** Returns pointer to the quiesce event. */
|
||||
virtual EndQuiesceEvent *getQuiesceEvent()
|
||||
{
|
||||
return this->thread->quiesceEvent;
|
||||
}
|
||||
#endif
|
||||
|
||||
virtual uint64_t readNextNPC()
|
||||
{
|
||||
return this->cpu->readNextNPC(this->thread->readTid());
|
||||
}
|
||||
|
||||
virtual void setNextNPC(uint64_t val)
|
||||
{
|
||||
#if THE_ISA == ALPHA_ISA
|
||||
panic("Not supported on Alpha!");
|
||||
#endif
|
||||
this->cpu->setNextNPC(val, this->thread->readTid());
|
||||
}
|
||||
|
||||
virtual void changeRegFileContext(TheISA::RegContextParam param,
|
||||
TheISA::RegContextVal val)
|
||||
{
|
||||
#if THE_ISA != SPARC_ISA
|
||||
panic("changeRegFileContext not implemented.");
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/** This function exits the thread context in the CPU and returns
|
||||
* 1 if the CPU has no more active threads (meaning it's OK to exit);
|
||||
* Used in syscall-emulation mode when a thread executes the 'exit'
|
||||
* syscall.
|
||||
*/
|
||||
virtual int exit()
|
||||
{
|
||||
this->deallocate();
|
||||
|
||||
// If there are still threads executing in the system
|
||||
if (this->cpu->numActiveThreads())
|
||||
return 0; // don't exit simulation
|
||||
else
|
||||
return 1; // exit simulation
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user