Only break out of the simulator loop on WFI, not on CSR writes
authorAndrew Waterman <andrew@sifive.com>
Mon, 30 Apr 2018 22:06:52 +0000 (15:06 -0700)
committerAndrew Waterman <andrew@sifive.com>
Mon, 30 Apr 2018 22:06:52 +0000 (15:06 -0700)
Breaking out of the loop on WFI was intended to let other threads run
when the current thread has no work to do.  There's no advantage to doing
so on CSR writes, and the unintentional change in thread interleaving
broke some test programs that relied on short timer periods.

riscv/decode.h
riscv/execute.cc
riscv/insns/wfi.h

index 8fc8ada1b269cad40ecf04203a5fac245aec0584..9634f57ab6c634d2f90552387bb4936263d8313b 100644 (file)
@@ -211,11 +211,17 @@ private:
        STATE.pc = __npc; \
      } while(0)
 
+#define wfi() \
+  do { set_pc_and_serialize(npc); \
+       npc = PC_SERIALIZE_WFI; \
+     } while(0)
+
 #define serialize() set_pc_and_serialize(npc)
 
 /* Sentinel PC values to serialize simulator pipeline */
 #define PC_SERIALIZE_BEFORE 3
 #define PC_SERIALIZE_AFTER 5
+#define PC_SERIALIZE_WFI 7
 #define invalid_pc(pc) ((pc) & 1)
 
 /* Convenience wrappers to simplify softfloat code sequences */
index 9d1fb87ad2da6a8cccca13eb3f01e5ff61147ac4..d7e586dcc33a42e664a9eed195995154057ccd5c 100644 (file)
@@ -109,7 +109,8 @@ void processor_t::step(size_t n)
      if (unlikely(invalid_pc(pc))) { \
        switch (pc) { \
          case PC_SERIALIZE_BEFORE: state.serialized = true; break; \
-         case PC_SERIALIZE_AFTER: n = ++instret; break; \
+         case PC_SERIALIZE_AFTER: ++instret; break; \
+         case PC_SERIALIZE_WFI: n = ++instret; break; \
          default: abort(); \
        } \
        pc = state.pc; \
index 16de594408522bc52c89589bb899b6ac1a6e8a43..6504b78c608b0cf192df1bfd8592cb799389ff42 100644 (file)
@@ -1,2 +1,2 @@
 require_privilege(get_field(STATE.mstatus, MSTATUS_TW) ? PRV_M : PRV_S);
-set_pc_and_serialize(npc);
+wfi();