From 4ce6118fdac16cfdc0d945e8793ace3379779288 Mon Sep 17 00:00:00 2001 From: Steve Reinhardt Date: Wed, 10 Dec 2003 17:47:28 -0800 Subject: [PATCH] Factor ExecContext::setStatus(), BaseCPU::execCtxStatusChange(), and SimpleCPU::setStatus() into separate functions. For example, setStatus(Active) is now activate(). --HG-- extra : convert_revision : 4392e07caf6c918db0b535f613175109681686fe --- arch/alpha/alpha_tru64_process.cc | 10 +-- arch/alpha/ev5.cc | 2 +- arch/alpha/pseudo_inst.cc | 2 +- cpu/base_cpu.hh | 15 +++- cpu/exec_context.cc | 43 +++++++++-- cpu/exec_context.hh | 13 +++- cpu/simple_cpu/simple_cpu.cc | 119 ++++++++++++------------------ cpu/simple_cpu/simple_cpu.hh | 23 +++++- dev/alpha_console.cc | 2 +- kern/tru64/tru64_system.cc | 2 +- sim/process.cc | 2 +- 11 files changed, 142 insertions(+), 91 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 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,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) { 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(); + 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; } } 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 @@ -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