the way i understand it, interrupts in m5 is a little bloated. the usage of CPU...
authorLisa Hsu <hsul@eecs.umich.edu>
Mon, 8 Jan 2007 23:18:28 +0000 (18:18 -0500)
committerLisa Hsu <hsul@eecs.umich.edu>
Mon, 8 Jan 2007 23:18:28 +0000 (18:18 -0500)
src/arch/sparc/interrupts.hh:
    fill in how we do interrupts on sparc a little bit.

    1) create a bitfield for interrupts, and check that in checkInterrupts() to fast path CPU.
    2) fill in getInterrupts() a little bit.

    also, update the bitfield access to be HPSTATE::hpriv, etc.
src/arch/sparc/ua2005.cc:
    1) update formatting
    2) change the way interrupts are done to use the new way to tickle the CPU.
src/cpu/base.cc:
src/cpu/base.hh:
    overload the post_interrupt function for SPARC interrupts - which are only denoted by a single int value.

--HG--
extra : convert_revision : 9074a003eff37a40dcce78f56d20f6cbcc453eb5

src/arch/sparc/interrupts.hh
src/arch/sparc/ua2005.cc
src/cpu/base.cc
src/cpu/base.hh

index 452164e46724d5d51d79df2571c4bf9fc14551c0..76bd4c6e2ad25101920d4db08201addec393542d 100644 (file)
 #include "arch/sparc/faults.hh"
 #include "cpu/thread_context.hh"
 
