Compress log output of jump-to-self loops.
[riscv-isa-sim.git] / riscv / processor.cc
index 04d483c613459c6e70526cfe5ada567534dc498a..13aeaa4b85759390dc8df686cfb92e2845ddbc71 100644 (file)
@@ -7,7 +7,6 @@
 #include "sim.h"
 #include "mmu.h"
 #include "disasm.h"
-#include "gdbserver.h"
 #include <cinttypes>
 #include <cmath>
 #include <cstdlib>
@@ -22,7 +21,8 @@
 
 processor_t::processor_t(const char* isa, sim_t* sim, uint32_t id,
         bool halt_on_reset)
-  : debug(false), sim(sim), ext(NULL), id(id), halt_on_reset(halt_on_reset)
+  : debug(false), halt_request(false), sim(sim), ext(NULL), id(id),
+  halt_on_reset(halt_on_reset)
 {
   parse_isa_string(isa);
   register_base_instructions();
@@ -109,6 +109,8 @@ void processor_t::parse_isa_string(const char* str)
   // advertise support for supervisor and user modes
   isa |= 1L << ('s' - 'a');
   isa |= 1L << ('u' - 'a');
+
+  max_isa = isa;
 }
 
 void state_t::reset()
@@ -198,7 +200,7 @@ void processor_t::enter_debug_mode(uint8_t cause)
   state.dcsr.prv = state.prv;
   set_privilege(PRV_M);
   state.dpc = state.pc;
-  state.pc = DEBUG_ROM_START;
+  state.pc = debug_rom_entry();
 }
 
 void processor_t::take_trap(trap_t& t, reg_t epc)
@@ -211,6 +213,15 @@ void processor_t::take_trap(trap_t& t, reg_t epc)
           t.get_badaddr());
   }
 
+  if (state.dcsr.cause) {
+    if (t.cause() == CAUSE_BREAKPOINT) {
+      state.pc = debug_rom_entry();
+    } else {
+      state.pc = DEBUG_ROM_EXCEPTION;
+    }
+    return;
+  }
+
   if (t.cause() == CAUSE_BREAKPOINT && (
               (state.prv == PRV_M && state.dcsr.ebreakm) ||
               (state.prv == PRV_H && state.dcsr.ebreakh) ||
@@ -220,11 +231,6 @@ void processor_t::take_trap(trap_t& t, reg_t epc)
     return;
   }
 
-  if (state.dcsr.cause) {
-    state.pc = DEBUG_ROM_EXCEPTION;
-    return;
-  }
-
   // by default, trap to M-mode, unless delegated to S-mode
   reg_t bit = t.cause();
   reg_t deleg = state.medeleg;
@@ -264,9 +270,23 @@ void processor_t::take_trap(trap_t& t, reg_t epc)
 
 void processor_t::disasm(insn_t insn)
 {
+  static uint64_t last_pc = 1, last_bits;
+  static uint64_t executions = 1;
+
   uint64_t bits = insn.bits() & ((1ULL << (8 * insn_length(insn.bits()))) - 1);
-  fprintf(stderr, "core %3d: 0x%016" PRIx64 " (0x%08" PRIx64 ") %s\n",
-          id, state.pc, bits, disassembler->disassemble(insn).c_str());
+  if (last_pc != state.pc || last_bits != bits) {
+    if (executions != 1) {
+      fprintf(stderr, "core %3d: Executed %" PRIx64 " times\n", id, executions);
+    }
+
+    fprintf(stderr, "core %3d: 0x%016" PRIx64 " (0x%08" PRIx64 ") %s\n",
+            id, state.pc, bits, disassembler->disassemble(insn).c_str());
+    last_pc = state.pc;
+    last_bits = bits;
+    executions = 1;
+  } else {
+    executions++;
+  }
 }
 
 static bool validate_vm(int max_xlen, reg_t vm)
@@ -349,20 +369,32 @@ void processor_t::set_csr(int which, reg_t val)
       state.medeleg = (state.medeleg & ~mask) | (val & mask);
       break;
     }
+    case CSR_MINSTRET:
+    case CSR_MCYCLE:
+      if (xlen == 32)
+        state.minstret = (state.minstret >> 32 << 32) | (val & 0xffffffffU);
+      else
+        state.minstret = val;
+      break;
+    case CSR_MINSTRETH:
+    case CSR_MCYCLEH:
+      state.minstret = (val << 32) | (state.minstret << 32 >> 32);
+      break;
     case CSR_MUCOUNTEREN:
