refactor disassembler, and add hwacha disassembler
authorYunsup Lee <yunsup@cs.berkeley.edu>
Sat, 19 Oct 2013 00:34:54 +0000 (17:34 -0700)
committerYunsup Lee <yunsup@cs.berkeley.edu>
Sat, 19 Oct 2013 00:34:54 +0000 (17:34 -0700)
17 files changed:
.gitignore
hwacha/hwacha.cc
hwacha/hwacha.h
hwacha/hwacha.mk.in
hwacha/hwacha_disasm.cc [new file with mode: 0644]
hwacha/insns/vf.h
riscv/disasm.cc
riscv/disasm.h
riscv/extension.h
riscv/interactive.cc
riscv/processor.cc
riscv/processor.h
riscv/riscv-dis.cc
riscv/rocc.cc
riscv/rocc.h
riscv/sim.cc
riscv/sim.h

index 12a75cdd71e5aa672035b1701c034f6caa2c56de..031e691660dec0b202e2ad42470a27462f0fa292 100644 (file)
@@ -1,2 +1,3 @@
 build/
 autom4te.cache/
+.*.swp
index 0d6b906dd74708021889d721244acbda1df5533a..192d30848cbfb02f44fa970bf989ae7036d45ef1 100644 (file)
@@ -1,5 +1,6 @@
 #include "hwacha.h"
 #include "hwacha_xcpt.h"
+#include "mmu.h"
 #include "trap.h"
 
 void ct_state_t::reset()
index e48bf529cd2488c5fe8173800e637d4cfe9f3e7a..7504e577b3b79f433f0b354af4b92defceb46bd1 100644 (file)
@@ -30,9 +30,12 @@ struct ut_state_t
 class hwacha_t : public extension_t
 {
 public:
+  hwacha_t() : debug(false) {}
   std::vector<insn_desc_t> get_instructions();
+  std::vector<disasm_insn_t*> get_disasms();
   const char* name() { return "hwacha"; }
   void reset();
+  void set_debug(bool value) { debug = value; }
 
   ct_state_t* get_ct_state() { return &ct_state; }
   ut_state_t* get_ut_state(int idx) { return &ut_state[idx]; }
@@ -40,10 +43,15 @@ public:
   void take_exception(reg_t, reg_t);
   void clear_exception() { clear_interrupt(); }
 
+  bool get_debug() { return debug; }
+  disassembler_t* get_ut_disassembler() { return &ut_disassembler; }
+
 private:
   static const int max_uts = 2048;
   ct_state_t ct_state;
   ut_state_t ut_state[max_uts];
+  disassembler_t ut_disassembler;
+  bool debug;
 };
 
 REGISTER_EXTENSION(hwacha, []() { return new hwacha_t; })
index cf698d3b1976f4abc14038f5e12c9df79ccc276c..bf16b6fba823d4c7bdc2cf82533023dec121379f 100644 (file)
@@ -9,6 +9,7 @@ hwacha_install_prog_srcs = \
 
 hwacha_hdrs = \
        hwacha.h \
+       hwacha_xcpt.h \
        decode_hwacha.h \
        decode_hwacha_ut.h \
        opcodes_hwacha.h \
@@ -16,6 +17,7 @@ hwacha_hdrs = \
 
 hwacha_srcs = \
        hwacha.cc \
+       hwacha_disasm.cc \
        $(hwacha_gen_srcs) \
        $(hwacha_ut_gen_srcs) \
 
