Factor ExecContext::setStatus(), BaseCPU::execCtxStatusChange(),
authorSteve Reinhardt <stever@eecs.umich.edu>
Thu, 11 Dec 2003 01:47:28 +0000 (17:47 -0800)
committerSteve Reinhardt <stever@eecs.umich.edu>
Thu, 11 Dec 2003 01:47:28 +0000 (17:47 -0800)
and SimpleCPU::setStatus() into separate functions.  For example,
setStatus(Active) is now activate().

--HG--
extra : convert_revision : 4392e07caf6c918db0b535f613175109681686fe

arch/alpha/alpha_tru64_process.cc
arch/alpha/ev5.cc
arch/alpha/pseudo_inst.cc
cpu/base_cpu.hh
cpu/exec_context.cc
cpu/exec_context.hh
cpu/simple_cpu/simple_cpu.cc
cpu/simple_cpu/simple_cpu.hh
dev/alpha_console.cc
kern/tru64/tru64_system.cc
sim/process.cc

index aece4de5a7ecb08c2ed39467a6e4b86b7f66daf3..f411e594d8416cea00a29d84fb570571c26a9a29 100644 (file)
@@ -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;
     }
index 826a1ab02c70c1700175ee7da6faccedee7d7843..6759fdbf9ab92f6c54d069e83e286e56b3122e03 100644 (file)
@@ -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");
         }
index c62de3ce6a6608425768beb022a8f8df634d120f..c5d82bd21573d5f5fdf2dc00a2509a20e6b901a8 100644 (file)
@@ -52,7 +52,7 @@ namespace AlphaPseudo
             return;
 
         Annotate::QUIESCE(xc);
-        xc->setStatus(ExecContext::Suspended);
+        xc->suspend();
         xc->kernelStats.quiesce();
     }
 
index 143fc9662e998c72c5715abff4563e0cce461151..af1f34b6756f0bd2c08310e61d35e77c6be16e2c 100644 (file)
@@ -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:
 
index 7332b86a670a1d52328e2969046945c012047bf1..23ae7eda84017c5610612fe9bd7addd801859b1f 100644 (file)
@@ -121,23 +121,54 @@ 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)
 {
index 7999e37350dfc5ebc7acb3068008bcf50d68910a..f3c4b80152454128bea1d70f7889ca57c08600a8 100644 (file)
@@ -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:
index 77f0c41ed7661f1e307fbac92ff51032132b2633..2bbfb82f1f2ea149b534b977f72bc3fe5aef251c 100644 (file)
@@ -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;
             }
         }
index 666fe490b1806a5640f18afd59ed8db00101e72a..7c9d4ea751ea9c589d8449aeaf49630334c75afb 100644 (file)
@@ -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();
index 6fe57edb55eb677a765001fe16add7c534a88bd1..268370b0ef7dfdc26c14639b8fb57678732e4c9e 100644 (file)
@@ -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;
     }
 
index 3fa07828b0e3bb814611f7b2638a50a459e35526..6fe5fb81b20553d09821647c913588c7ef48c7e3 100644 (file)
@@ -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);
index bb433389667e28aca4a38816420473549a11728e..0d7c3403d870b29f24363c05b9ba6ebf79506304 100644 (file)
@@ -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