Factor ExecContext::setStatus(), BaseCPU::execCtxStatusChange(),

and SimpleCPU::setStatus() into separate functions.  For example,
setStatus(Active) is now activate().

--HG--
extra : convert_revision : 4392e07caf6c918db0b535f613175109681686fe
This commit is contained in:
Steve Reinhardt 2003-12-10 17:47:28 -08:00
parent db6038937d
commit 4ce6118fda
11 changed files with 142 additions and 91 deletions

View file

@ -892,7 +892,7 @@ class Tru64 {
ec->regs.pc = attrp->registers.pc; ec->regs.pc = attrp->registers.pc;
ec->regs.npc = attrp->registers.pc + sizeof(MachInst); ec->regs.npc = attrp->registers.pc + sizeof(MachInst);
ec->setStatus(ExecContext::Active); ec->activate();
} }
/// Create thread. /// Create thread.
@ -1098,7 +1098,7 @@ class Tru64 {
// found waiting process: make it active // found waiting process: make it active
ExecContext *newCtx = i->waitingContext; ExecContext *newCtx = i->waitingContext;
assert(newCtx->status() == ExecContext::Suspended); assert(newCtx->status() == ExecContext::Suspended);
newCtx->setStatus(ExecContext::Active); newCtx->activate();
// get rid of this record // get rid of this record
i = process->waitList.erase(i); i = process->waitList.erase(i);
@ -1127,7 +1127,7 @@ class Tru64 {
} else { } else {
// lock is busy: disable until free // lock is busy: disable until free
process->waitList.push_back(Process::WaitRec(uaddr, xc)); 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); m5_unlock_mutex(lock_addr, process, xc);
process->waitList.push_back(Process::WaitRec(cond_addr, xc)); process->waitList.push_back(Process::WaitRec(cond_addr, xc));
xc->setStatus(ExecContext::Suspended); xc->suspend();
return 0; return 0;
} }
@ -1250,7 +1250,7 @@ class Tru64 {
ExecContext *xc) ExecContext *xc)
{ {
assert(xc->status() == ExecContext::Active); assert(xc->status() == ExecContext::Active);
xc->setStatus(ExecContext::Unallocated); xc->deallocate();
return 0; return 0;
} }

View file

@ -552,7 +552,7 @@ ExecContext::simPalCheck(int palFunc)
switch (palFunc) { switch (palFunc) {
case PAL::halt: case PAL::halt:
if (!misspeculating()) { if (!misspeculating()) {
setStatus(Halted); halt();
if (--System::numSystemsRunning == 0) if (--System::numSystemsRunning == 0)
new SimExitEvent("all cpus halted"); new SimExitEvent("all cpus halted");
} }

View file

@ -52,7 +52,7 @@ namespace AlphaPseudo
return; return;
Annotate::QUIESCE(xc); Annotate::QUIESCE(xc);
xc->setStatus(ExecContext::Suspended); xc->suspend();
xc->kernelStats.quiesce(); xc->kernelStats.quiesce();
} }

View file

@ -73,7 +73,20 @@ class BaseCPU : public SimObject
std::vector<ExecContext *> execContexts; std::vector<ExecContext *> execContexts;
public: 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: public:

View file