-
 namespace SparcISA
 {
+
+enum interrupts_t {
+    trap_level_zero,
+    hstick_match,
+    interrupt_vector,
+    cpu_mondo,
+    dev_mondo,
+    resumable_error,
+    soft_interrupt,
+    num_interrupt_types
+};
+
     class Interrupts
     {
-      protected:
 
+      private:
+
+        bool interrupts[num_interrupt_types];
+        int numPosted;
 
       public:
         Interrupts()
         {
+            for (int i = 0; i < num_interrupt_types; ++i) {
+                interrupts[i] = false;
+            }
+            numPosted = 0;
+        }
 
+        void post(int int_type)
+        {
+            if (int_type < 0 || int_type >= num_interrupt_types)
+                panic("posting unknown interrupt!\n");
+            interrupts[int_type] = true;
+            ++numPosted;
         }
+
         void post(int int_num, int index)
         {
 
@@ -64,9 +90,7 @@ namespace SparcISA
 
         bool check_interrupts(ThreadContext * tc) const
         {
-            // so far only handle softint interrupts
-            int int_level = InterruptLevel(tc->readMiscReg(MISCREG_SOFTINT));
-            if (int_level)
+            if (numPosted)
                 return true;
             else
                 return false;
@@ -74,14 +98,99 @@ namespace SparcISA
 
         Fault getInterrupt(ThreadContext * tc)
         {
+            int hpstate = tc->readMiscReg(MISCREG_HPSTATE);
+            int pstate = tc->readMiscReg(MISCREG_PSTATE);
+            bool ie = pstate & PSTATE::ie;
+
+            // THESE ARE IN ORDER OF PRIORITY
+            // since there are early returns, and the highest
+            // priority interrupts should get serviced,
+            // it is v. important that new interrupts are inserted
+            // in the right order of processing
+            if (hpstate & HPSTATE::hpriv) {
+                if (ie) {
+                    if (interrupts[hstick_match]) {
+                        interrupts[hstick_match] = false;
+                        --numPosted;
+                        return new HstickMatch;
+                    }
+                    if (interrupts[interrupt_vector]) {
+                        interrupts[interrupt_vector] = false;
+                        --numPosted;
+                        //HAVEN'T IMPLed THIS YET
+                        return NoFault;
+                    }
+                }
+            } else {
+
+                if (interrupts[trap_level_zero]) {
+                    //HAVEN'T IMPLed YET
+                    if ((pstate & HPSTATE::tlz) && (tc->readMiscReg(MISCREG_TL) == 0)) {
+                        interrupts[trap_level_zero] = false;
+                        --numPosted;
+                        return NoFault;
+                    }
+                }
+                if (interrupts[hstick_match]) {
+                    interrupts[hstick_match] = false;
+                    --numPosted;
+                    return new HstickMatch;
+                }
+                if (ie) {
+                    if (interrupts[cpu_mondo]) {
+                        interrupts[cpu_mondo] = false;
+                        --numPosted;
+                        return new CpuMondo;
+                    }
+                    if (interrupts[dev_mondo]) {
+                        interrupts[dev_mondo] = false;
+                        --numPosted;
+                        return new DevMondo;
+                    }
+                    if (interrupts[soft_interrupt]) {
+                        int il = InterruptLevel(tc->readMiscReg(MISCREG_SOFTINT));
+                        // it seems that interrupt vectors are right in
+                        // the middle of interrupt levels with regard to
+                        // priority, so have to check
+                        if ((il < 6) &&
+                            interrupts[interrupt_vector]) {
+                                // may require more details here since there
+                                // may be lots of interrupts embedded in an
+                                // platform interrupt vector
+                                interrupts[interrupt_vector] = false;
+                                --numPosted;
+                                //HAVEN'T IMPLed YET
+                                return NoFault;
+                        } else {
+                            if (il > tc->readMiscReg(MISCREG_PIL)) {
+                                uint64_t si = tc->readMiscReg(MISCREG_SOFTINT);
+                                uint64_t more = si & ~(1 << (il + 1));
+                                if (!InterruptLevel(more)) {
+                                    interrupts[soft_interrupt] = false;
+                                    --numPosted;
+                                }
+                                return new InterruptLevelN(il);
+                            }
+                        }
+                    }
+                    if (interrupts[resumable_error]) {
+                        interrupts[resumable_error] = false;
+                        --numPosted;
+                        return new ResumableError;
+                    }
+                }
+            }
+            return NoFault;
+
+
             // conditioning the softint interrups
-            if (tc->readMiscReg(MISCREG_HPSTATE) & hpriv) {
+            if (tc->readMiscReg(MISCREG_HPSTATE) & HPSTATE::hpriv) {
                 // if running in privileged mode, then pend the interrupt
                 return NoFault;
             } else {
                 int int_level = InterruptLevel(tc->readMiscReg(MISCREG_SOFTINT));
                 if ((int_level <= tc->readMiscReg(MISCREG_PIL)) ||
-                    !(tc->readMiscReg(MISCREG_PSTATE) & ie)) {
+                    !(tc->readMiscReg(MISCREG_PSTATE) & PSTATE::ie)) {
                     // if PIL or no interrupt enabled, then pend the interrupt
                     return NoFault;
                 } else {
index 1f7f650453ffe83560ca35955f5b013682ae4356..c153c2d52e64bfd3dd95c3fb9011c216ba5e9dde 100644 (file)
@@ -38,105 +38,105 @@ using namespace SparcISA;
 
 void
 MiscRegFile::setFSRegWithEffect(int miscReg, const MiscReg &val,
-        ThreadContext *tc)
+                                ThreadContext *tc)
 {
     int64_t time;
     switch (miscReg) {
         /* Full system only ASRs */
-        case MISCREG_SOFTINT:
-          // Check if we are going to interrupt because of something
-          setReg(miscReg, val);
-          tc->getCpuPtr()->checkInterrupts = true;
-          warn("Writing to softint not really supported, writing: %#x\n", val);
-          break;
-
-        case MISCREG_SOFTINT_CLR:
-          return setRegWithEffect(MISCREG_SOFTINT, ~val & softint, tc);
-        case MISCREG_SOFTINT_SET:
-          return setRegWithEffect(MISCREG_SOFTINT, val | softint, tc);
-
-        case MISCREG_TICK_CMPR:
-          if (tickCompare == NULL)
-              tickCompare = new TickCompareEvent(this, tc);
-          setReg(miscReg, val);
-          if ((tick_cmpr & mask(63)) && tickCompare->scheduled())
-                  tickCompare->deschedule();
-          time = (tick_cmpr & mask(63)) - (tick & mask(63));
-          if (!(tick_cmpr & ~mask(63)) && time > 0)
-              tickCompare->schedule(time * tc->getCpuPtr()->cycles(1));
-          panic("writing to TICK compare register %#X\n", val);
-          break;
-
-        case MISCREG_STICK_CMPR:
-          if (sTickCompare == NULL)
-              sTickCompare = new STickCompareEvent(this, tc);
-          setReg(miscReg, val);
-          if ((stick_cmpr & ~mask(63)) && sTickCompare->scheduled())
-                  sTickCompare->deschedule();
-          time = ((int64_t)(stick_cmpr & mask(63)) - (int64_t)stick) -
-             tc->getCpuPtr()->instCount();
-          if (!(stick_cmpr & ~mask(63)) && time > 0)
-              sTickCompare->schedule(time * tc->getCpuPtr()->cycles(1) + curTick);
-          DPRINTF(Timer, "writing to sTICK compare register value %#X\n", val);
-          break;
-
-        case MISCREG_PSTATE:
-          if (val & ie && !(pstate & ie)) {
-              tc->getCpuPtr()->checkInterrupts = true;
-          }
-          setReg(miscReg, val);
-
-        case MISCREG_PIL:
-          if (val < pil) {
-              tc->getCpuPtr()->checkInterrupts = true;
-          }
-          setReg(miscReg, val);
-          break;
-
-        case MISCREG_HVER:
-          panic("Shouldn't be writing HVER\n");
-
-        case MISCREG_HTBA:
-          // clear lower 7 bits on writes.
-          setReg(miscReg, val & ULL(~0x7FFF));
-          break;
-
-        case MISCREG_QUEUE_CPU_MONDO_HEAD:
-        case MISCREG_QUEUE_CPU_MONDO_TAIL:
-        case MISCREG_QUEUE_DEV_MONDO_HEAD:
-        case MISCREG_QUEUE_DEV_MONDO_TAIL:
-        case MISCREG_QUEUE_RES_ERROR_HEAD:
-        case MISCREG_QUEUE_RES_ERROR_TAIL:
-        case MISCREG_QUEUE_NRES_ERROR_HEAD:
-        case MISCREG_QUEUE_NRES_ERROR_TAIL:
-          setReg(miscReg, val);
-          tc->getCpuPtr()->checkInterrupts = true;
-          break;
-
-        case MISCREG_HSTICK_CMPR:
-          if (hSTickCompare == NULL)
-              hSTickCompare = new HSTickCompareEvent(this, tc);
-          setReg(miscReg, val);
-          if ((hstick_cmpr & ~mask(63)) && hSTickCompare->scheduled())
-                hSTickCompare->deschedule();
-          time = ((int64_t)(hstick_cmpr & mask(63)) - (int64_t)stick) -
-             tc->getCpuPtr()->instCount();
-          if (!(hstick_cmpr & ~mask(63)) && time > 0)
-              hSTickCompare->schedule(curTick + time * tc->getCpuPtr()->cycles(1));
-          DPRINTF(Timer, "writing to hsTICK compare register value %#X\n", val);
-          break;
-
-        case MISCREG_HPSTATE:
-          // T1000 spec says impl. dependent val must always be 1
-          setReg(miscReg, val | id);
-          break;
-        case MISCREG_HTSTATE:
-        case MISCREG_STRAND_STS_REG:
-          setReg(miscReg, val);
-          break;
-
-        default:
-          panic("Invalid write to FS misc register %s\n", getMiscRegName(miscReg));
+      case MISCREG_SOFTINT:
+        // Check if we are going to interrupt because of something
+        setReg(miscReg, val);
+        tc->getCpuPtr()->post_interrupt(soft_interrupt);
+        warn("Writing to softint not really supported, writing: %#x\n", val);
+        break;
+
+      case MISCREG_SOFTINT_CLR:
+        return setRegWithEffect(MISCREG_SOFTINT, ~val & softint, tc);
+      case MISCREG_SOFTINT_SET:
+        return setRegWithEffect(MISCREG_SOFTINT, val | softint, tc);
+
+      case MISCREG_TICK_CMPR:
+        if (tickCompare == NULL)
+            tickCompare = new TickCompareEvent(this, tc);
+        setReg(miscReg, val);
+        if ((tick_cmpr & mask(63)) && tickCompare->scheduled())
+            tickCompare->deschedule();
+        time = (tick_cmpr & mask(63)) - (tick & mask(63));
+        if (!(tick_cmpr & ~mask(63)) && time > 0)
+            tickCompare->schedule(time * tc->getCpuPtr()->cycles(1));
+        panic("writing to TICK compare register %#X\n", val);
+        break;
+
+      case MISCREG_STICK_CMPR:
+        if (sTickCompare == NULL)
+            sTickCompare = new STickCompareEvent(this, tc);
+        setReg(miscReg, val);
+        if ((stick_cmpr & ~mask(63)) && sTickCompare->scheduled())
+            sTickCompare->deschedule();
+        time = ((int64_t)(stick_cmpr & mask(63)) - (int64_t)stick) -
+            tc->getCpuPtr()->instCount();
+        if (!(stick_cmpr & ~mask(63)) && time > 0)
+            sTickCompare->schedule(time * tc->getCpuPtr()->cycles(1) + curTick);
+        DPRINTF(Timer, "writing to sTICK compare register value %#X\n", val);
+        break;
+
+      case MISCREG_PSTATE:
+        if (val & ie && !(pstate & ie)) {
+            tc->getCpuPtr()->checkInterrupts = true;
+        }
+        setReg(miscReg, val);
+
+      case MISCREG_PIL:
+        if (val < pil) {
+            tc->getCpuPtr()->checkInterrupts = true;
+        }
+        setReg(miscReg, val);
+        break;
+
+      case MISCREG_HVER:
+        panic("Shouldn't be writing HVER\n");
+
+      case MISCREG_HTBA:
+        // clear lower 7 bits on writes.
+        setReg(miscReg, val & ULL(~0x7FFF));
+        break;
+
+      case MISCREG_QUEUE_CPU_MONDO_HEAD:
+      case MISCREG_QUEUE_CPU_MONDO_TAIL:
+      case MISCREG_QUEUE_DEV_MONDO_HEAD:
+      case MISCREG_QUEUE_DEV_MONDO_TAIL:
+      case MISCREG_QUEUE_RES_ERROR_HEAD:
+      case MISCREG_QUEUE_RES_ERROR_TAIL:
+      case MISCREG_QUEUE_NRES_ERROR_HEAD:
+      case MISCREG_QUEUE_NRES_ERROR_TAIL:
+        setReg(miscReg, val);
+        tc->getCpuPtr()->checkInterrupts = true;
+        break;
+
+      case MISCREG_HSTICK_CMPR:
+        if (hSTickCompare == NULL)
+            hSTickCompare = new HSTickCompareEvent(this, tc);
+        setReg(miscReg, val);
+        if ((hstick_cmpr & ~mask(63)) && hSTickCompare->scheduled())
+            hSTickCompare->deschedule();
+        time = ((int64_t)(hstick_cmpr & mask(63)) - (int64_t)stick) -
+            tc->getCpuPtr()->instCount();
+        if (!(hstick_cmpr & ~mask(63)) && time > 0)
+            hSTickCompare->schedule(curTick + time * tc->getCpuPtr()->cycles(1));
+        DPRINTF(Timer, "writing to hsTICK compare register value %#X\n", val);
+        break;
+
+      case MISCREG_HPSTATE:
+        // T1000 spec says impl. dependent val must always be 1
+        setReg(miscReg, val | id);
+        break;
+      case MISCREG_HTSTATE:
+      case MISCREG_STRAND_STS_REG:
+        setReg(miscReg, val);
+        break;
+
+      default:
+        panic("Invalid write to FS misc register %s\n", getMiscRegName(miscReg));
     }
 }
 
@@ -144,7 +144,7 @@ MiscReg
 MiscRegFile::readFSRegWithEffect(int miscReg, ThreadContext * tc)
 {
     switch (miscReg) {
-      /* Privileged registers. */
+        /* Privileged registers. */
       case MISCREG_QUEUE_CPU_MONDO_HEAD:
       case MISCREG_QUEUE_CPU_MONDO_TAIL:
       case MISCREG_QUEUE_DEV_MONDO_HEAD:
@@ -174,12 +174,12 @@ MiscRegFile::readFSRegWithEffect(int miscReg, ThreadContext * tc)
     }
 }
 /*
-        In Niagra STICK==TICK so this isn't needed
-        case MISCREG_STICK:
-          SparcSystem *sys;
-          sys = dynamic_cast<SparcSystem*>(tc->getSystemPtr());
-          assert(sys != NULL);
-          return curTick/Clock::Int::ns - sys->sysTick | (stick & ~(mask(63)));
+  In Niagra STICK==TICK so this isn't needed
+  case MISCREG_STICK:
+  SparcSystem *sys;
+  sys = dynamic_cast<SparcSystem*>(tc->getSystemPtr());
+  assert(sys != NULL);
+  return curTick/Clock::Int::ns - sys->sysTick | (stick & ~(mask(63)));
 */
 
 
@@ -198,12 +198,13 @@ MiscRegFile::processSTickCompare(ThreadContext *tc)
     // more
     int ticks;
     ticks = ((int64_t)(stick_cmpr & mask(63)) - (int64_t)stick) -
-            tc->getCpuPtr()->instCount();
+        tc->getCpuPtr()->instCount();
     assert(ticks >= 0 && "stick compare missed interrupt cycle");
 
     if (ticks == 0) {
         DPRINTF(Timer, "STick compare cycle reached at %#x\n",
                 (stick_cmpr & mask(63)));
+        tc->getCpuPtr()->post_interrupt(soft_interrupt);
         tc->getCpuPtr()->checkInterrupts = true;
         softint |= ULL(1) << 16;
     } else
@@ -218,12 +219,13 @@ MiscRegFile::processHSTickCompare(ThreadContext *tc)
     // more
     int ticks;
     ticks = ((int64_t)(hstick_cmpr & mask(63)) - (int64_t)stick) -
-            tc->getCpuPtr()->instCount();
+        tc->getCpuPtr()->instCount();
     assert(ticks >= 0 && "hstick compare missed interrupt cycle");
 
     if (ticks == 0) {
         DPRINTF(Timer, "HSTick compare cycle reached at %#x\n",
                 (stick_cmpr & mask(63)));
+        tc->getCpuPtr()->post_interrupt(hstick_match);
         tc->getCpuPtr()->checkInterrupts = true;
         // Need to do something to cause interrupt to happen here !!! @todo
     } else
index 31604ad589c10f64c381cafd66f22144bbaca01c..b03bc19a572be59b85ee486a7282ebe9e4afc578 100644 (file)
@@ -362,6 +362,12 @@ BaseCPU::ProfileEvent::process()
     schedule(curTick + interval);
 }
 
+void
+BaseCPU::post_interrupt(int int_type)
+{
+    interrupts.post(int_type);
+}
+
 void
 BaseCPU::post_interrupt(int int_num, int index)
 {
index 8c6b079dae2cfdedacab58ff5ef6cc967ea21acc..89c7d9dda46143ea2e1f2b5995828a88a1df0a1a 100644 (file)
@@ -102,6 +102,7 @@ class BaseCPU : public MemObject
     TheISA::Interrupts interrupts;
 
   public:
+    virtual void post_interrupt(int int_type);
     virtual void post_interrupt(int int_num, int index);
     virtual void clear_interrupt(int int_num, int index);
     virtual void clear_interrupts();