/*
+ * Copyright (c) 2010-2012, 2016-2017 ARM Limited
+ * Copyright (c) 2013 Advanced Micro Devices, Inc.
+ * All rights reserved
+ *
+ * The license below extends only to copyright in the software and shall
+ * not be construed as granting a license to any other intellectual
+ * property including but not limited to intellectual property relating
+ * to a hardware implementation of the functionality of the software
+ * licensed hereunder. You may use the software subject to the license
+ * terms below provided that you ensure that this notice is replicated
+ * unmodified and in its entirety in all distributions of the software,
+ * modified or unmodified, in source code or in binary form.
+ *
* Copyright (c) 2004-2006 The Regents of The University of Michigan
* All rights reserved.
*
* Korey Sewell
*/
+#ifndef __CPU_O3_THREAD_CONTEXT_IMPL_HH__
+#define __CPU_O3_THREAD_CONTEXT_IMPL_HH__
+
+#include "arch/kernel_stats.hh"
#include "arch/registers.hh"
+#include "config/the_isa.hh"
#include "cpu/o3/thread_context.hh"
#include "cpu/quiesce_event.hh"
+#include "debug/O3CPU.hh"
-#if FULL_SYSTEM
template <class Impl>
-VirtualPort *
-O3ThreadContext<Impl>::getVirtPort()
+FSTranslatingPortProxy&
+O3ThreadContext<Impl>::getVirtProxy()
{
- return thread->getVirtPort();
+ return thread->getVirtProxy();
}
template <class Impl>
{
thread->dumpFuncProfile();
}
-#endif
template <class Impl>
void
O3ThreadContext<Impl>::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);
- setContextId(old_context->contextId());
- setThreadId(old_context->threadId());
-
-#if !FULL_SYSTEM
- thread->funcExeInst = old_context->readFuncExeInst();
-#else
- EndQuiesceEvent *other_quiesce = old_context->getQuiesceEvent();
- if (other_quiesce) {
- // Point the quiesce event's TC at this TC so that it wakes up
- // the proper CPU.
- other_quiesce->tc = this;
- }
- if (thread->quiesceEvent) {
- thread->quiesceEvent->tc = this;
- }
+ ::takeOverFrom(*this, *old_context);
+ TheISA::Decoder *newDecoder = getDecoderPtr();
+ TheISA::Decoder *oldDecoder = old_context->getDecoderPtr();
+ newDecoder->takeOverFrom(oldDecoder);
- // Transfer kernel stats from one CPU to the other.
thread->kernelStats = old_context->getKernelStats();
-// storeCondFailures = 0;
- cpu->lockFlag = false;
-#endif
-
- old_context->setStatus(ThreadContext::Halted);
+ thread->funcExeInst = old_context->readFuncExeInst();
- thread->inSyscall = false;
+ thread->noSquashFromTC = false;
thread->trapPending = false;
}
template <class Impl>
void
-O3ThreadContext<Impl>::activate(int delay)
+O3ThreadContext<Impl>::activate()
{
DPRINTF(O3CPU, "Calling activate on Thread Context %d\n",
threadId());
if (thread->status() == ThreadContext::Active)
return;
-#if FULL_SYSTEM
- thread->lastActivate = curTick;
-#endif
-
+ thread->lastActivate = curTick();
thread->setStatus(ThreadContext::Active);
// status() == Suspended
- cpu->activateContext(thread->threadId(), delay);
+ cpu->activateContext(thread->threadId());
}
template <class Impl>
void
-O3ThreadContext<Impl>::suspend(int delay)
+O3ThreadContext<Impl>::suspend()
{
DPRINTF(O3CPU, "Calling suspend on Thread Context %d\n",
threadId());
if (thread->status() == ThreadContext::Suspended)
return;
-#if FULL_SYSTEM
- thread->lastActivate = curTick;
- thread->lastSuspend = curTick;
-#endif
-/*
-#if FULL_SYSTEM
- // Don't change the status from active if there are pending interrupts
- if (cpu->checkInterrupts()) {
- assert(status() == ThreadContext::Active);
+ if (cpu->isDraining()) {
+ DPRINTF(O3CPU, "Ignoring suspend on TC due to pending drain\n");
return;
}
-#endif
-*/
+
+ thread->lastActivate = curTick();
+ thread->lastSuspend = curTick();
+
thread->setStatus(ThreadContext::Suspended);
cpu->suspendContext(thread->threadId());
}
template <class Impl>
void
-O3ThreadContext<Impl>::halt(int delay)
+O3ThreadContext<Impl>::halt()
{
- DPRINTF(O3CPU, "Calling halt on Thread Context %d\n",
- threadId());
+ DPRINTF(O3CPU, "Calling halt on Thread Context %d\n", threadId());
if (thread->status() == ThreadContext::Halted)
return;
void
O3ThreadContext<Impl>::regStats(const std::string &name)
{
-#if FULL_SYSTEM
- thread->kernelStats = new TheISA::Kernel::Statistics(cpu->system);
- thread->kernelStats->regStats(name + ".kern");
-#endif
-}
-
-template <class Impl>
-void
-O3ThreadContext<Impl>::serialize(std::ostream &os)
-{
-#if FULL_SYSTEM
- if (thread->kernelStats)
- thread->kernelStats->serialize(os);
-#endif
-
-}
-
-template <class Impl>
-void
-O3ThreadContext<Impl>::unserialize(Checkpoint *cp, const std::string §ion)
-{
-#if FULL_SYSTEM
- if (thread->kernelStats)
- thread->kernelStats->unserialize(cp, section);
-#endif
-
+ if (FullSystem) {
+ thread->kernelStats = new TheISA::Kernel::Statistics();
+ thread->kernelStats->regStats(name + ".kern");
+ }
}
-#if FULL_SYSTEM
template <class Impl>
Tick
O3ThreadContext<Impl>::readLastActivate()
{
thread->profileSample();
}
-#endif
-
-template <class Impl>
-TheISA::MachInst
-O3ThreadContext<Impl>:: getInst()
-{
- return thread->getInst();
-}
template <class Impl>
void
O3ThreadContext<Impl>::copyArchRegs(ThreadContext *tc)
{
- // This function will mess things up unless the ROB is empty and
- // there are no instructions in the pipeline.
- ThreadID tid = thread->threadId();
- PhysRegIndex renamed_reg;
-
- // First loop through the integer registers.
- for (int i = 0; i < TheISA::NumIntRegs; ++i) {
- renamed_reg = cpu->renameMap[tid].lookup(i);
+ // Prevent squashing
+ thread->noSquashFromTC = true;
+ TheISA::copyRegs(tc, this);
+ thread->noSquashFromTC = false;
- DPRINTF(O3CPU, "Copying over register %i, had data %lli, "
- "now has data %lli.\n",
- renamed_reg, cpu->readIntReg(renamed_reg),
- tc->readIntReg(i));
-
- cpu->setIntReg(renamed_reg, tc->readIntReg(i));
- }
-
- // Then loop through the floating point registers.
- for (int i = 0; i < TheISA::NumFloatRegs; ++i) {
- renamed_reg = cpu->renameMap[tid].lookup(i + TheISA::FP_Base_DepTag);
- cpu->setFloatRegBits(renamed_reg,
- tc->readFloatRegBits(i));
- }
-
- // Copy the misc regs.
- TheISA::copyMiscRegs(tc, this);
-
- // Then finally set the PC, the next PC, the nextNPC, the micropc, and the
- // next micropc.
- cpu->setPC(tc->readPC(), tid);
- cpu->setNextPC(tc->readNextPC(), tid);
- cpu->setNextNPC(tc->readNextNPC(), tid);
- cpu->setMicroPC(tc->readMicroPC(), tid);
- cpu->setNextMicroPC(tc->readNextMicroPC(), tid);
-#if !FULL_SYSTEM
- this->thread->funcExeInst = tc->readFuncExeInst();
-#endif
+ if (!FullSystem)
+ this->thread->funcExeInst = tc->readFuncExeInst();
}
template <class Impl>
void
O3ThreadContext<Impl>::clearArchRegs()
-{}
+{
+ cpu->isa[thread->threadId()]->clear();
+}
template <class Impl>
uint64_t
-O3ThreadContext<Impl>::readIntReg(int reg_idx)
+O3ThreadContext<Impl>::readIntRegFlat(int reg_idx)
{
- reg_idx = cpu->isa[thread->threadId()].flattenIntIndex(reg_idx);
return cpu->readArchIntReg(reg_idx, thread->threadId());
}
template <class Impl>
-TheISA::FloatReg
-O3ThreadContext<Impl>::readFloatReg(int reg_idx)
+TheISA::FloatRegBits
+O3ThreadContext<Impl>::readFloatRegBitsFlat(int reg_idx)
{
- reg_idx = cpu->isa[thread->threadId()].flattenFloatIndex(reg_idx);
- return cpu->readArchFloatReg(reg_idx, thread->threadId());
+ return cpu->readArchFloatRegBits(reg_idx, thread->threadId());
}
template <class Impl>
-TheISA::FloatRegBits
-O3ThreadContext<Impl>::readFloatRegBits(int reg_idx)
+const TheISA::VecRegContainer&
+O3ThreadContext<Impl>::readVecRegFlat(int reg_id) const
{
- reg_idx = cpu->isa[thread->threadId()].flattenFloatIndex(reg_idx);
- return cpu->readArchFloatRegInt(reg_idx, thread->threadId());
+ return cpu->readArchVecReg(reg_id, thread->threadId());
}
template <class Impl>
-void
-O3ThreadContext<Impl>::setIntReg(int reg_idx, uint64_t val)
+TheISA::VecRegContainer&
+O3ThreadContext<Impl>::getWritableVecRegFlat(int reg_id)
{
- reg_idx = cpu->isa[thread->threadId()].flattenIntIndex(reg_idx);
- cpu->setArchIntReg(reg_idx, val, thread->threadId());
+ return cpu->getWritableArchVecReg(reg_id, thread->threadId());
+}
- // Squash if we're not already in a state update mode.
- if (!thread->trapPending && !thread->inSyscall) {
- cpu->squashFromTC(thread->threadId());
- }
+template <class Impl>
+const TheISA::VecElem&
+O3ThreadContext<Impl>::readVecElemFlat(const RegIndex& idx,
+ const ElemIndex& elemIndex) const
+{
+ return cpu->readArchVecElem(idx, elemIndex, thread->threadId());
+}
+
+template <class Impl>
+TheISA::CCReg
+O3ThreadContext<Impl>::readCCRegFlat(int reg_idx)
+{
+ return cpu->readArchCCReg(reg_idx, thread->threadId());
}
template <class Impl>
void
-O3ThreadContext<Impl>::setFloatReg(int reg_idx, FloatReg val)
+O3ThreadContext<Impl>::setIntRegFlat(int reg_idx, uint64_t val)
{
- reg_idx = cpu->isa[thread->threadId()].flattenFloatIndex(reg_idx);
- cpu->setArchFloatReg(reg_idx, val, thread->threadId());
+ cpu->setArchIntReg(reg_idx, val, thread->threadId());
- if (!thread->trapPending && !thread->inSyscall) {
- cpu->squashFromTC(thread->threadId());
- }
+ conditionalSquash();
}
template <class Impl>
void
-O3ThreadContext<Impl>::setFloatRegBits(int reg_idx, FloatRegBits val)
+O3ThreadContext<Impl>::setFloatRegBitsFlat(int reg_idx, FloatRegBits val)
{
- reg_idx = cpu->isa[thread->threadId()].flattenFloatIndex(reg_idx);
- cpu->setArchFloatRegInt(reg_idx, val, thread->threadId());
+ cpu->setArchFloatRegBits(reg_idx, val, thread->threadId());
- // Squash if we're not already in a state update mode.
- if (!thread->trapPending && !thread->inSyscall) {
- cpu->squashFromTC(thread->threadId());
- }
+ conditionalSquash();
}
template <class Impl>
void
-O3ThreadContext<Impl>::setPC(uint64_t val)
+O3ThreadContext<Impl>::setVecRegFlat(int reg_idx, const VecRegContainer& val)
{
- cpu->setPC(val, thread->threadId());
+ cpu->setArchVecReg(reg_idx, val, thread->threadId());
- // Squash if we're not already in a state update mode.
- if (!thread->trapPending && !thread->inSyscall) {
- cpu->squashFromTC(thread->threadId());
- }
+ conditionalSquash();
}
template <class Impl>
void
-O3ThreadContext<Impl>::setNextPC(uint64_t val)
+O3ThreadContext<Impl>::setVecElemFlat(const RegIndex& idx,
+ const ElemIndex& elemIndex, const VecElem& val)
{
- cpu->setNextPC(val, thread->threadId());
-
- // Squash if we're not already in a state update mode.
- if (!thread->trapPending && !thread->inSyscall) {
- cpu->squashFromTC(thread->threadId());
- }
+ cpu->setArchVecElem(idx, elemIndex, val, thread->threadId());
+ conditionalSquash();
}
template <class Impl>
void
-O3ThreadContext<Impl>::setMicroPC(uint64_t val)
+O3ThreadContext<Impl>::setCCRegFlat(int reg_idx, TheISA::CCReg val)
{
- cpu->setMicroPC(val, thread->threadId());
+ cpu->setArchCCReg(reg_idx, val, thread->threadId());
- // Squash if we're not already in a state update mode.
- if (!thread->trapPending && !thread->inSyscall) {
- cpu->squashFromTC(thread->threadId());
- }
+ conditionalSquash();
}
template <class Impl>
void
-O3ThreadContext<Impl>::setNextMicroPC(uint64_t val)
+O3ThreadContext<Impl>::pcState(const TheISA::PCState &val)
{
- cpu->setNextMicroPC(val, thread->threadId());
+ cpu->pcState(val, thread->threadId());
- // Squash if we're not already in a state update mode.
- if (!thread->trapPending && !thread->inSyscall) {
- cpu->squashFromTC(thread->threadId());
- }
+ conditionalSquash();
}
template <class Impl>
-int
-O3ThreadContext<Impl>::flattenIntIndex(int reg)
+void
+O3ThreadContext<Impl>::pcStateNoRecord(const TheISA::PCState &val)
{
- return cpu->isa[thread->threadId()].flattenIntIndex(reg);
+ cpu->pcState(val, thread->threadId());
+
+ conditionalSquash();
}
template <class Impl>
-int
-O3ThreadContext<Impl>::flattenFloatIndex(int reg)
+RegId
+O3ThreadContext<Impl>::flattenRegId(const RegId& regId) const
{
- return cpu->isa[thread->threadId()].flattenFloatIndex(reg);
+ return cpu->isa[thread->threadId()]->flattenRegId(regId);
}
template <class Impl>
{
cpu->setMiscRegNoEffect(misc_reg, val, thread->threadId());
- // Squash if we're not already in a state update mode.
- if (!thread->trapPending && !thread->inSyscall) {
- cpu->squashFromTC(thread->threadId());
- }
+ conditionalSquash();
}
+#endif//__CPU_O3_THREAD_CONTEXT_IMPL_HH__
template <class Impl>
void
-O3ThreadContext<Impl>::setMiscReg(int misc_reg,
- const MiscReg &val)
+O3ThreadContext<Impl>::setMiscReg(int misc_reg, const MiscReg &val)
{
cpu->setMiscReg(misc_reg, val, thread->threadId());
- // Squash if we're not already in a state update mode.
- if (!thread->trapPending && !thread->inSyscall) {
- cpu->squashFromTC(thread->threadId());
- }
+ conditionalSquash();
}