summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--arch/alpha/alpha_tru64_process.cc10
-rw-r--r--arch/alpha/ev5.cc2
-rw-r--r--arch/alpha/pseudo_inst.cc2
-rw-r--r--cpu/base_cpu.hh15
-rw-r--r--cpu/exec_context.cc43
-rw-r--r--cpu/exec_context.hh13
-rw-r--r--cpu/simple_cpu/simple_cpu.cc111
-rw-r--r--cpu/simple_cpu/simple_cpu.hh23
-rw-r--r--dev/alpha_console.cc2
-rw-r--r--kern/tru64/tru64_system.cc2
-rw-r--r--sim/process.cc2
11 files changed, 138 insertions, 87 deletions
diff --git a/arch/alpha/alpha_tru64_process.cc b/arch/alpha/alpha_tru64_process.cc
index aece4de5a..f411e594d 100644
--- a/arch/alpha/alpha_tru64_process.cc
+++ b/arch/alpha/alpha_tru64_process.cc
@@ -892,7 +892,7 @@ class Tru64 {
ec->regs.pc = attrp->registers.pc;
ec->regs.npc = attrp->registers.pc + sizeof(MachInst);
- ec->setStatus(ExecContext::Active);
+ ec->activate();
}
/// Create thread.
@@ -1098,7 +1098,7 @@ class Tru64 {
// found waiting process: make it active
ExecContext *newCtx = i->waitingContext;
assert(newCtx->status() == ExecContext::Suspended);
- newCtx->setStatus(ExecContext::Active);
+ newCtx->activate();
// get rid of this record
i = process->waitList.erase(i);
@@ -1127,7 +1127,7 @@ class Tru64 {
} else {
// lock is busy: disable until free
process->waitList.push_back(Process::WaitRec(uaddr, xc));
- xc->setStatus(ExecContext::Suspended);
+ xc->suspend();
}
}
@@ -1239,7 +1239,7 @@ class Tru64 {
m5_unlock_mutex(lock_addr, process, xc);
process->waitList.push_back(Process::WaitRec(cond_addr, xc));
- xc->setStatus(ExecContext::Suspended);
+ xc->suspend();
return 0;
}
@@ -1250,7 +1250,7 @@ class Tru64 {
ExecContext *xc)
{
assert(xc->status() == ExecContext::Active);
- xc->setStatus(ExecContext::Unallocated);
+ xc->deallocate();
return 0;
}
diff --git a/arch/alpha/ev5.cc b/arch/alpha/ev5.cc
index 826a1ab02..6759fdbf9 100644
--- a/arch/alpha/ev5.cc
+++ b/arch/alpha/ev5.cc
@@ -552,7 +552,7 @@ ExecContext::simPalCheck(int palFunc)
switch (palFunc) {
case PAL::halt:
if (!misspeculating()) {
- setStatus(Halted);
+ halt();
if (--System::numSystemsRunning == 0)
new SimExitEvent("all cpus halted");
}
diff --git a/arch/alpha/pseudo_inst.cc b/arch/alpha/pseudo_inst.cc
index c62de3ce6..c5d82bd21 100644
--- a/arch/alpha/pseudo_inst.cc
+++ b/arch/alpha/pseudo_inst.cc
@@ -52,7 +52,7 @@ namespace AlphaPseudo
return;
Annotate::QUIESCE(xc);
- xc->setStatus(ExecContext::Suspended);
+ xc->suspend();
xc->kernelStats.quiesce();
}
diff --git a/cpu/base_cpu.hh b/cpu/base_cpu.hh
index 143fc9662..af1f34b67 100644
--- a/cpu/base_cpu.hh
+++ b/cpu/base_cpu.hh
@@ -73,7 +73,20 @@ class BaseCPU : public SimObject
std::vector<ExecContext *> execContexts;
public:
- virtual void execCtxStatusChg(int thread_num) {}
+
+ /// Notify the CPU that the indicated context is now active. The
+ /// delay parameter indicates the number of ticks to wait before
+ /// executing (typically 0 or 1).
+ virtual void activateContext(int thread_num, int delay) {}
+
+ /// Notify the CPU that the indicated context is now suspended.
+ virtual void suspendContext(int thread_num) {}
+
+ /// Notify the CPU that the indicated context is now deallocated.
+ virtual void deallocateContext(int thread_num) {}
+
+ /// Notify the CPU that the indicated context is now halted.
+ virtual void haltContext(int thread_num) {}
public:
diff --git a/cpu/exec_context.cc b/cpu/exec_context.cc
index 7332b86a6..23ae7eda8 100644
--- a/cpu/exec_context.cc
+++ b/cpu/exec_context.cc
@@ -121,24 +121,55 @@ ExecContext::unserialize(Checkpoint *cp, const std::string &section)
void
-ExecContext::setStatus(Status new_status)
+ExecContext::activate(int delay)
{
-#ifdef FULL_SYSTEM
- if (status() == new_status)
+ if (status() == Active)
return;
+ _status = Active;
+ cpu->activateContext(thread_num, delay);
+}
+
+void
+ExecContext::suspend()
+{
+ if (status() == Suspended)
+ return;
+
+#ifdef FULL_SYSTEM
// Don't change the status from active if there are pending interrupts
- if (new_status == Suspended && cpu->check_interrupts()) {
+ if (cpu->check_interrupts()) {
assert(status() == Active);
return;
}
#endif
- _status = new_status;
- cpu->execCtxStatusChg(thread_num);
+ _status = Suspended;
+ cpu->suspendContext(thread_num);
}
void
+ExecContext::deallocate()
+{
+ if (status() == Unallocated)
+ return;
+
+ _status = Unallocated;
+ cpu->deallocateContext(thread_num);
+}
+
+void
+ExecContext::halt()
+{
+ if (status() == Halted)
+ return;
+
+ _status = Halted;
+ cpu->haltContext(thread_num);
+}
+
+
+void
ExecContext::regStats(const string &name)
{
#ifdef FULL_SYSTEM
diff --git a/cpu/exec_context.hh b/cpu/exec_context.hh
index 7999e3735..f3c4b8015 100644
--- a/cpu/exec_context.hh
+++ b/cpu/exec_context.hh
@@ -93,7 +93,18 @@ class ExecContext
public:
Status status() const { return _status; }
- void setStatus(Status new_status);
+ /// Set the status to Active. Optional delay indicates number of
+ /// cycles to wait before beginning execution.
+ void activate(int delay = 1);
+
+ /// Set the status to Suspended.
+ void suspend();
+
+ /// Set the status to Unallocated.
+ void deallocate();
+
+ /// Set the status to Halted.
+ void halt();
#ifdef FULL_SYSTEM
public:
diff --git a/cpu/simple_cpu/simple_cpu.cc b/cpu/simple_cpu/simple_cpu.cc
index 77f0c41ed..2bbfb82f1 100644
--- a/cpu/simple_cpu/simple_cpu.cc
+++ b/cpu/simple_cpu/simple_cpu.cc
@@ -193,11 +193,7 @@ SimpleCPU::takeOverFrom(BaseCPU *oldCPU)
ExecContext *xc = execContexts[i];
if (xc->status() == ExecContext::Active && _status != Running) {
_status = Running;
- // the CpuSwitchEvent has a low priority, so it's
- // scheduled *after* the current cycle's tick event. Thus
- // the first tick event for the new context should take
- // place on the *next* cycle.
- tickEvent.schedule(curTick+1);
+ tickEvent.schedule(curTick);
}
}
@@ -206,74 +202,47 @@ SimpleCPU::takeOverFrom(BaseCPU *oldCPU)
void
-SimpleCPU::execCtxStatusChg(int thread_num) {
+SimpleCPU::activateContext(int thread_num, int delay)
+{
assert(thread_num == 0);
assert(xc);
- if (xc->status() == ExecContext::Active)
- setStatus(Running);
- else
- setStatus(Idle);
+ assert(_status == Idle);
+ notIdleFraction++;
+ scheduleTickEvent(delay);
+ _status = Running;
}
+
void
-SimpleCPU::setStatus(Status new_status)
+SimpleCPU::suspendContext(int thread_num)
{
- Status old_status = status();
-
- // We should never even get here if the CPU has been switched out.
- assert(old_status != SwitchedOut);
-
- _status = new_status;
+ assert(thread_num == 0);
+ assert(xc);
- switch (status()) {
- case IcacheMissStall:
- assert(old_status == Running);
- lastIcacheStall = curTick;
- if (tickEvent.scheduled())
- tickEvent.squash();
- break;
+ assert(_status == Running);
+ notIdleFraction--;
+ unscheduleTickEvent();
+ _status = Idle;
+}
- case IcacheMissComplete:
- assert(old_status == IcacheMissStall);
- if (tickEvent.squashed())
- tickEvent.reschedule(curTick + 1);
- else if (!tickEvent.scheduled())
- tickEvent.schedule(curTick + 1);
- break;
- case DcacheMissStall:
- assert(old_status == Running);
- lastDcacheStall = curTick;
- if (tickEvent.scheduled())
- tickEvent.squash();
- break;
-
- case Idle:
- assert(old_status == Running);
- notIdleFraction--;
- if (tickEvent.scheduled())
- tickEvent.squash();
- break;
+void
+SimpleCPU::deallocateContext(int thread_num)
+{
+ // for now, these are equivalent
+ suspendContext(thread_num);
+}
- case Running:
- assert(old_status == Idle ||
- old_status == DcacheMissStall ||
- old_status == IcacheMissComplete);
- if (old_status == Idle)
- notIdleFraction++;
-
- if (tickEvent.squashed())
- tickEvent.reschedule(curTick + 1);
- else if (!tickEvent.scheduled())
- tickEvent.schedule(curTick + 1);
- break;
- default:
- panic("can't get here");
- }
+void
+SimpleCPU::haltContext(int thread_num)
+{
+ // for now, these are equivalent
+ suspendContext(thread_num);
}
+
void
SimpleCPU::regStats()
{
@@ -382,7 +351,9 @@ SimpleCPU::read(Addr addr, T& data, unsigned flags)
// at some point.
if (result != MA_HIT && dcacheInterface->doEvents) {
memReq->completionEvent = &cacheCompletionEvent;
- setStatus(DcacheMissStall);
+ lastDcacheStall = curTick;
+ unscheduleTickEvent();
+ _status = DcacheMissStall;
}
}
@@ -463,7 +434,9 @@ SimpleCPU::write(T data, Addr addr, unsigned flags, uint64_t *res)
// at some point.
if (result != MA_HIT && dcacheInterface->doEvents) {
memReq->completionEvent = &cacheCompletionEvent;
- setStatus(DcacheMissStall);
+ lastDcacheStall = curTick;
+ unscheduleTickEvent();
+ _status = DcacheMissStall;
}
}
@@ -533,11 +506,13 @@ SimpleCPU::processCacheCompletion()
switch (status()) {
case IcacheMissStall:
icacheStallCycles += curTick - lastIcacheStall;
- setStatus(IcacheMissComplete);
+ _status = IcacheMissComplete;
+ scheduleTickEvent(1);
break;
case DcacheMissStall:
dcacheStallCycles += curTick - lastDcacheStall;
- setStatus(Running);
+ _status = Running;
+ scheduleTickEvent(1);
break;
case SwitchedOut:
// If this CPU has been switched out due to sampling/warm-up,
@@ -558,7 +533,7 @@ SimpleCPU::post_interrupt(int int_num, int index)
if (xc->status() == ExecContext::Suspended) {
DPRINTF(IPI,"Suspended Processor awoke\n");
- xc->setStatus(ExecContext::Active);
+ xc->activate();
Annotate::Resume(xc);
}
}
@@ -627,7 +602,9 @@ SimpleCPU::tick()
// We've already fetched an instruction and were stalled on an
// I-cache miss. No need to fetch it again.
- setStatus(Running);
+ // Set status to running; tick event will get rescheduled if
+ // necessary at end of tick() function.
+ _status = Running;
}
else {
// Try to fetch an instruction
@@ -660,7 +637,9 @@ SimpleCPU::tick()
// at some point.
if (result != MA_HIT && icacheInterface->doEvents) {
memReq->completionEvent = &cacheCompletionEvent;
- setStatus(IcacheMissStall);
+ lastIcacheStall = curTick;
+ unscheduleTickEvent();
+ _status = IcacheMissStall;
return;
}
}
diff --git a/cpu/simple_cpu/simple_cpu.hh b/cpu/simple_cpu/simple_cpu.hh
index 666fe490b..7c9d4ea75 100644
--- a/cpu/simple_cpu/simple_cpu.hh
+++ b/cpu/simple_cpu/simple_cpu.hh
@@ -75,6 +75,22 @@ class SimpleCPU : public BaseCPU
TickEvent tickEvent;
+ /// Schedule tick event, regardless of its current state.
+ void scheduleTickEvent(int delay)
+ {
+ if (tickEvent.squashed())
+ tickEvent.reschedule(curTick + delay);
+ else if (!tickEvent.scheduled())
+ tickEvent.schedule(curTick + delay);
+ }
+
+ /// Unschedule tick event, regardless of its current state.
+ void unscheduleTickEvent()
+ {
+ if (tickEvent.scheduled())
+ tickEvent.squash();
+ }
+
private:
Trace::InstRecord *traceData;
template<typename T>
@@ -172,9 +188,10 @@ class SimpleCPU : public BaseCPU
Status status() const { return _status; }
- virtual void execCtxStatusChg(int thread_num);
-
- void setStatus(Status new_status);
+ virtual void activateContext(int thread_num, int delay);
+ virtual void suspendContext(int thread_num);
+ virtual void deallocateContext(int thread_num);
+ virtual void haltContext(int thread_num);
// statistics
virtual void regStats();
diff --git a/dev/alpha_console.cc b/dev/alpha_console.cc
index 6fe57edb5..268370b0e 100644
--- a/dev/alpha_console.cc
+++ b/dev/alpha_console.cc
@@ -158,7 +158,7 @@ AlphaConsole::write(MemReqPtr req, const uint8_t *data)
other_xc->regs.ipr[TheISA::IPR_PALtemp16] = cpu;
other_xc->regs.intRegFile[0] = cpu;
other_xc->regs.intRegFile[30] = alphaAccess->bootStrapImpure;
- other_xc->setStatus(ExecContext::Active); //Start the cpu
+ other_xc->activate(); //Start the cpu
return No_Fault;
}
diff --git a/kern/tru64/tru64_system.cc b/kern/tru64/tru64_system.cc
index 3fa07828b..6fe5fb81b 100644
--- a/kern/tru64/tru64_system.cc
+++ b/kern/tru64/tru64_system.cc
@@ -566,7 +566,7 @@ Tru64System::registerExecContext(ExecContext *xc)
int xcIndex = System::registerExecContext(xc);
if (xcIndex == 0) {
- xc->setStatus(ExecContext::Active);
+ xc->activate();
}
RemoteGDB *rgdb = new RemoteGDB(this, xc);
diff --git a/sim/process.cc b/sim/process.cc
index bb4333896..0d7c3403d 100644
--- a/sim/process.cc
+++ b/sim/process.cc
@@ -149,7 +149,7 @@ Process::registerExecContext(ExecContext *xc)
xc->regs = *init_regs;
// mark this context as active
- xc->setStatus(ExecContext::Active);
+ xc->activate();
}
// return CPU number to caller and increment available CPU count