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:
parent
db6038937d
commit
4ce6118fda
11 changed files with 142 additions and 91 deletions
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
|
|
|
@ -52,7 +52,7 @@ namespace AlphaPseudo
|
|||
return;
|
||||
|
||||
Annotate::QUIESCE(xc);
|
||||
xc->setStatus(ExecContext::Suspended);
|
||||
xc->suspend();
|
||||
xc->kernelStats.quiesce();
|
||||
}
|
||||
|
||||
|
|
|
@ -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:
|
||||
|
||||
|
|
|
@ -121,23 +121,54 @@ ExecContext::unserialize(Checkpoint *cp, const std::string §ion)
|
|||
|
||||
|
||||
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)
|
||||
{
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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();
|
||||
assert(thread_num == 0);
|
||||
assert(xc);
|
||||
|
||||
// We should never even get here if the CPU has been switched out.
|
||||
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--;
|
||||
if (tickEvent.scheduled())
|
||||
tickEvent.squash();
|
||||
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");
|
||||
}
|
||||
assert(_status == Running);
|
||||
notIdleFraction--;
|
||||
unscheduleTickEvent();
|
||||
_status = Idle;
|
||||
}
|
||||
|
||||
|
||||
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
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue