expose pending interrupts in status register
authorAndrew Waterman <waterman@cs.berkeley.edu>
Tue, 26 Mar 2013 03:06:10 +0000 (20:06 -0700)
committerAndrew Waterman <waterman@cs.berkeley.edu>
Tue, 26 Mar 2013 03:06:10 +0000 (20:06 -0700)
riscv/pcr.h
riscv/processor.cc
riscv/processor.h

index 7659a97df5bafd5380165d5241bebd2ac9e7a375..33939d8aa8bf8ec6dd8f5df22a53b5fc71f76825 100644 (file)
 #define SR_S64   0x00000080
 #define SR_VM    0x00000100
 #define SR_IM    0x00FF0000
-#define SR_ZERO  ~(SR_ET|SR_EF|SR_EV|SR_EC|SR_PS|SR_S|SR_U64|SR_S64|SR_VM|SR_IM)
+#define SR_IP    0xFF000000
+#define SR_ZERO  ~(SR_ET|SR_EF|SR_EV|SR_EC|SR_PS|SR_S|SR_U64|SR_S64|SR_VM|SR_IM|SR_IP)
 #define SR_IM_SHIFT 16
+#define SR_IP_SHIFT 24
 
 #define PCR_SR       0
 #define PCR_EPC      1
@@ -35,6 +37,7 @@
 #define PCR_FROMHOST 31
 
 #define IRQ_IPI   5
+#define IRQ_HOST  6
 #define IRQ_TIMER 7
 
 #define CAUSE_MISALIGNED_FETCH 0
index 38f2965b00858a099cd7431d75f28f01dfd8ed44..b90bdd684810ac371feb7ed05a25d19dbcc21911 100644 (file)
@@ -97,7 +97,7 @@ void processor_t::setvl(int vlapp)
 
 void processor_t::take_interrupt()
 {
-  uint32_t interrupts = interrupts_pending;
+  uint32_t interrupts = (sr & SR_IP) >> SR_IP_SHIFT;
   interrupts &= (sr & SR_IM) >> SR_IM_SHIFT;
 
   if(interrupts && (sr & SR_ET))
@@ -165,7 +165,7 @@ void processor_t::step(size_t n, bool noisy)
   uint32_t old_count = count;
   count += i;
   if(old_count < compare && uint64_t(old_count) + i >= compare)
-    interrupts_pending |= 1 << IRQ_TIMER;
+    set_interrupt(IRQ_TIMER, true);
 }
 
 void processor_t::take_trap(reg_t t, bool noisy)
@@ -237,7 +237,7 @@ void processor_t::set_pcr(int which, reg_t val)
       count = val;
       break;
     case PCR_COMPARE:
-      interrupts_pending &= ~(1 << IRQ_TIMER);
+      set_interrupt(IRQ_TIMER, false);
       compare = val;
       break;
     case PCR_PTBR:
@@ -247,10 +247,7 @@ void processor_t::set_pcr(int which, reg_t val)
       sim.send_ipi(val);
       break;
     case PCR_CLR_IPI:
-      if (val & 1)
-        interrupts_pending |= (1 << IRQ_IPI);
-      else
-        interrupts_pending &= ~(1 << IRQ_IPI);
+      set_interrupt(IRQ_IPI, val & 1);
       break;
     case PCR_K0:
       pcr_k0 = val;
@@ -267,6 +264,7 @@ void processor_t::set_pcr(int which, reg_t val)
         tohost = val;
       break;
     case PCR_FROMHOST:
+      set_interrupt(IRQ_HOST, val != 0);
       fromhost = val;
       break;
   }
@@ -309,3 +307,12 @@ reg_t processor_t::get_pcr(int which)
   }
   return -1;
 }
+
+void processor_t::set_interrupt(int which, bool on)
+{
+  uint32_t mask = (1 << (which + SR_IP_SHIFT)) & SR_IP;
+  if (on)
+    sr |= mask;
+  else
+    sr &= ~mask;
+}
index d086760ee04b19f29523c4a76f5cdcf9afaf805d..826fb96b1d67b425fe1383cf5c95e784568db6db 100644 (file)
@@ -25,6 +25,7 @@ public:
   void deliver_ipi(); // register an interprocessor interrupt
   bool running() { return run; }
   void set_pcr(int which, reg_t val);
+  void set_interrupt(int which, bool on);
   reg_t get_pcr(int which);
   mmu_t* get_mmu() { return &mmu; }
 
@@ -49,7 +50,6 @@ private:
   reg_t cause;
   reg_t tohost;
   reg_t fromhost;
-  uint32_t interrupts_pending;
   uint32_t id;
   uint32_t sr; // only modify the status register using set_pcr()
   uint32_t fsr;