Added error message when trying to use histogram
[riscv-isa-sim.git] / riscv / processor.cc
index 6368c8f18cc5ad3f3423894927c06043626cb6af..5b533910ac0c368e3555b0551a04c18ba653639a 100644 (file)
@@ -121,6 +121,12 @@ void processor_t::set_debug(bool value)
 void processor_t::set_histogram(bool value)
 {
   histogram_enabled = value;
+#ifndef RISCV_ENABLE_HISTOGRAM
+  if (value) {
+    fprintf(stderr, "PC Histogram support has not been properly enabled;");
+    fprintf(stderr, " please re-build the riscv-isa-run project using \"configure --enable-histogram\".\n");
+  }
+#endif
 }
 
 void processor_t::reset(bool value)
@@ -151,6 +157,9 @@ void processor_t::take_interrupt()
     if (interrupts & MIP_MSIP)
       raise_interrupt(IRQ_SOFT);
 
+    if (interrupts & MIP_MTIP)
+      raise_interrupt(IRQ_TIMER);
+
     if (state.fromhost != 0)
       raise_interrupt(IRQ_HOST);
   }
@@ -202,18 +211,10 @@ static reg_t execute_insn(processor_t* p, reg_t pc, insn_fetch_t fetch)
   return npc;
 }
 
-static void update_timer(state_t* state, size_t instret)
-{
-  uint64_t count0 = (uint64_t)(uint32_t)state->mtime;
-  state->mtime += instret;
-  uint64_t before = count0 - state->stimecmp;
-  if (int64_t(before ^ (before + instret)) < 0)
-    state->mip |= MIP_STIP;
-}
-
-static size_t next_timer(state_t* state)
+void processor_t::check_timer()
 {
-  return state->stimecmp - (uint32_t)state->mtime;
+  if (sim->rtc >= state.mtimecmp)
+    state.mip |= MIP_MTIP;
 }
 
 void processor_t::step(size_t n)
@@ -224,7 +225,6 @@ void processor_t::step(size_t n)
 
   if (unlikely(!run || !n))
     return;
-  n = std::min(n, next_timer(&state) | 1U);
 
   #define maybe_serialize() \
    if (unlikely(pc == PC_SERIALIZE)) { \
@@ -235,6 +235,7 @@ void processor_t::step(size_t n)
 
   try
   {
+    check_timer();
     take_interrupt();
 
     if (unlikely(debug))
@@ -280,7 +281,7 @@ void processor_t::step(size_t n)
     take_trap(t, pc);
   }
 
-  update_timer(&state, instret);
+  state.minstret += instret;
 
   // tail-recurse if we didn't execute as many instructions as we'd hoped
   if (instret < n)
@@ -371,29 +372,35 @@ void processor_t::set_csr(int which, reg_t val)
       break;
     case CSR_MTIME:
     case CSR_STIMEW:
-      state.mtime = val;
+      // this implementation ignores writes to MTIME
       break;
     case CSR_MTIMEH:
     case CSR_STIMEHW:
+      // this implementation ignores writes to MTIME
+      break;
+    case CSR_TIMEW:
+      val -= sim->rtc;
       if (xlen == 32)
-        state.mtime = (uint32_t)val | (state.mtime >> 32 << 32);
+        state.sutime_delta = (uint32_t)val | (state.sutime_delta >> 32 << 32);
       else
-        state.mtime = val;
+        state.sutime_delta = val;
+      break;
+    case CSR_TIMEHW:
+      val = ((val << 32) - sim->rtc) >> 32;
+      state.sutime_delta = (val << 32) | (uint32_t)state.sutime_delta;
       break;
     case CSR_CYCLEW:
-    case CSR_TIMEW:
     case CSR_INSTRETW:
-      val -= state.mtime;
+      val -= state.minstret;
       if (xlen == 32)
-        state.sutime_delta = (uint32_t)val | (state.sutime_delta >> 32 << 32);
+        state.suinstret_delta = (uint32_t)val | (state.suinstret_delta >> 32 << 32);
       else
-        state.sutime_delta = val;
+        state.suinstret_delta = val;
       break;
     case CSR_CYCLEHW:
-    case CSR_TIMEHW:
     case CSR_INSTRETHW:
-      val -= state.mtime;
-      state.sutime_delta = (val << 32) | (uint32_t)state.sutime_delta;
+      val = ((val << 32) - state.minstret) >> 32;
+      state.suinstret_delta = (val << 32) | (uint32_t)state.suinstret_delta;
       break;
     case CSR_MSTATUS: {
       if ((val ^ state.mstatus) & (MSTATUS_VM | MSTATUS_PRV | MSTATUS_PRV1 | MSTATUS_MPRV))
@@ -426,12 +433,12 @@ void processor_t::set_csr(int which, reg_t val)
       break;
     }
     case CSR_MIP: {
-      reg_t mask = MIP_SSIP | MIP_MSIP;
+      reg_t mask = MIP_SSIP | MIP_MSIP | MIP_STIP;
       state.mip = (state.mip & ~mask) | (val & mask);
       break;
     }
     case CSR_MIE: {
-      reg_t mask = MIP_SSIP | MIP_MSIP | MIP_STIP;
+      reg_t mask = MIP_SSIP | MIP_MSIP | MIP_STIP | MIP_MTIP;
       state.mie = (state.mie & ~mask) | (val & mask);
       break;
     }
@@ -457,16 +464,16 @@ void processor_t::set_csr(int which, reg_t val)
     }
     case CSR_SEPC: state.sepc = val; break;
     case CSR_STVEC: state.stvec = val & ~3; break;
