riscv

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README

commit 0d4b70e1e805f3cc6c85846f43cabdfcc31b8a36
parent f9d029a85313d1a909a73dcdb2ef9079cee7998a
Author: Brian Swetland <swetland@frotz.net>
Date:   Mon, 21 Oct 2019 17:32:58 -0700

rvsim: pass some tests

- better tracing of register and memory writes
- fix an unwanted fall-through
- support writing a dump so riscv-compliance can use rvsim
- passing 14 of 55 tests

Diffstat:
Mriscv.h | 2++
Mrvdis.c | 18++++++++++++++----
Mrvsim.c | 116++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---------------------
3 files changed, 101 insertions(+), 35 deletions(-)

diff --git a/riscv.h b/riscv.h @@ -102,3 +102,5 @@ static inline uint32_t get_fn7(uint32_t ins) { #define F3_BGEU 0b111 void rvdis(uint32_t pc, uint32_t ins, char *out); +const char* rvregname(uint32_t n); + diff --git a/rvdis.c b/rvdis.c @@ -19,20 +19,30 @@ static char *append_u32(char *buf, int32_t n) { return buf + sprintf(buf, "0x%x", n); } -static const char* regname[32] = { -#if 0 +static const char* regname_plain[32] = { "x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15", "x16", "x17", "x18", "x19", "x20", "x21", "x22", "x23", "x24", "x25", "x26", "x27", "x28", "x29", "x30", "x31", -#else +}; +static const char* regname_fancy[32] = { "zero", "ra", "sp", "gp", "tp", "t0", "t1", "t2", "s0", "s1", "a0", "a1", "a2", "a3", "a4", "a5", "a6", "a7", "s2", "s3", "s4", "s5", "s6", "s7", "s8", "s9", "s10", "s11", "t3", "t4", "t5", "t6", -#endif }; +static const char** regname = regname_plain; + +const char* rvregname(uint32_t n) { + if (n < 32) { + return regname[n]; + } else { + return "??"; + } +} + + typedef struct { uint32_t mask; uint32_t bits; diff --git a/rvsim.c b/rvsim.c @@ -11,13 +11,6 @@ #include "riscv.h" -static const char* regname[32] = { - "zero", "ra", "sp", "gp", "tp", "t0", "t1", "t2", - "s0", "s1", "a0", "a1", "a2", "a3", "a4", "a5", - "a6", "a7", "s2", "s3", "s4", "s5", "s6", "s7", - "s8", "s9", "s10", "s11", "t3", "t4", "t5", "t6", -}; - uint8_t memory[32768]; int load_image(const char* fn, uint8_t* ptr, size_t sz) { @@ -81,24 +74,30 @@ static inline void wreg(rvstate_t* s, uint32_t n, uint32_t v) { #define RdR1() rreg(s, get_r1(ins)) #define RdR2() rreg(s, get_r2(ins)) +#define RdRd() rreg(s, get_rd(ins)) #define WrRd(v) wreg(s, get_rd(ins), v) #define DO_DISASM 1 #define DO_TRACK 1 +#define trace_reg(fmt...) printf(fmt...) + +#define trace_reg_wr(v) do {\ + printf(" (%s = %08x)\n", \ + rvregname(get_rd(ins)), v); \ + } while (0) + +#define trace_mem_wr(a, v) do {\ + printf(" ([%08x] = %08x)\n", a, v);\ + } while (0) + void rvsim(rvstate_t* s) { -#if DO_TRACK - uint32_t last[32]; -#endif uint32_t pc = s->pc; uint32_t next = pc; uint32_t ccount = 0; uint32_t ins; for (;;) { pc = next; -#if DO_TRACK - memcpy(last, &s->x, sizeof(last)); -#endif ins = rd32(pc); #if DO_DISASM char dis[128]; @@ -108,15 +107,19 @@ void rvsim(rvstate_t* s) { next = pc + 4; ccount++; switch (get_oc(ins)) { - case OC_LOAD: + case OC_LOAD: { + uint32_t v; switch (get_fn3(ins)) { case F3_LW: - WrRd(rd32(RdR1() + get_ii(ins))); + v = rd32(RdR1() + get_ii(ins)); break; default: goto inval; } + WrRd(v); + trace_reg_wr(v); break; + } case OC_CUSTOM_0: goto inval; case OC_MISC_MEM: @@ -126,7 +129,7 @@ void rvsim(rvstate_t* s) { case OC_OP_IMM: { uint32_t a = RdR1(); uint32_t b = get_ii(ins); - uint32_t n; + uint32_t n = 0xe1e1e1e1; switch (get_fn3(ins)) { case F3_ADDI: n = a + b; break; case F3_SLLI: @@ -147,19 +150,28 @@ void rvsim(rvstate_t* s) { case F3_ANDI: n = a & b; break; } WrRd(n); + trace_reg_wr(n); break; } - case OC_AUIPC: - WrRd(pc + get_iu(ins)); + case OC_AUIPC: { + uint32_t v = pc + get_iu(ins); + WrRd(v); + trace_reg_wr(v); break; - case OC_STORE: + } + case OC_STORE: { + uint32_t a = RdR1() + get_is(ins); + uint32_t v = RdR2(); switch (get_fn3(ins)) { case F3_SW: - wr32(RdR2() + get_is(ins), RdR1()); + wr32(a, v); + trace_mem_wr(a, v); break; default: goto inval; } + break; + } case OC_OP: { uint32_t a = RdR1(); uint32_t b = RdR1(); @@ -179,11 +191,15 @@ void rvsim(rvstate_t* s) { default: goto inval; } WrRd(n); + trace_reg_wr(n); break; } - case OC_LUI: - WrRd(get_iu(ins)); + case OC_LUI: { + uint32_t v = get_iu(ins); + WrRd(v); + trace_reg_wr(v); break; + } case OC_BRANCH: { uint32_t a = RdR1(); uint32_t b = RdR2(); @@ -204,10 +220,12 @@ void rvsim(rvstate_t* s) { case OC_JALR: if (get_fn3(ins) != 0) goto inval; WrRd(next); + trace_reg_wr(next); next = RdR1() + (get_ii(ins) << 1); break; case OC_JAL: WrRd(next); + trace_reg_wr(next); next = pc + get_ij(ins); break; case OC_SYSTEM: @@ -216,24 +234,60 @@ void rvsim(rvstate_t* s) { inval: return; } -#if DO_TRACK - for (unsigned n = 1; n < 32; n++) { - if (s->x[n] != last[n]) { - printf(" (%s = 0x%08x)\n", - regname[n], s->x[n]); - } - } -#endif } } int main(int argc, char** argv) { + const char* fn = NULL; + const char* dumpfn = NULL; + uint32_t dumpfrom = 0, dumpto = 0; + while (argc > 1) { + argc--; + argv++; + if (argv[0][0] != '-') { + if (fn != NULL) { + fprintf(stderr, "error: multiple inputs\n"); + return -1; + } + fn = argv[0]; + continue; + } + if (!strncmp(argv[0],"-dump=",6)) { + dumpfn = argv[0] + 6; + continue; + } + if (!strncmp(argv[0],"-from=",6)) { + dumpfrom = strtoul(argv[0] + 6, NULL, 16); + continue; + } + if (!strncmp(argv[0],"-to=",4)) { + dumpto = strtoul(argv[0] + 4, NULL, 16); + continue; + } + fprintf(stderr, "error: unknown argument: %s\n", argv[0]); + return -1; + } rvstate_t s; - if (load_image("out/hello.bin", memory, sizeof(memory)) < 0) return -1; + if (load_image(fn, memory, sizeof(memory)) < 0) { + fprintf(stderr, "error: failed to load '%s'\n", fn); + return -1; + } memset(&s, 0, sizeof(s)); s.pc = 0x80000000; rvsim(&s); + if (dumpfn && (dumpto > dumpfrom)) { + FILE* fp; + if ((fp = fopen(dumpfn, "w")) == NULL) { + fprintf(stderr, "error: failed to open '%s' to write\n", dumpfn); + return -1; + } + for (uint32_t n = dumpfrom; n < dumpto; n += 4) { + uint32_t v = rd32(n); + fprintf(fp, "%08x\n", v); + } + fclose(fp); + } return 0; }