revamp hwacha; now runs in physical mode
[riscv-isa-sim.git] / riscv / processor.cc
index 0510a3dd6f6f5bd80c332acb64eae1b07c59daec..652a17033aad9d78a2c748f87760ac841ba0f402 100644 (file)
@@ -1,6 +1,7 @@
 // See LICENSE for license details.
 
 #include "processor.h"
+#include "extension.h"
 #include "common.h"
 #include "config.h"
 #include "sim.h"
 #include <iostream>
 #include <assert.h>
 #include <limits.h>
+#include <stdexcept>
 
 processor_t::processor_t(sim_t* _sim, mmu_t* _mmu, uint32_t _id)
-  : sim(*_sim), mmu(*_mmu), id(_id), opcode_bits(0)
+  : sim(_sim), mmu(_mmu), ext(NULL), id(_id), opcode_bits(0)
 {
   reset(true);
-  mmu.set_processor(this);
+  mmu->set_processor(this);
 
-  #define DECLARE_INSN(name, match, mask) \
-    extern reg_t rv32_##name(processor_t*, insn_t, reg_t); \
-    extern reg_t rv64_##name(processor_t*, insn_t, reg_t); \
-    register_insn(match, mask, rv32_##name, rv64_##name);
+  #define DECLARE_INSN(name, match, mask) REGISTER_INSN(this, name, match, mask)
   #include "opcodes.h"
   #undef DECLARE_INSN
 }
@@ -66,7 +65,8 @@ void processor_t::reset(bool value)
     return;
   run = !value;
 
-  state.reset();
+  state.reset(); // reset the core
+  ext->reset(); // reset the extension
 }
 
 uint32_t processor_t::set_fsr(uint32_t val)
@@ -94,7 +94,7 @@ void processor_t::step(size_t n, bool noisy)
 
   size_t i = 0;
   reg_t npc = state.pc;
