Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 24 additions & 1 deletion src/emulate.c
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,25 @@ static void rv_trap_default_handler(riscv_t *rv)
static void __trap_handler(riscv_t *rv);
#endif /* RV32_HAS(SYSTEM) */

#if RV32_HAS(ARCH_TEST)
/* Check if the write is to tohost and halt emulation if so.
* Compliance tests write to tohost and then enter an infinite loop.
* The emulator should detect this and exit gracefully.
*/
static inline void check_tohost_write(riscv_t *rv,
uint32_t addr,
uint32_t value)
{
if (rv->tohost_addr && addr == rv->tohost_addr && value != 0) {
/* Non-zero write to tohost means test wants to exit */
rv->halt = true;
/* Extract exit code from tohost value (value >> 1) */
vm_attr_t *attr = PRIV(rv);
attr->exit_code = (value >> 1);
}
}
#endif /* RV32_HAS(ARCH_TEST) */

/* wrap load/store and insn misaligned handler
* @mask_or_pc: mask for load/store and pc for insn misaligned handler.
* @type: type of misaligned handler
Expand Down Expand Up @@ -466,7 +485,11 @@ static bool do_fuse3(riscv_t *rv,
for (int i = 0; i < ir->imm2; i++) {
uint32_t addr = rv->X[fuse[i].rs1] + fuse[i].imm;
RV_EXC_MISALIGN_HANDLER(3, STORE, false, 1);
rv->io.mem_write_w(rv, addr, rv->X[fuse[i].rs2]);
uint32_t value = rv->X[fuse[i].rs2];
rv->io.mem_write_w(rv, addr, value);
#if RV32_HAS(ARCH_TEST)
check_tohost_write(rv, addr, value);
#endif
}
PC += ir->imm2 * 4;
if (unlikely(RVOP_NO_NEXT(ir))) {
Expand Down
19 changes: 19 additions & 0 deletions src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -314,6 +314,25 @@ int main(int argc, char **args)
}
rv_log_info("RISC-V emulator is created and ready to run");

#if RV32_HAS(ARCH_TEST)
/* Extract tohost/fromhost addresses for arch-test mode */
if (opt_arch_test && opt_prog_name) {
elf_t *elf = elf_new();
if (elf && elf_open(elf, opt_prog_name)) {
const struct Elf32_Sym *sym;
if ((sym = elf_get_symbol(elf, "tohost"))) {
rv_set_tohost_addr(rv, sym->st_value);
rv_log_info("Found tohost at 0x%08x", sym->st_value);
}
if ((sym = elf_get_symbol(elf, "fromhost"))) {
rv_set_fromhost_addr(rv, sym->st_value);
rv_log_info("Found fromhost at 0x%08x", sym->st_value);
}
}
elf_delete(elf);
}
#endif

#if defined(__EMSCRIPTEN__)
disable_run_button();
#endif
Expand Down
12 changes: 12 additions & 0 deletions src/riscv.c
Original file line number Diff line number Diff line change
Expand Up @@ -886,6 +886,18 @@ bool rv_has_halted(riscv_t *rv)
return rv->halt;
}

#if RV32_HAS(ARCH_TEST)
void rv_set_tohost_addr(riscv_t *rv, uint32_t addr)
{
rv->tohost_addr = addr;
}

void rv_set_fromhost_addr(riscv_t *rv, uint32_t addr)
{
rv->fromhost_addr = addr;
}
#endif