-    case CSR_STIMECMP:
-      state.mip &= ~MIP_STIP;
-      state.stimecmp = val;
-      break;
     case CSR_SPTBR: state.sptbr = zext_xlen(val & -PGSIZE); break;
     case CSR_SSCRATCH: state.sscratch = val; break;
     case CSR_MEPC: state.mepc = val; break;
     case CSR_MSCRATCH: state.mscratch = val; break;
     case CSR_MCAUSE: state.mcause = val; break;
     case CSR_MBADADDR: state.mbadaddr = val; break;
+    case CSR_MTIMECMP:
+      state.mip &= ~MIP_MTIP;
+      state.mtimecmp = val;
+      break;
     case CSR_SEND_IPI: sim->send_ipi(val); break;
     case CSR_MTOHOST:
       if (state.tohost == 0)
@@ -496,29 +503,33 @@ reg_t processor_t::get_csr(int which)
         break;
       return (state.fflags << FSR_AEXC_SHIFT) | (state.frm << FSR_RD_SHIFT);
     case CSR_MTIME:
+    case CSR_STIME:
     case CSR_STIMEW:
-      return state.mtime;
+      return sim->rtc;
     case CSR_MTIMEH:
+    case CSR_STIMEH:
     case CSR_STIMEHW:
-      return state.mtime >> 32;
-    case CSR_CYCLE:
+      return sim->rtc >> 32;
     case CSR_TIME:
-    case CSR_INSTRET:
-    case CSR_STIME:
-    case CSR_CYCLEW:
     case CSR_TIMEW:
+      return sim->rtc + state.sutime_delta;
+    case CSR_CYCLE:
+    case CSR_CYCLEW:
+    case CSR_INSTRET:
     case CSR_INSTRETW:
-      return state.mtime + state.sutime_delta;
-    case CSR_CYCLEH:
+      return state.minstret + state.suinstret_delta;
     case CSR_TIMEH:
+    case CSR_TIMEHW:
+      if (xlen == 64)
+        break;
+      return (sim->rtc + state.sutime_delta) >> 32;
+    case CSR_CYCLEH:
     case CSR_INSTRETH:
-    case CSR_STIMEH:
     case CSR_CYCLEHW:
-    case CSR_TIMEHW:
     case CSR_INSTRETHW:
       if (xlen == 64)
         break;
-      return (state.mtime + state.sutime_delta) >> 32;
+      return (state.minstret + state.suinstret_delta) >> 32;
     case CSR_SSTATUS: {
       reg_t ss = 0;
       ss = set_field(ss, SSTATUS_IE, get_field(state.mstatus, MSTATUS_IE));
@@ -536,7 +547,6 @@ reg_t processor_t::get_csr(int which)
     case CSR_SEPC: return state.sepc;
     case CSR_SBADADDR: return state.sbadaddr;
     case CSR_STVEC: return state.stvec;
-    case CSR_STIMECMP: return state.stimecmp;
     case CSR_SCAUSE:
       if (max_xlen > xlen)
         return state.scause | ((state.scause >> (max_xlen-1)) << (xlen-1));
@@ -551,6 +561,7 @@ reg_t processor_t::get_csr(int which)
     case CSR_MSCRATCH: return state.mscratch;
     case CSR_MCAUSE: return state.mcause;
     case CSR_MBADADDR: return state.mbadaddr;
+    case CSR_MTIMECMP: return state.mtimecmp;
     case CSR_MCPUID: return cpuid;
     case CSR_MIMPID: return IMPL_ROCKET;
     case CSR_MHARTID: return id;