diff --git a/hwacha/hwacha_disasm.cc b/hwacha/hwacha_disasm.cc
new file mode 100644 (file)
index 0000000..46ec080
--- /dev/null
@@ -0,0 +1,200 @@
+#include "hwacha.h"
+
+static const char* xpr[] = {
+  "zero", "ra", "s0", "s1",  "s2",  "s3",  "s4",  "s5",
+  "s6",   "s7", "s8", "s9", "s10", "s11",  "sp",  "tp",
+  "v0",   "v1", "a0", "a1",  "a2",  "a3",  "a4",  "a5",
+  "a6",   "a7", "t0", "t1",  "t2",  "t3",  "t4",  "gp"
+};
+
+static const char* fpr[] = {
+  "fs0", "fs1",  "fs2",  "fs3",  "fs4",  "fs5",  "fs6",  "fs7",
+  "fs8", "fs9", "fs10", "fs11", "fs12", "fs13", "fs14", "fs15",
+  "fv0", "fv1", "fa0",   "fa1",  "fa2",  "fa3",  "fa4",  "fa5",
+  "fa6", "fa7", "ft0",   "ft1",  "ft2",  "ft3",  "ft4",  "ft5"
+};
+
+static const char* vxpr[] = {
+  "vx0",  "vx1",  "vx2",  "vx3",  "vx4",  "vx5",  "vx6",  "vx7",
+  "vx8",  "vx9",  "vx10", "vx11", "vx12", "vx13", "vx14", "vx15",
+  "vx16", "vx17", "vx18", "vx19", "vx20", "vx21", "vx22", "vx23",
+  "vx24", "vx25", "vx26", "vx27", "vx28", "vx29", "vx30", "vx31"
+};
+
+static const char* vfpr[] = {
+  "vf0",  "vf1",  "vf2",  "vf3",  "vf4",  "vf5",  "vf6",  "vf7",
+  "vf8",  "vf9",  "vf10", "vf11", "vf12", "vf13", "vf14", "vf15",
+  "vf16", "vf17", "vf18", "vf19", "vf20", "vf21", "vf22", "vf23",
+  "vf24", "vf25", "vf26", "vf27", "vf28", "vf29", "vf30", "vf31"
+};
+
+struct : public arg_t {
+  std::string to_string(insn_t insn) const {
+    return xpr[insn.rs1()];
+  }
+} xrs1;
+
+struct : public arg_t {
+  std::string to_string(insn_t insn) const {
+    return xpr[insn.rs2()];
+  }
+} xrs2;
+
+struct : public arg_t {
+  std::string to_string(insn_t insn) const {
+    return xpr[insn.rd()];
+  }
+} xrd;
+
+struct : public arg_t {
+  std::string to_string(insn_t insn) const {
+    return fpr[insn.rd()];
+  }
+} frd;
+
+struct : public arg_t {
+  std::string to_string(insn_t insn) const {
+    return fpr[insn.rs1()];
+  }
+} frs1;
+
+struct : public arg_t {
+  std::string to_string(insn_t insn) const {
+    return fpr[insn.rs2()];
+  }
+} frs2;
+
+struct : public arg_t {
+  std::string to_string(insn_t insn) const {
+    return fpr[insn.rs3()];
+  }
+} frs3;
+
+struct : public arg_t {
+  std::string to_string(insn_t insn) const {
+    return vxpr[insn.rd()];
+  }
+} vxrd;
+
+struct : public arg_t {
+  std::string to_string(insn_t insn) const {
+    return vxpr[insn.rs1()];
+  }
+} vxrs1;
+
+struct : public arg_t {
+  std::string to_string(insn_t insn) const {
+    return vfpr[insn.rd()];
+  }
+} vfrd;
+
+struct : public arg_t {
+  std::string to_string(insn_t insn) const {
+    return vfpr[insn.rs1()];
+  }
+} vfrs1;
+
+struct : public arg_t {
+  std::string to_string(insn_t insn) const {
+    return std::to_string(insn.i_imm() & 0x3f);
+  }
+} nxregs;
+
+struct : public arg_t {
+  std::string to_string(insn_t insn) const {
+    return std::to_string((insn.i_imm() >> 6) & 0x3f);
+  }
+} nfregs;
+
+struct : public arg_t {
+  std::string to_string(insn_t insn) const {
+    return std::to_string((int)insn.s_imm()) + '(' + xpr[insn.rs1()] + ')';
+  }
+} vf_addr;
+
+std::vector<disasm_insn_t*> hwacha_t::get_disasms()
+{
+  std::vector<disasm_insn_t*> insns;
+
+  #define DECLARE_INSN(code, match, mask) \
+   const uint32_t match_##code = match; \
+   const uint32_t mask_##code = mask;
+  #include "opcodes_hwacha.h"
+  #undef DECLARE_INSN
+
+  #define DISASM_INSN(name, code, extra, ...) \
+    insns.push_back(new disasm_insn_t(name, match_##code, mask_##code | (extra), __VA_ARGS__));
+
+  DISASM_INSN("vsetcfg", vsetcfg, 0, {&xrs1, &nxregs, &nfregs});
+  DISASM_INSN("vsetvl", vsetvl, 0, {&xrd, &xrs1});
+  DISASM_INSN("vgetcfg", vgetcfg, 0, {&xrd});
+  DISASM_INSN("vgetvl", vgetvl, 0, {&xrd});
+
+  DISASM_INSN("vmvv", vmvv, 0, {&vxrd, &vxrs1});
+  DISASM_INSN("vmsv", vmsv, 0, {&vxrd, &xrs1});
+  DISASM_INSN("vf", vf, 0, {&vf_addr});
+
+  DISASM_INSN("vxcptcause", vxcptcause, 0, {&xrd});
+  DISASM_INSN("vxcptaux", vxcptaux, 0, {&xrd});
+  DISASM_INSN("vxcptsave", vxcptsave, 0, {&xrs1});
+  DISASM_INSN("vxcptrestore", vxcptrestore, 0, {&xrs1});
+  DISASM_INSN("vxcptkill", vxcptkill, 0, {});
+
+  const uint32_t mask_vseglen = 0x7UL << 29;
+
+  #define DISASM_VMEM_INSN(name1, name2, code, ...) \
+    DISASM_INSN(name1, code, mask_vseglen, __VA_ARGS__) \
+    DISASM_INSN(name2, code, 0, __VA_ARGS__) \
+
+  DISASM_VMEM_INSN("vld", "vlsegd", vlsegd, {&vxrd, &xrs1});
+  DISASM_VMEM_INSN("vlw", "vlsegw", vlsegw, {&vxrd, &xrs1});
+  DISASM_VMEM_INSN("vlwu", "vlsegwu", vlsegwu, {&vxrd, &xrs1});
+  DISASM_VMEM_INSN("vlh", "vlsegh", vlsegh, {&vxrd, &xrs1});
+  DISASM_VMEM_INSN("vlhu", "vlseghu", vlseghu, {&vxrd, &xrs1});
+  DISASM_VMEM_INSN("vlb", "vlsegb", vlsegb, {&vxrd, &xrs1});
+  DISASM_VMEM_INSN("vlbu", "vlsegbu", vlsegbu, {&vxrd, &xrs1});
+  DISASM_VMEM_INSN("vfld", "vflsegd", vflsegd, {&vfrd, &xrs1});
+  DISASM_VMEM_INSN("vflw", "vflsegw", vflsegw, {&vfrd, &xrs1});
+
+  DISASM_VMEM_INSN("vlstd", "vlsegstd", vlsegstd, {&vxrd, &xrs1, &xrs2});
+  DISASM_VMEM_INSN("vlstw", "vlsegstw", vlsegstw, {&vxrd, &xrs1, &xrs2});
+  DISASM_VMEM_INSN("vlstwu", "vlsegstwu", vlsegstwu, {&vxrd, &xrs1, &xrs2});
+  DISASM_VMEM_INSN("vlsth", "vlsegsth", vlsegsth, {&vxrd, &xrs1, &xrs2});
+  DISASM_VMEM_INSN("vlsthu", "vlsegsthu", vlsegsthu, {&vxrd, &xrs1, &xrs2});
+  DISASM_VMEM_INSN("vlstb", "vlsegstb", vlsegstb, {&vxrd, &xrs1, &xrs2});
+  DISASM_VMEM_INSN("vlstbu", "vlsegstbu", vlsegstbu, {&vxrd, &xrs1, &xrs2});
+  DISASM_VMEM_INSN("vflstd", "vflsegstd", vflsegstd, {&vfrd, &xrs1, &xrs2});
+  DISASM_VMEM_INSN("vflstw", "vflsegstw", vflsegstw, {&vfrd, &xrs1, &xrs2});
+
+  DISASM_VMEM_INSN("vsd", "vssegd", vssegd, {&vxrd, &xrs1});
+  DISASM_VMEM_INSN("vsw", "vssegw", vssegw, {&vxrd, &xrs1});
+  DISASM_VMEM_INSN("vsh", "vssegh", vssegh, {&vxrd, &xrs1});
+  DISASM_VMEM_INSN("vsb", "vssegb", vssegb, {&vxrd, &xrs1});
+  DISASM_VMEM_INSN("vfsd", "vfssegd", vfssegd, {&vfrd, &xrs1});
+  DISASM_VMEM_INSN("vfsw", "vfssegw", vfssegw, {&vfrd, &xrs1});
+
+  DISASM_VMEM_INSN("vsstd", "vssegstd", vssegstd, {&vxrd, &xrs1, &xrs2});
+  DISASM_VMEM_INSN("vsstw", "vssegstw", vssegstw, {&vxrd, &xrs1, &xrs2});
+  DISASM_VMEM_INSN("vssth", "vssegsth", vssegsth, {&vxrd, &xrs1, &xrs2});
+  DISASM_VMEM_INSN("vsstb", "vssegstb", vssegstb, {&vxrd, &xrs1, &xrs2});
+  DISASM_VMEM_INSN("vfsstd", "vfssegstd", vfssegstd, {&vfrd, &xrs1, &xrs2});
+  DISASM_VMEM_INSN("vfsstw", "vfssegstw", vfssegstw, {&vfrd, &xrs1, &xrs2});
+
+  #define DECLARE_INSN(code, match, mask) \
+   const uint32_t match_##code = match; \
+   const uint32_t mask_##code = mask;
+  #include "opcodes_hwacha_ut.h"
+  #undef DECLARE_INSN
+
+  #define DISASM_UT_INSN(name, code, extra, ...) \
+    ut_disassembler.add_insn(new disasm_insn_t(name, match_##code, mask_##code | (extra), __VA_ARGS__));
+
+  DISASM_UT_INSN("stop", ut_stop, 0, {});
+  DISASM_UT_INSN("utidx", ut_utidx, 0, {&xrd});
+  DISASM_UT_INSN("movz", ut_movz, 0, {&xrd, &xrs1, &xrs2});
+  DISASM_UT_INSN("movn", ut_movn, 0, {&xrd, &xrs1, &xrs2});
+  DISASM_UT_INSN("fmovz", ut_fmovz, 0, {&frd, &xrs1, &frs2});
+  DISASM_UT_INSN("fmovn", ut_fmovn, 0, {&frd, &xrs1, &frs2});
+
+  return insns;
+}
index 7bd1973edac9af95b1b52e42444adddd46b13d1a..fafb8b913de75927d18a07c4e09317c40cad2550 100644 (file)
@@ -5,11 +5,12 @@ if (VL) {
       h->get_ut_state(i)->run = true;
   }
 
+vf_loop:
+
   if (VF_PC & 3)
     h->take_exception(HWACHA_CAUSE_VF_MISALIGNED_FETCH, VF_PC);
 
-  mmu_t::insn_fetch_t ut_fetch = p->get_mmu()->load_insn(VF_PC);
-  insn_t ut_insn = ut_fetch.insn.insn;
+  insn_t ut_insn = p->get_mmu()->load_insn(VF_PC).insn.insn;
 
   bool matched = false;
 
@@ -25,7 +26,13 @@ if (VL) {
   if (!matched)
     h->take_exception(HWACHA_CAUSE_VF_ILLEGAL_INSTRUCTION, VF_PC);
 
-  // if vf is still running, rewind pc so that it will execute again
-  if (h->vf_active())
-    npc = pc;
+  if (!h->get_debug()) {
+    if (h->vf_active())
+      goto vf_loop;
+  } else {
+    fprintf(stderr, "vf block: 0x%016" PRIx64 " (0x%08" PRIx32 ") %s\n",
+      VF_PC, ut_insn.bits(), h->get_ut_disassembler()->disassemble(ut_insn).c_str());
+    if (h->vf_active())
+      npc = pc;
+  }
 }
index caf4ff4956b16a85182d0e1d4f59c99ef9afa1cc..436aea36f74b71f96b29ec07fb79cd517e4dd5e5 100644 (file)
@@ -6,14 +6,6 @@
 #include <cstdarg>
 #include <sstream>
 #include <stdlib.h>
-using namespace std;
-
-class arg_t
-{
- public:
-  virtual string to_string(insn_t val) const = 0;
-  virtual ~arg_t() {}
-};
 
 static const char* xpr[] = {
   "zero", "ra", "s0", "s1",  "s2",  "s3",  "s4",  "s5",
@@ -29,35 +21,21 @@ static const char* fpr[] = {
   "fa6", "fa7", "ft0",   "ft1",  "ft2",  "ft3",  "ft4",  "ft5"
 };
 
-static const char* vxpr[] = {
-  "vx0",  "vx1",  "vx2",  "vx3",  "vx4",  "vx5",  "vx6",  "vx7",
-  "vx8",  "vx9",  "vx10", "vx11", "vx12", "vx13", "vx14", "vx15",
-  "vx16", "vx17", "vx18", "vx19", "vx20", "vx21", "vx22", "vx23",
-  "vx24", "vx25", "vx26", "vx27", "vx28", "vx29", "vx30", "vx31"
-};
-
-static const char* vfpr[] = {
-  "vf0",  "vf1",  "vf2",  "vf3",  "vf4",  "vf5",  "vf6",  "vf7",
-  "vf8",  "vf9",  "vf10", "vf11", "vf12", "vf13", "vf14", "vf15",
-  "vf16", "vf17", "vf18", "vf19", "vf20", "vf21", "vf22", "vf23",
-  "vf24", "vf25", "vf26", "vf27", "vf28", "vf29", "vf30", "vf31"
-};
-
 struct : public arg_t {
-  string to_string(insn_t insn) const {
-    return ::to_string((int)insn.i_imm()) + '(' + xpr[insn.rs1()] + ')';
+  std::string to_string(insn_t insn) const {
+    return std::to_string((int)insn.i_imm()) + '(' + xpr[insn.rs1()] + ')';
   }
 } load_address;
 
 struct : public arg_t {
-  string to_string(insn_t insn) const {
-    return ::to_string((int)insn.s_imm()) + '(' + xpr[insn.rs1()] + ')';
+  std::string to_string(insn_t insn) const {
+    return std::to_string((int)insn.s_imm()) + '(' + xpr[insn.rs1()] + ')';
   }
 } store_address;
 
 struct : public arg_t {
-  string to_string(insn_t insn) const {
-    return string("0(") + xpr[insn.rs1()] + ')';
+  std::string to_string(insn_t insn) const {
+    return std::string("0(") + xpr[insn.rs1()] + ')';
   }
 } amo_address;
 
@@ -105,49 +83,13 @@ struct : public arg_t {
 
 struct : public arg_t {
   std::string to_string(insn_t insn) const {
-    return vxpr[insn.rd()];
-  }
-} vxrd;
-
-struct : public arg_t {
-  std::string to_string(insn_t insn) const {
-    return vxpr[insn.rs1()];
-  }
-} vxrs1;
-
-struct : public arg_t {
-  std::string to_string(insn_t insn) const {
-    return vfpr[insn.rd()];
-  }
-} vfrd;
-
-struct : public arg_t {
-  std::string to_string(insn_t insn) const {
-    return vfpr[insn.rs1()];
-  }
-} vfrs1;
-
-struct : public arg_t {
-  std::string to_string(insn_t insn) const {
-    return ::to_string(insn.i_imm() & 0x3f);
-  }
-} nxregs;
-
-struct : public arg_t {
-  std::string to_string(insn_t insn) const {
-    return ::to_string((insn.i_imm() >> 6) & 0x3f);
-  }
-} nfregs;
-
-struct : public arg_t {
-  std::string to_string(insn_t insn) const {
-    return string("pcr") + xpr[insn.rs1()];
+    return std::string("pcr") + xpr[insn.rs1()];
   }
 } pcr;
 
 struct : public arg_t {
   std::string to_string(insn_t insn) const {
-    return ::to_string((int)insn.i_imm());
+    return std::to_string((int)insn.i_imm());
   }
 } imm;
 
@@ -179,52 +121,13 @@ struct : public arg_t {
   }
 } jump_target;
 
-class disasm_insn_t
-{
- public:
-  disasm_insn_t(const char* name, uint32_t match, uint32_t mask,
-                const std::vector<const arg_t*>& args)
-    : match(match), mask(mask), args(args), name(name) {}
-
-  bool operator == (insn_t insn) const
-  {
-    return (insn.bits() & mask) == match;
-  }
-
-  std::string to_string(insn_t insn) const
-  {
-    std::stringstream s;
-    int len;
-    for (len = 0; name[len]; len++)
-      s << (name[len] == '_' ? '.' : name[len]);
-
-    if (args.size())
-    {
-      s << std::string(std::max(1, 8 - len), ' ');
-      for (size_t i = 0; i < args.size()-1; i++)
-        s << args[i]->to_string(insn) << ", ";
-      s << args[args.size()-1]->to_string(insn);
-    }
-    return s.str();
-  }
-
-  uint32_t get_match() const { return match; }
-  uint32_t get_mask() const { return mask; }
-
- private:
-  uint32_t match;
-  uint32_t mask;
-  std::vector<const arg_t*> args;
-  const char* name;
-};
-
-std::string disassembler::disassemble(insn_t insn)
+std::string disassembler_t::disassemble(insn_t insn)
 {
   const disasm_insn_t* disasm_insn = lookup(insn);
   return disasm_insn ? disasm_insn->to_string(insn) : "unknown";
 }
 
-disassembler::disassembler()
+disassembler_t::disassembler_t()
 {
   const uint32_t mask_rd = 0x1fUL << 7;
   const uint32_t match_rd_ra = 1UL << 7;
@@ -463,7 +366,7 @@ disassembler::disassembler()
   #undef DECLARE_INSN
 }
 
-const disasm_insn_t* disassembler::lookup(insn_t insn)
+const disasm_insn_t* disassembler_t::lookup(insn_t insn)
 {
   size_t idx = insn.bits() % HASH_SIZE;
   for (size_t j = 0; j < chain[idx].size(); j++)
@@ -478,7 +381,7 @@ const disasm_insn_t* disassembler::lookup(insn_t insn)
   return NULL;
 }
 
-void disassembler::add_insn(disasm_insn_t* insn)
+void disassembler_t::add_insn(disasm_insn_t* insn)
 {
   size_t idx = HASH_SIZE;
   if (insn->get_mask() % HASH_SIZE == HASH_SIZE - 1)
@@ -486,7 +389,7 @@ void disassembler::add_insn(disasm_insn_t* insn)
   chain[idx].push_back(insn);
 }
 
-disassembler::~disassembler()
+disassembler_t::~disassembler_t()
 {
   for (size_t i = 0; i < HASH_SIZE+1; i++)
     for (size_t j = 0; j < chain[i].size(); j++)
index ee6d9190920cd433beb1b9e4ad7c8835e559a7f1..b5aa6debb1da8c69676f7efcefca5f8dd091a4de 100644 (file)
@@ -5,20 +5,65 @@
 
 #include "decode.h"
 #include <string>
+#include <sstream>
 #include <vector>
 
-struct disasm_insn_t;
+class arg_t
+{
+ public:
+  virtual std::string to_string(insn_t val) const = 0;
+  virtual ~arg_t() {}
+};
 
-class disassembler
+class disasm_insn_t
 {
  public:
-  disassembler();
-  ~disassembler();
+  disasm_insn_t(const char* name, uint32_t match, uint32_t mask,
+                const std::vector<const arg_t*>& args)
+    : match(match), mask(mask), args(args), name(name) {}
+
+  bool operator == (insn_t insn) const
+  {
+    return (insn.bits() & mask) == match;
+  }
+
+  std::string to_string(insn_t insn) const
+  {
+    std::stringstream s;
+    int len;
+    for (len = 0; name[len]; len++)
+      s << (name[len] == '_' ? '.' : name[len]);
+
+    if (args.size())
+    {
+      s << std::string(std::max(1, 8 - len), ' ');
+      for (size_t i = 0; i < args.size()-1; i++)
+        s << args[i]->to_string(insn) << ", ";
+      s << args[args.size()-1]->to_string(insn);
+    }
+    return s.str();
+  }
+
+  uint32_t get_match() const { return match; }
+  uint32_t get_mask() const { return mask; }
+
+ private:
+  uint32_t match;
+  uint32_t mask;
+  std::vector<const arg_t*> args;
+  const char* name;
+};
+
+class disassembler_t
+{
+ public:
+  disassembler_t();
+  ~disassembler_t();
   std::string disassemble(insn_t insn);
+  void add_insn(disasm_insn_t* insn);
  private:
   static const int HASH_SIZE = 256;
   std::vector<const disasm_insn_t*> chain[HASH_SIZE+1];
-  void add_insn(disasm_insn_t* insn);
   const disasm_insn_t* lookup(insn_t insn);
 };
 
index da42db98ed9616dac25f326b72592c83dcf8cedb..cce8345121f61a9f2fe554d0f284b810977236f5 100644 (file)
@@ -2,6 +2,7 @@
 #define _RISCV_COPROCESSOR_H
 
 #include "processor.h"
+#include "disasm.h"
 #include <map>
 #include <string>
 #include <vector>
@@ -11,8 +12,10 @@ class extension_t
 {
  public:
   virtual std::vector<insn_desc_t> get_instructions() = 0;
+  virtual std::vector<disasm_insn_t*> get_disasms() = 0;
   virtual const char* name() = 0;
   virtual void reset() {};
+  virtual void set_debug(bool value) {};
   virtual ~extension_t();
 
   void set_processor(processor_t* _p) { p = _p; }
index a1b7dd05cfc341dc054142c20913bc06056de4c5..ad38ace4cd15dcd6724e37c069f16a8469dad8f5 100644 (file)
@@ -56,7 +56,8 @@ void sim_t::interactive()
 
     if (!(ss >> cmd))
     {
-      step(1, true);
+      set_procs_debug(true);
+      step(1);
       continue;
     }
 
@@ -101,8 +102,9 @@ void sim_t::interactive_run(const std::string& cmd, const std::vector<std::strin
 {
   size_t steps = args.size() ? atoll(args[0].c_str()) : -1;
   ctrlc_pressed = false;
+  set_procs_debug(noisy);
   for (size_t i = 0; i < steps && !ctrlc_pressed; i++)
-    step(1, noisy);
+    step(1);
 }
 
 void sim_t::interactive_quit(const std::string& cmd, const std::vector<std::string>& args)
@@ -269,6 +271,7 @@ void sim_t::interactive_until(const std::string& cmd, const std::vector<std::str
     }
     catch (trap_t t) {}
 
-    step(1, false);
+    set_procs_debug(false);
+    step(1);
   }
 }
index 77a81b3cce66c625cc0f225e119d09159a095b2c..ac5c1f7520410472ddcf4139f7ef4fac68c6c823 100644 (file)
@@ -15,7 +15,7 @@
 #include <stdexcept>
 
 processor_t::processor_t(sim_t* _sim, mmu_t* _mmu, uint32_t _id)
-  : sim(_sim), mmu(_mmu), ext(NULL), id(_id), opcode_bits(0)
+  : sim(_sim), mmu(_mmu), ext(NULL), id(_id), debug(false), opcode_bits(0)
 {
   reset(true);
   mmu->set_processor(this);
@@ -59,6 +59,13 @@ void state_t::reset()
   load_reservation = -1;
 }
 
+void processor_t::set_debug(bool value)
+{
+  debug = value;
+  if (ext)
+    ext->set_debug(value);
+}
+
 void processor_t::reset(bool value)
 {
   if (run == !value)
@@ -88,7 +95,7 @@ void processor_t::take_interrupt()
         throw trap_t((1ULL << ((state.sr & SR_S64) ? 63 : 31)) + i);
 }
 
-void processor_t::step(size_t n, bool noisy)
+void processor_t::step(size_t n)
 {
   if(!run)
     return;
@@ -105,7 +112,7 @@ void processor_t::step(size_t n, bool noisy)
     #define execute_insn(noisy) \
       do { \
         mmu_t::insn_fetch_t fetch = _mmu->load_insn(npc); \
-        if(noisy) disasm(fetch.insn.insn, npc); \
+        if(noisy) disasm(fetch.insn.insn); \
         npc = fetch.func(this, fetch.insn.insn, npc); \
       } while(0)
 
@@ -117,7 +124,7 @@ void processor_t::step(size_t n, bool noisy)
     #define execute_insn(noisy) \
       do { \
         mmu_t::insn_fetch_t fetch = _mmu->load_insn(npc); \
-        if(noisy) disasm(fetch.insn.insn, npc); \
+        if(noisy) disasm(fetch.insn.insn); \
         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());*/ \
@@ -125,7 +132,7 @@ void processor_t::step(size_t n, bool noisy)
       } while(0)
 #endif
 
-    if(noisy) for( ; i < n; i++) // print out instructions as we go
+    if(debug) for( ; i < n; i++) // print out instructions as we go
       execute_insn(true);
     else 
     {
@@ -145,7 +152,7 @@ void processor_t::step(size_t n, bool noisy)
   }
   catch(trap_t& t)
   {
-    take_trap(npc, t, noisy);
+    take_trap(npc, t);
   }
 
   state.cycle += i;
@@ -157,9 +164,9 @@ void processor_t::step(size_t n, bool noisy)
     set_interrupt(IRQ_TIMER, true);
 }
 
-void processor_t::take_trap(reg_t pc, trap_t& t, bool noisy)
+void processor_t::take_trap(reg_t pc, trap_t& t)
 {
-  if (noisy)
+  if (debug)
     fprintf(stderr, "core %3d: exception %s, epc 0x%016" PRIx64 "\n",
             id, t.name(), pc);
 
@@ -182,12 +189,11 @@ void processor_t::deliver_ipi()
     set_pcr(PCR_CLR_IPI, 1);
 }
 
-void processor_t::disasm(insn_t insn, reg_t pc)
+void processor_t::disasm(insn_t insn)
 {
   // the disassembler is stateless, so we share it
-  static disassembler disasm;
   fprintf(stderr, "core %3d: 0x%016" PRIx64 " (0x%08" PRIx32 ") %s\n",
-          id, state.pc, insn.bits(), disasm.disassemble(insn).c_str());
+          id, state.pc, insn.bits(), disassembler.disassemble(insn).c_str());
 }
 
 reg_t processor_t::set_pcr(int which, reg_t val)
@@ -342,6 +348,8 @@ void processor_t::register_extension(extension_t* x)
 {
   for (auto insn : x->get_instructions())
     register_insn(insn);
+  for (auto disasm_insn : x->get_disasms())
+    disassembler.add_insn(disasm_insn);
   if (ext != NULL)
     throw std::logic_error("only one extension may be registered");
   ext = x;
index 6b007f24e263de5b6a4406d741bd4d3eaee64e43..0256bd829cde2ad54594dc323f46debba25b4276 100644 (file)
@@ -1,9 +1,9 @@
 // See LICENSE for license details.
-
 #ifndef _RISCV_PROCESSOR_H
 #define _RISCV_PROCESSOR_H
 
 #include "decode.h"
+#include "disasm.h"
 #include <cstring>
 #include "config.h"
 #include <map>
@@ -59,8 +59,9 @@ public:
   processor_t(sim_t* _sim, mmu_t* _mmu, uint32_t _id);
   ~processor_t();
 
+  void set_debug(bool value);
   void reset(bool value);
-  void step(size_t n, bool noisy); // run for n cycles
+  void step(size_t n); // run for n cycles
   void deliver_ipi(); // register an interprocessor interrupt
   bool running() { return run; }
   reg_t set_pcr(int which, reg_t val);
@@ -80,16 +81,18 @@ private:
   sim_t* sim;
   mmu_t* mmu; // main memory is always accessed via the mmu
   extension_t* ext;
+  disassembler_t disassembler;
   state_t state;
   uint32_t id;
   bool run; // !reset
+  bool debug;
 
   unsigned opcode_bits;
   std::multimap<uint32_t, insn_desc_t> opcode_map;
 
   void take_interrupt(); // take a trap if any interrupts are pending
-  void take_trap(reg_t pc, trap_t& t, bool noisy); // take an exception
-  void disasm(insn_t insn, reg_t pc); // disassemble and print an instruction
+  void take_trap(reg_t pc, trap_t& t); // take an exception
+  void disasm(insn_t insn); // disassemble and print an instruction
 
   friend class sim_t;
   friend class mmu_t;
index 62d522e32080e2dcf1b05c6c30f16ab9f9429383..fdeb69feb58240f89684c6b1fe64de0ec53ea45d 100644 (file)
@@ -15,7 +15,7 @@ using namespace std;
 int main()
 {
   string s;
-  disassembler d;
+  disassembler_t d;
 
   while (getline(cin, s))
   {
index b14831939e1f50ff21405c90e0c83d852ca0238e..7988c011e20ce9d1b1b27f0b53ba0c9d2bf2e972 100644 (file)
@@ -36,3 +36,9 @@ std::vector<insn_desc_t> rocc_t::get_instructions()
   insns.push_back((insn_desc_t){0x7b, 0x7f, &::illegal_instruction, c3});
   return insns;
 }
+
+std::vector<disasm_insn_t*> rocc_t::get_disasms()
+{
+  std::vector<disasm_insn_t*> insns;
+  return insns;
+}
index e4148ec1509b7706d37db140a3d44797ae6d1c00..63d074d41c084ef58402152a926656e38121815f 100644 (file)
@@ -29,6 +29,7 @@ class rocc_t : public extension_t
   virtual reg_t custom2(rocc_insn_t insn, reg_t xs1, reg_t xs2);
   virtual reg_t custom3(rocc_insn_t insn, reg_t xs1, reg_t xs2);
   std::vector<insn_desc_t> get_instructions();
+  std::vector<disasm_insn_t*> get_disasms();
 };
 
 #endif
index a4a1c172498e1d7bd279bf803c9664582b137c39..4d61555d0b6a8a440812a4ed4ce6453534df6e44 100644 (file)
@@ -79,16 +79,16 @@ void sim_t::run()
     if (debug || ctrlc_pressed)
       interactive();
     else
-      step(INTERLEAVE, false);
+      step(INTERLEAVE);
   }
 }
 
-void sim_t::step(size_t n, bool noisy)
+void sim_t::step(size_t n)
 {
   for (size_t i = 0, steps = 0; i < n; i += steps)
   {
     steps = std::min(n - i, INTERLEAVE - current_step);
-    procs[current_proc]->step(steps, noisy);
+    procs[current_proc]->step(steps);
 
     current_step += steps;
     if (current_step == INTERLEAVE)
@@ -117,3 +117,14 @@ void sim_t::stop()
   while (htif->tick())
     ;
 }
+
+void sim_t::set_debug(bool value)
+{
+  debug = value;
+}
+
+void sim_t::set_procs_debug(bool value)
+{
+  for (size_t i=0; i< procs.size(); i++)
+    procs[i]->set_debug(value);
+}
index bcb7c1c9c7361abfc0cce39a6f2748d827bfd150..e827087ebd784729f3775af4378b91dd879d42e5 100644 (file)
@@ -22,7 +22,8 @@ public:
   void run();
   bool running();
   void stop();
-  void set_debug(bool value) { debug = value; }
+  void set_debug(bool value);
+  void set_procs_debug(bool value);
 
   // deliver an IPI to a specific processor
   void send_ipi(reg_t who);
@@ -41,7 +42,7 @@ private:
   mmu_t* debug_mmu;  // debug port into main memory
   std::vector<processor_t*> procs;
 
-  void step(size_t n, bool noisy); // step through simulation
+  void step(size_t n); // step through simulation
   static const size_t INTERLEAVE = 5000;
   size_t current_step;
   size_t current_proc;