void rv_delete(riscv_t *rv)
{
assert(rv);
Expand Down
6 changes: 6 additions & 0 deletions src/riscv.h
Original file line number Diff line number Diff line change
Expand Up @@ -440,6 +440,12 @@ void rv_halt(riscv_t *rv);
/* return the halt state */
bool rv_has_halted(riscv_t *rv);

#if RV32_HAS(ARCH_TEST)
/* Set tohost/fromhost addresses for architectural testing */
void rv_set_tohost_addr(riscv_t *rv, uint32_t addr);
void rv_set_fromhost_addr(riscv_t *rv, uint32_t addr);
#endif

enum {
/* run and trace instructions and print them out during emulation */
RV_RUN_TRACE = 1,
Expand Down
6 changes: 6 additions & 0 deletions src/riscv_private.h
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,12 @@ struct riscv_internal {
*/
uint32_t last_csr_sepc;
#endif

#if RV32_HAS(ARCH_TEST)
/* RISC-V architectural test support: tohost/fromhost addresses */
uint32_t tohost_addr;
uint32_t fromhost_addr;
#endif
};

/* sign extend a 16 bit value */
Expand Down
81 changes: 72 additions & 9 deletions src/rv32_template.c
Original file line number Diff line number Diff line change
Expand Up @@ -705,7 +705,11 @@ RVOP(
sb,
{
const uint32_t addr = rv->X[ir->rs1] + ir->imm;
rv->io.mem_write_b(rv, addr, rv->X[ir->rs2]);
const uint32_t value = rv->X[ir->rs2];
rv->io.mem_write_b(rv, addr, value);
#if RV32_HAS(ARCH_TEST)
check_tohost_write(rv, addr, value);
#endif
},
GEN({
mem;
Expand All @@ -722,7 +726,11 @@ RVOP(
{
const uint32_t addr = rv->X[ir->rs1] + ir->imm;
RV_EXC_MISALIGN_HANDLER(1, STORE, false, 1);
rv->io.mem_write_s(rv, addr, rv->X[ir->rs2]);
const uint32_t value = rv->X[ir->rs2];
rv->io.mem_write_s(rv, addr, value);
#if RV32_HAS(ARCH_TEST)
check_tohost_write(rv, addr, value);
#endif
},
GEN({
mem;
Expand All @@ -739,7 +747,11 @@ RVOP(
{
const uint32_t addr = rv->X[ir->rs1] + ir->imm;
RV_EXC_MISALIGN_HANDLER(3, STORE, false, 1);
rv->io.mem_write_w(rv, addr, rv->X[ir->rs2]);
const uint32_t value = rv->X[ir->rs2];
rv->io.mem_write_w(rv, addr, value);
#if RV32_HAS(ARCH_TEST)
check_tohost_write(rv, addr, value);
#endif
},
GEN({
mem;
Expand Down Expand Up @@ -1501,8 +1513,12 @@ RVOP(
*/
const uint32_t addr = rv->X[ir->rs1];
RV_EXC_MISALIGN_HANDLER(3, STORE, false, 1);
rv->io.mem_write_w(rv, addr, rv->X[ir->rs2]);
const uint32_t value = rv->X[ir->rs2];
rv->io.mem_write_w(rv, addr, value);
rv->X[ir->rd] = 0;
#if RV32_HAS(ARCH_TEST)
check_tohost_write(rv, addr, value);
#endif
},
GEN({
assert; /* FIXME: Implement */
Expand All @@ -1519,6 +1535,9 @@ RVOP(
if (ir->rd)
rv->X[ir->rd] = value1;
rv->io.mem_write_w(rv, addr, value2);
#if RV32_HAS(ARCH_TEST)
check_tohost_write(rv, addr, value2);
#endif
},
GEN({
assert; /* FIXME: Implement */
Expand All @@ -1536,6 +1555,9 @@ RVOP(
rv->X[ir->rd] = value1;
const uint32_t res = value1 + value2;
rv->io.mem_write_w(rv, addr, res);
#if RV32_HAS(ARCH_TEST)
check_tohost_write(rv, addr, res);
#endif
},
GEN({
assert; /* FIXME: Implement */
Expand All @@ -1553,6 +1575,9 @@ RVOP(
rv->X[ir->rd] = value1;
const uint32_t res = value1 ^ value2;
rv->io.mem_write_w(rv, addr, res);
#if RV32_HAS(ARCH_TEST)
check_tohost_write(rv, addr, res);
#endif
},
GEN({
assert; /* FIXME: Implement */
Expand All @@ -1570,6 +1595,9 @@ RVOP(
rv->X[ir->rd] = value1;
const uint32_t res = value1 & value2;
rv->io.mem_write_w(rv, addr, res);
#if RV32_HAS(ARCH_TEST)
check_tohost_write(rv, addr, res);
#endif
},
GEN({
assert; /* FIXME: Implement */
Expand All @@ -1587,6 +1615,9 @@ RVOP(
rv->X[ir->rd] = value1;
const uint32_t res = value1 | value2;
rv->io.mem_write_w(rv, addr, res);
#if RV32_HAS(ARCH_TEST)
check_tohost_write(rv, addr, res);
#endif
},
GEN({
assert; /* FIXME: Implement */
Expand All @@ -1606,6 +1637,9 @@ RVOP(
const int32_t b = value2;
const uint32_t res = a < b ? value1 : value2;
rv->io.mem_write_w(rv, addr, res);
#if RV32_HAS(ARCH_TEST)
check_tohost_write(rv, addr, res);
#endif
},
GEN({
assert; /* FIXME: Implement */
Expand All @@ -1625,6 +1659,9 @@ RVOP(
const int32_t b = value2;
const uint32_t res = a > b ? value1 : value2;
rv->io.mem_write_w(rv, addr, res);
#if RV32_HAS(ARCH_TEST)
check_tohost_write(rv, addr, res);
#endif
},
GEN({
assert; /* FIXME: Implement */
Expand All @@ -1642,6 +1679,9 @@ RVOP(
rv->X[ir->rd] = value1;
const uint32_t ures = value1 < value2 ? value1 : value2;
rv->io.mem_write_w(rv, addr, ures);
#if RV32_HAS(ARCH_TEST)
check_tohost_write(rv, addr, ures);
#endif
},
GEN({
assert; /* FIXME: Implement */
Expand All @@ -1659,6 +1699,9 @@ RVOP(
rv->X[ir->rd] = value1;
const uint32_t ures = value1 > value2 ? value1 : value2;
rv->io.mem_write_w(rv, addr, ures);
#if RV32_HAS(ARCH_TEST)
check_tohost_write(rv, addr, ures);
#endif
},
GEN({
assert; /* FIXME: Implement */
Expand Down Expand Up @@ -1688,7 +1731,11 @@ RVOP(
/* copy from float registers */
const uint32_t addr = rv->X[ir->rs1] + ir->imm;
RV_EXC_MISALIGN_HANDLER(3, STORE, false, 1);
rv->io.mem_write_w(rv, addr, rv->F[ir->rs2].v);
const uint32_t value = rv->F[ir->rs2].v;
rv->io.mem_write_w(rv, addr, value);
#if RV32_HAS(ARCH_TEST)
check_tohost_write(rv, addr, value);
#endif
},
GEN({
assert; /* FIXME: Implement */
Expand Down Expand Up @@ -2070,7 +2117,11 @@ RVOP(
{
const uint32_t addr = rv->X[ir->rs1] + (uint32_t) ir->imm;
RV_EXC_MISALIGN_HANDLER(3, STORE, true, 1);
rv->io.mem_write_w(rv, addr, rv->X[ir->rs2]);
const uint32_t value = rv->X[ir->rs2];
rv->io.mem_write_w(rv, addr, value);
#if RV32_HAS(ARCH_TEST)
check_tohost_write(rv, addr, value);
#endif
},
GEN({
mem;
Expand Down Expand Up @@ -2591,7 +2642,11 @@ RVOP(
{
const uint32_t addr = rv->X[rv_reg_sp] + ir->imm;
RV_EXC_MISALIGN_HANDLER(3, STORE, true, 1);
rv->io.mem_write_w(rv, addr, rv->X[ir->rs2]);
const uint32_t value = rv->X[ir->rs2];
rv->io.mem_write_w(rv, addr, value);
#if RV32_HAS(ARCH_TEST)
check_tohost_write(rv, addr, value);
#endif
},
GEN({
mem;
Expand Down Expand Up @@ -2622,7 +2677,11 @@ RVOP(
{
const uint32_t addr = rv->X[rv_reg_sp] + ir->imm;
RV_EXC_MISALIGN_HANDLER(3, STORE, false, 1);
rv->io.mem_write_w(rv, addr, rv->F[ir->rs2].v);
const uint32_t value = rv->F[ir->rs2].v;
rv->io.mem_write_w(rv, addr, value);
#if RV32_HAS(ARCH_TEST)
check_tohost_write(rv, addr, value);
#endif
},
GEN({
assert; /* FIXME: Implement */
Expand All @@ -2646,7 +2705,11 @@ RVOP(
{
const uint32_t addr = rv->X[ir->rs1] + (uint32_t) ir->imm;
RV_EXC_MISALIGN_HANDLER(3, STORE, false, 1);
rv->io.mem_write_w(rv, addr, rv->F[ir->rs2].v);
const uint32_t value = rv->F[ir->rs2].v;
rv->io.mem_write_w(rv, addr, value);
#if RV32_HAS(ARCH_TEST)
check_tohost_write(rv, addr, value);
#endif
},
GEN({
assert; /* FIXME: Implement */
Expand Down
Loading