-  mmu_t& _mmu = mmu;
+  mmu_t* _mmu = mmu;
 
   try
   {
@@ -103,11 +103,27 @@ void processor_t::step(size_t n, bool noisy)
     // execute_insn fetches and executes one instruction
     #define execute_insn(noisy) \
       do { \
-        mmu_t::insn_fetch_t fetch = _mmu.load_insn(npc); \
-        if(noisy) disasm(fetch.insn, npc); \
-        npc = fetch.func(this, fetch.insn, npc); \
+        mmu_t::insn_fetch_t fetch = _mmu->load_insn(npc); \
+        if(noisy) disasm(fetch.insn.insn, npc); \
+        npc = fetch.func(this, fetch.insn.insn, npc); \
       } while(0)
 
+    
+    // special execute_insn  for commit log dumping
+#ifdef RISCV_ENABLE_COMMITLOG
+    //static disassembler disasmblr; 
+    #undef execute_insn 
+    #define execute_insn(noisy) \
+      do { \
+        mmu_t::insn_fetch_t fetch = _mmu->load_insn(npc); \
+        if(noisy) disasm(fetch.insn.insn, npc); \
+        bool in_spvr = state.sr & SR_S; \
+        if (!in_spvr) fprintf(stderr, "\n0x%016" PRIx64 " (0x%08" PRIx32 ") ", npc, fetch.insn.insn.bits()); \
+        /*if (!in_spvr) fprintf(stderr, "\n0x%016" PRIx64 " (0x%08" PRIx32 ") %s  ", npc, fetch.insn.insn.bits(), disasmblr.disassemble(fetch.insn.insn).c_str());*/ \
+        npc = fetch.func(this, fetch.insn.insn, npc); \
+      } while(0)
+#endif
+
     if(noisy) for( ; i < n; i++) // print out instructions as we go
       execute_insn(true);
     else 
@@ -142,20 +158,15 @@ void processor_t::step(size_t n, bool noisy)
 
 void processor_t::take_trap(reg_t pc, trap_t& t, bool noisy)
 {
-  if(noisy)
-  {
-    if ((sreg_t)t.cause() < 0)
-      fprintf(stderr, "core %3d: interrupt %d, epc 0x%016" PRIx64 "\n",
-              id, uint8_t(t.cause()), pc);
-    else
-      fprintf(stderr, "core %3d: trap %s, epc 0x%016" PRIx64 "\n",
-              id, t.name(), pc);
-  }
+  if (noisy)
+    fprintf(stderr, "core %3d: exception %s, epc 0x%016" PRIx64 "\n",
+            id, t.name(), pc);
 
   // switch to supervisor, set previous supervisor bit, disable interrupts
   set_pcr(PCR_SR, (((state.sr & ~SR_EI) | SR_S) & ~SR_PS & ~SR_PEI) |
                   ((state.sr & SR_S) ? SR_PS : 0) |
                   ((state.sr & SR_EI) ? SR_PEI : 0));
+
   yield_load_reservation();
   state.cause = t.cause();
   state.epc = pc;
@@ -174,8 +185,8 @@ void processor_t::disasm(insn_t insn, reg_t pc)
 {
   // the disassembler is stateless, so we share it
   static disassembler disasm;
-  fprintf(stderr, "core %3d: 0x%016" PRIx64 " (0x%08" PRIxFAST32 ") %s\n",
-          id, state.pc, insn.bits, disasm.disassemble(insn).c_str());
+  fprintf(stderr, "core %3d: 0x%016" PRIx64 " (0x%08" PRIx32 ") %s\n",
+          id, state.pc, insn.bits(), disasm.disassemble(insn).c_str());
 }
 
 reg_t processor_t::set_pcr(int which, reg_t val)
@@ -196,7 +207,7 @@ reg_t processor_t::set_pcr(int which, reg_t val)
       state.sr &= ~SR_EV;
 #endif
       state.sr &= ~SR_ZERO;
-      mmu.flush_tlb();
+      mmu->flush_tlb();
       break;
     case PCR_EPC:
       state.epc = val;
@@ -215,15 +226,15 @@ reg_t processor_t::set_pcr(int which, reg_t val)
       state.ptbr = val & ~(PGSIZE-1);
       break;
     case PCR_SEND_IPI:
-      sim.send_ipi(val);
+      sim->send_ipi(val);
       break;
     case PCR_CLR_IPI:
       set_interrupt(IRQ_IPI, val & 1);
       break;
-    case PCR_K0:
+    case PCR_SUP0:
       state.pcr_k0 = val;
       break;
-    case PCR_K1:
+    case PCR_SUP1:
       state.pcr_k1 = val;
       break;
     case PCR_TOHOST:
@@ -262,15 +273,15 @@ reg_t processor_t::get_pcr(int which)
     case PCR_ASID:
       return 0;
     case PCR_FATC:
-      mmu.flush_tlb();
+      mmu->flush_tlb();
       return 0;
     case PCR_HARTID:
       return id;
     case PCR_IMPL:
       return 1;
-    case PCR_K0:
+    case PCR_SUP0:
       return state.pcr_k0;
-    case PCR_K1:
+    case PCR_SUP1:
       return state.pcr_k1;
     case PCR_TOHOST:
       return state.tohost;
@@ -289,7 +300,7 @@ void processor_t::set_interrupt(int which, bool on)
     state.sr &= ~mask;
 }
 
-static reg_t illegal_instruction(processor_t* p, insn_t insn, reg_t pc)
+reg_t illegal_instruction(processor_t* p, insn_t insn, reg_t pc)
 {
   throw trap_illegal_instruction();
 }
@@ -298,21 +309,21 @@ insn_func_t processor_t::decode_insn(insn_t insn)
 {
   bool rv64 = (state.sr & SR_S) ? (state.sr & SR_S64) : (state.sr & SR_U64);
 
-  auto key = insn.bits & ((1L << opcode_bits)-1);
+  auto key = insn.bits() & ((1L << opcode_bits)-1);
   for (auto it = opcode_map.find(key); it != opcode_map.end() && it->first == key; ++it)
-    if ((insn.bits & it->second.mask) == it->second.match)
+    if ((insn.bits() & it->second.mask) == it->second.match)
       return rv64 ? it->second.rv64 : it->second.rv32;
 
   return &illegal_instruction;
 }
 
-void processor_t::register_insn(uint32_t match, uint32_t mask, insn_func_t rv32, insn_func_t rv64)
+void processor_t::register_insn(insn_desc_t desc)
 {
-  assert(mask & 1);
-  if (opcode_bits == 0 || (mask & ((1L << opcode_bits)-1)) != ((1L << opcode_bits)-1))
+  assert(desc.mask & 1);
+  if (opcode_bits == 0 || (desc.mask & ((1L << opcode_bits)-1)) != ((1L << opcode_bits)-1))
   {
     unsigned x = 0;
-    while ((mask & ((1L << (x+1))-1)) == ((1L << (x+1))-1) &&
+    while ((desc.mask & ((1L << (x+1))-1)) == ((1L << (x+1))-1) &&
            (opcode_bits == 0 || x <= opcode_bits))
       x++;
     opcode_bits = x;
@@ -323,6 +334,15 @@ void processor_t::register_insn(uint32_t match, uint32_t mask, insn_func_t rv32,
     opcode_map = new_map;
   }
 
-  opcode_map.insert(std::make_pair(match & ((1L<<opcode_bits)-1),
-    (opcode_map_entry_t){match, mask, rv32, rv64}));
+  opcode_map.insert(std::make_pair(desc.match & ((1L<<opcode_bits)-1), desc));
+}
+
+void processor_t::register_extension(extension_t* x)
+{
+  for (auto insn : x->get_instructions())
+    register_insn(insn);
+  if (ext != NULL)
+    throw std::logic_error("only one extension may be registered");
+  ext = x;
+  x->set_processor(this);
 }