-      state.mucounteren = val & 7;
+      state.mucounteren = val;
       break;
     case CSR_MSCOUNTEREN:
-      state.mscounteren = val & 7;
+      state.mscounteren = val;
       break;
     case CSR_SSTATUS: {
       reg_t mask = SSTATUS_SIE | SSTATUS_SPIE | SSTATUS_SPP | SSTATUS_FS
                  | SSTATUS_XS | SSTATUS_PUM;
       return set_csr(CSR_MSTATUS, (state.mstatus & ~mask) | (val & mask));
     }
-    case CSR_SIP:
-      return set_csr(CSR_MIP,
-                     (state.mip & ~state.mideleg) | (val & state.mideleg));
+    case CSR_SIP: {
+      reg_t mask = MIP_SSIP & state.mideleg;
+      return set_csr(CSR_MIP, (state.mip & ~mask) | (val & mask));
+    }
     case CSR_SIE:
       return set_csr(CSR_MIE,
                      (state.mie & ~state.mideleg) | (val & state.mideleg));
@@ -381,12 +413,36 @@ void processor_t::set_csr(int which, reg_t val)
     case CSR_MSCRATCH: state.mscratch = val; break;
     case CSR_MCAUSE: state.mcause = val; break;
     case CSR_MBADADDR: state.mbadaddr = val; break;
-    case CSR_TSELECT: state.tselect = val; break;
+    case CSR_MISA: {
+      if (!(val & (1L << ('F' - 'A'))))
+        val &= ~(1L << ('D' - 'A'));
+
+      // allow MAFDC bits in MISA to be modified
+      reg_t mask = 0;
+      mask |= 1L << ('M' - 'A');
+      mask |= 1L << ('A' - 'A');
+      mask |= 1L << ('F' - 'A');
+      mask |= 1L << ('D' - 'A');
+      mask |= 1L << ('C' - 'A');
+      mask &= max_isa;
+
+      isa = (val & mask) | (isa & ~mask);
+      break;
+    }
+    case CSR_TSELECT:
+      if (val < state.num_triggers) {
+        state.tselect = val;
+      }
+      break;
     case CSR_TDATA1:
