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.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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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");
|
||||||
}
|
}
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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:
|
||||||
|
|
||||||
|
|
|
@ -121,23 +121,54 @@ ExecContext::unserialize(Checkpoint *cp, const std::string §ion)
|
||||||
|
|
||||||
|
|
||||||
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)
|
||||||
{
|
{
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in a new issue