Browse Source

refactor disassembler, and add hwacha disassembler

mvp
Yunsup Lee 13 years ago
parent
commit
cb6cfc5f3a
  1. 1
      .gitignore
  2. 1
      hwacha/hwacha.cc
  3. 8
      hwacha/hwacha.h
  4. 2
      hwacha/hwacha.mk.in
  5. 200
      hwacha/hwacha_disasm.cc
  6. 17
      hwacha/insns/vf.h
  7. 123
      riscv/disasm.cc
  8. 55
      riscv/disasm.h
  9. 3
      riscv/extension.h
  10. 9
      riscv/interactive.cc
  11. 30
      riscv/processor.cc
  12. 11
      riscv/processor.h
  13. 2
      riscv/riscv-dis.cc
  14. 6
      riscv/rocc.cc
  15. 1
      riscv/rocc.h
  16. 17
      riscv/sim.cc
  17. 5
      riscv/sim.h

1
.gitignore

@ -1,2 +1,3 @@
build/
autom4te.cache/
.*.swp

1
hwacha/hwacha.cc

@ -1,5 +1,6 @@
#include "hwacha.h"
#include "hwacha_xcpt.h"
#include "mmu.h"
#include "trap.h"
void ct_state_t::reset()

8
hwacha/hwacha.h

@ -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; })

2
hwacha/hwacha.mk.in

@ -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) \

200
hwacha/hwacha_disasm.cc

@ -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;
}

17
hwacha/insns/vf.h

@ -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;
}
}

123
riscv/disasm.cc

@ -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++)

55
riscv/disasm.h

@ -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);
};

3
riscv/extension.h

@ -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; }

9
riscv/interactive.cc

@ -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);
}
}

30
riscv/processor.cc

@ -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;

11
riscv/processor.h

@ -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;

2
riscv/riscv-dis.cc

@ -15,7 +15,7 @@ using namespace std;
int main()
{
string s;
disassembler d;
disassembler_t d;
while (getline(cin, s))
{

6
riscv/rocc.cc

@ -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;
}

1
riscv/rocc.h

@ -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

17
riscv/sim.cc

@ -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);
}

5
riscv/sim.h

@ -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;

Loading…
Cancel
Save