-      if (state.tselect < state.num_triggers) {
+      {
         mcontrol_t *mc = &state.mcontrol[state.tselect];
+        if (mc->dmode && !state.dcsr.cause) {
+          break;
+        }
         mc->dmode = get_field(val, MCONTROL_DMODE(xlen));
         mc->select = get_field(val, MCONTROL_SELECT);
+        mc->timing = get_field(val, MCONTROL_TIMING);
         mc->action = (mcontrol_action_t) get_field(val, MCONTROL_ACTION);
         mc->chain = get_field(val, MCONTROL_CHAIN);
         mc->match = (mcontrol_match_t) get_field(val, MCONTROL_MATCH);
@@ -398,12 +454,17 @@ void processor_t::set_csr(int which, reg_t val)
         mc->store = get_field(val, MCONTROL_STORE);
         mc->load = get_field(val, MCONTROL_LOAD);
         // Assume we're here because of csrw.
+        if (mc->execute)
+          mc->timing = 0;
         trigger_updated();
       }
       break;
     case CSR_TDATA2:
+      if (state.mcontrol[state.tselect].dmode && !state.dcsr.cause) {
+        break;
+      }
       if (state.tselect < state.num_triggers) {
-        state.tdata1[state.tselect] = val;
+        state.tdata2[state.tselect] = val;
       }
       break;
     case CSR_DCSR:
@@ -427,6 +488,23 @@ void processor_t::set_csr(int which, reg_t val)
 
 reg_t processor_t::get_csr(int which)
 {
+  reg_t ctr_en = state.prv == PRV_U ? state.mucounteren :
+                 state.prv == PRV_S ? state.mscounteren : -1U;
+  bool ctr_ok = (ctr_en >> (which & 31)) & 1;
+
+  if (ctr_ok) {
+    if (which >= CSR_HPMCOUNTER3 && which <= CSR_HPMCOUNTER31)
+      return 0;
+    if (xlen == 32 && which >= CSR_HPMCOUNTER3H && which <= CSR_HPMCOUNTER31H)
+      return 0;
+  }
+  if (which >= CSR_MHPMCOUNTER3 && which <= CSR_MHPMCOUNTER31)
+    return 0;
+  if (xlen == 32 && which >= CSR_MHPMCOUNTER3 && which <= CSR_MHPMCOUNTER31)
+    return 0;
+  if (which >= CSR_MHPMEVENT3 && which <= CSR_MHPMEVENT31)
+    return 0;
+
   switch (which)
   {
     case CSR_FFLAGS:
@@ -444,36 +522,21 @@ reg_t processor_t::get_csr(int which)
       if (!supports_extension('F'))
         break;
       return (state.fflags << FSR_AEXC_SHIFT) | (state.frm << FSR_RD_SHIFT);
-    case CSR_TIME:
     case CSR_INSTRET:
     case CSR_CYCLE:
-      if ((state.mucounteren >> (which & (xlen-1))) & 1)
-        return get_csr(which + (CSR_MCYCLE - CSR_CYCLE));
+      if (ctr_ok)
+        return state.minstret;
       break;
-    case CSR_STIME:
-    case CSR_SINSTRET:
-    case CSR_SCYCLE:
-      if ((state.mscounteren >> (which & (xlen-1))) & 1)
-        return get_csr(which + (CSR_MCYCLE - CSR_SCYCLE));
+    case CSR_MINSTRET:
+    case CSR_MCYCLE:
+      return state.minstret;
+    case CSR_MINSTRETH:
+    case CSR_MCYCLEH:
+      if (xlen == 32)
+        return state.minstret >> 32;
       break;
     case CSR_MUCOUNTEREN: return state.mucounteren;
     case CSR_MSCOUNTEREN: return state.mscounteren;
-    case CSR_MUCYCLE_DELTA: return 0;
-    case CSR_MUTIME_DELTA: return 0;
-    case CSR_MUINSTRET_DELTA: return 0;
-    case CSR_MSCYCLE_DELTA: return 0;
-    case CSR_MSTIME_DELTA: return 0;
-    case CSR_MSINSTRET_DELTA: return 0;
-    case CSR_MUCYCLE_DELTAH: if (xlen > 32) break; else return 0;
-    case CSR_MUTIME_DELTAH: if (xlen > 32) break; else return 0;
-    case CSR_MUINSTRET_DELTAH: if (xlen > 32) break; else return 0;
-    case CSR_MSCYCLE_DELTAH: if (xlen > 32) break; else return 0;
-    case CSR_MSTIME_DELTAH: if (xlen > 32) break; else return 0;
-    case CSR_MSINSTRET_DELTAH: if (xlen > 32) break; else return 0;
-    case CSR_MCYCLE: return state.minstret;
-    case CSR_MINSTRET: return state.minstret;
-    case CSR_MCYCLEH: if (xlen > 32) break; else return state.minstret >> 32;
-    case CSR_MINSTRETH: if (xlen > 32) break; else return state.minstret >> 32;
     case CSR_SSTATUS: {
       reg_t mask = SSTATUS_SIE | SSTATUS_SPIE | SSTATUS_SPP | SSTATUS_FS
                  | SSTATUS_XS | SSTATUS_PUM;
@@ -518,6 +581,7 @@ reg_t processor_t::get_csr(int which)
         v = set_field(v, MCONTROL_DMODE(xlen), mc->dmode);
         v = set_field(v, MCONTROL_MASKMAX(xlen), mc->maskmax);
         v = set_field(v, MCONTROL_SELECT, mc->select);
+        v = set_field(v, MCONTROL_TIMING, mc->timing);
         v = set_field(v, MCONTROL_ACTION, mc->action);
         v = set_field(v, MCONTROL_CHAIN, mc->chain);
         v = set_field(v, MCONTROL_MATCH, mc->match);
@@ -535,11 +599,12 @@ reg_t processor_t::get_csr(int which)
       break;
     case CSR_TDATA2:
       if (state.tselect < state.num_triggers) {
-        return state.tdata1[state.tselect];
+        return state.tdata2[state.tselect];
       } else {
         return 0;
       }
       break;
+    case CSR_TDATA3: return 0;
     case CSR_DCSR:
       {
         uint32_t v = 0;