@ -121,23 +121,54 @@ ExecContext::unserialize(Checkpoint *cp, const std::string &section)
void void
ExecContext::setStatus(Status new_status) ExecContext::activate(int delay)
{ {
#ifdef FULL_SYSTEM if (status() == Active)
if (status() == new_status)
return; 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 // 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); assert(status() == Active);
return; return;
} }
#endif #endif
_status = new_status; _status = Suspended;
cpu->execCtxStatusChg(thread_num); 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 void
ExecContext::regStats(const string &name) ExecContext::regStats(const string &name)
{ {

View file

@ -93,7 +93,18 @@ class ExecContext
public: public:
Status status() const { return _status; } 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 #ifdef FULL_SYSTEM
public: public:

View file

@ -193,11 +193,7 @@ SimpleCPU::takeOverFrom(BaseCPU *oldCPU)
ExecContext *xc = execContexts[i]; ExecContext *xc = execContexts[i];
if (xc->status() == ExecContext::Active && _status != Running) { if (xc->status() == ExecContext::Active && _status != Running) {
_status = Running; _status = Running;
// the CpuSwitchEvent has a low priority, so it's tickEvent.schedule(curTick);
// 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);
} }
} }
@ -206,74 +202,47 @@ SimpleCPU::takeOverFrom(BaseCPU *oldCPU)
void void
SimpleCPU::execCtxStatusChg(int thread_num) { SimpleCPU::activateContext(int thread_num, int delay)
{
assert(thread_num == 0); assert(thread_num == 0);
assert(xc); assert(xc);
if (xc->status() == ExecContext::Active) assert(_status == Idle);
setStatus(Running); notIdleFraction++;
else scheduleTickEvent(delay);
setStatus(Idle); _status = Running;
} }
void void
SimpleCPU::setStatus(Status new_status) SimpleCPU::suspendContext(int thread_num)
{ {
Status old_status = status(); assert(thread_num == 0);
assert(xc);
// We should never even get here if the CPU has been switched out. assert(_status == Running);
assert(old_status != SwitchedOut);
_status = new_status;
switch (status()) {
case IcacheMissStall:
assert(old_status == Running);
lastIcacheStall = curTick;
if (tickEvent.scheduled())
tickEvent.squash();
break;
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--; notIdleFraction--;
if (tickEvent.scheduled()) unscheduleTickEvent();
tickEvent.squash(); _status = Idle;
break;
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::deallocateContext(int thread_num)
{
// for now, these are equivalent
suspendContext(thread_num);
} }
void
SimpleCPU::haltContext(int thread_num)
{
// for now, these are equivalent
suspendContext(thread_num);
}
void void
SimpleCPU::regStats() SimpleCPU::regStats()
{ {
@ -382,7 +351,9 @@ SimpleCPU::read(Addr addr, T& data, unsigned flags)
// at some point. // at some point.
if (result != MA_HIT && dcacheInterface->doEvents) { if (result != MA_HIT && dcacheInterface->doEvents) {
memReq->completionEvent = &cacheCompletionEvent; 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. // at some point.
if (result != MA_HIT && dcacheInterface->doEvents) { if (result != MA_HIT && dcacheInterface->doEvents) {
memReq->completionEvent = &cacheCompletionEvent; memReq->completionEvent = &cacheCompletionEvent;
setStatus(DcacheMissStall); lastDcacheStall = curTick;
unscheduleTickEvent();
_status = DcacheMissStall;
} }
} }
@ -533,11 +506,13 @@ SimpleCPU::processCacheCompletion()
switch (status()) { switch (status()) {
case IcacheMissStall: case IcacheMissStall:
icacheStallCycles += curTick - lastIcacheStall; icacheStallCycles += curTick - lastIcacheStall;
setStatus(IcacheMissComplete); _status = IcacheMissComplete;
scheduleTickEvent(1);
break; break;
case DcacheMissStall: case DcacheMissStall:
dcacheStallCycles += curTick - lastDcacheStall; dcacheStallCycles += curTick - lastDcacheStall;
setStatus(Running); _status = Running;
scheduleTickEvent(1);
break; break;
case SwitchedOut: case SwitchedOut:
// If this CPU has been switched out due to sampling/warm-up, // 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) { if (xc->status() == ExecContext::Suspended) {
DPRINTF(IPI,"Suspended Processor awoke\n"); DPRINTF(IPI,"Suspended Processor awoke\n");
xc->setStatus(ExecContext::Active); xc->activate();
Annotate::Resume(xc); Annotate::Resume(xc);
} }
} }
@ -627,7 +602,9 @@ SimpleCPU::tick()
// We've already fetched an instruction and were stalled on an // We've already fetched an instruction and were stalled on an
// I-cache miss. No need to fetch it again. // 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 { else {
// Try to fetch an instruction // Try to fetch an instruction
@ -660,7 +637,9 @@ SimpleCPU::tick()
// at some point. // at some point.
if (result != MA_HIT && icacheInterface->doEvents) { if (result != MA_HIT && icacheInterface->doEvents) {
memReq->completionEvent = &cacheCompletionEvent; memReq->completionEvent = &cacheCompletionEvent;
setStatus(IcacheMissStall); lastIcacheStall = curTick;
unscheduleTickEvent();
_status = IcacheMissStall;
return; return;
} }
} }

View file

@ -75,6 +75,22 @@ class SimpleCPU : public BaseCPU
TickEvent tickEvent; 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: private:
Trace::InstRecord *traceData; Trace::InstRecord *traceData;
template<typename T> template<typename T>
@ -172,9 +188,10 @@ class SimpleCPU : public BaseCPU
Status status() const { return _status; } Status status() const { return _status; }
virtual void execCtxStatusChg(int thread_num); virtual void activateContext(int thread_num, int delay);
virtual void suspendContext(int thread_num);
void setStatus(Status new_status); virtual void deallocateContext(int thread_num);
virtual void haltContext(int thread_num);
// statistics // statistics
virtual void regStats(); virtual void regStats();

View file

@ -158,7 +158,7 @@ AlphaConsole::write(MemReqPtr req, const uint8_t *data)
other_xc->regs.ipr[TheISA::IPR_PALtemp16] = cpu; other_xc->regs.ipr[TheISA::IPR_PALtemp16] = cpu;
other_xc->regs.intRegFile[0] = cpu; other_xc->regs.intRegFile[0] = cpu;
other_xc->regs.intRegFile[30] = alphaAccess->bootStrapImpure; other_xc->regs.intRegFile[30] = alphaAccess->bootStrapImpure;
other_xc->setStatus(ExecContext::Active); //Start the cpu other_xc->activate(); //Start the cpu
return No_Fault; return No_Fault;
} }

View file

@ -566,7 +566,7 @@ Tru64System::registerExecContext(ExecContext *xc)
int xcIndex = System::registerExecContext(xc); int xcIndex = System::registerExecContext(xc);
if (xcIndex == 0) { if (xcIndex == 0) {
xc->setStatus(ExecContext::Active); xc->activate();
} }
RemoteGDB *rgdb = new RemoteGDB(this, xc); RemoteGDB *rgdb = new RemoteGDB(this, xc);

View file

@ -149,7 +149,7 @@ Process::registerExecContext(ExecContext *xc)
xc->regs = *init_regs; xc->regs = *init_regs;
// mark this context as active // mark this context as active
xc->setStatus(ExecContext::Active); xc->activate();
} }
// return CPU number to caller and increment available CPU count // return CPU number to caller and increment available CPU count