Skip to content

Commit bd0f10a

Browse files
authored
Merge pull request #629 from sysprog21/riscof
Add RISCOF compliance test support
2 parents a8a5b61 + 0767f16 commit bd0f10a

File tree

6 files changed

+139
-10
lines changed

6 files changed

+139
-10
lines changed

src/emulate.c

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,25 @@ static void rv_trap_default_handler(riscv_t *rv)
6161
static void __trap_handler(riscv_t *rv);
6262
#endif /* RV32_HAS(SYSTEM) */
6363

64+
#if RV32_HAS(ARCH_TEST)
65+
/* Check if the write is to tohost and halt emulation if so.
66+
* Compliance tests write to tohost and then enter an infinite loop.
67+
* The emulator should detect this and exit gracefully.
68+
*/
69+
static inline void check_tohost_write(riscv_t *rv,
70+
uint32_t addr,
71+
uint32_t value)
72+
{
73+
if (rv->tohost_addr && addr == rv->tohost_addr && value != 0) {
74+
/* Non-zero write to tohost means test wants to exit */
75+
rv->halt = true;
76+
/* Extract exit code from tohost value (value >> 1) */
77+
vm_attr_t *attr = PRIV(rv);
78+
attr->exit_code = (value >> 1);
79+
}
80+
}
81+
#endif /* RV32_HAS(ARCH_TEST) */
82+
6483
/* wrap load/store and insn misaligned handler
6584
* @mask_or_pc: mask for load/store and pc for insn misaligned handler.
6685
* @type: type of misaligned handler
@@ -466,7 +485,11 @@ static bool do_fuse3(riscv_t *rv,
466485
for (int i = 0; i < ir->imm2; i++) {
467486
uint32_t addr = rv->X[fuse[i].rs1] + fuse[i].imm;
468487
RV_EXC_MISALIGN_HANDLER(3, STORE, false, 1);
469-
rv->io.mem_write_w(rv, addr, rv->X[fuse[i].rs2]);
488+
uint32_t value = rv->X[fuse[i].rs2];
489+
rv->io.mem_write_w(rv, addr, value);
490+
#if RV32_HAS(ARCH_TEST)
491+
check_tohost_write(rv, addr, value);
492+
#endif
470493
}
471494
PC += ir->imm2 * 4;
472495
if (unlikely(RVOP_NO_NEXT(ir))) {

src/main.c

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -314,6 +314,25 @@ int main(int argc, char **args)
314314
}
315315
rv_log_info("RISC-V emulator is created and ready to run");
316316

317+
#if RV32_HAS(ARCH_TEST)
318+
/* Extract tohost/fromhost addresses for arch-test mode */
319+
if (opt_arch_test && opt_prog_name) {
320+
elf_t *elf = elf_new();
321+
if (elf && elf_open(elf, opt_prog_name)) {
322+
const struct Elf32_Sym *sym;
323+
if ((sym = elf_get_symbol(elf, "tohost"))) {
324+
rv_set_tohost_addr(rv, sym->st_value);
325+
rv_log_info("Found tohost at 0x%08x", sym->st_value);
326+
}
327+
if ((sym = elf_get_symbol(elf, "fromhost"))) {
328+
rv_set_fromhost_addr(rv, sym->st_value);
329+
rv_log_info("Found fromhost at 0x%08x", sym->st_value);
330+
}
331+
}
332+
elf_delete(elf);
333+
}
334+
#endif
335+
317336
#if defined(__EMSCRIPTEN__)
318337
disable_run_button();
319338
#endif

src/riscv.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -886,6 +886,18 @@ bool rv_has_halted(riscv_t *rv)
886886
return rv->halt;
887887
}
888888

889+
#if RV32_HAS(ARCH_TEST)
890+
void rv_set_tohost_addr(riscv_t *rv, uint32_t addr)
891+
{
892+
rv->tohost_addr = addr;
893+
}
894+
895+
void rv_set_fromhost_addr(riscv_t *rv, uint32_t addr)
896+
{
897+
rv->fromhost_addr = addr;
898+
}
899+
#endif
900+
889901
void rv_delete(riscv_t *rv)
890902
{
891903
assert(rv);

src/riscv.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -440,6 +440,12 @@ void rv_halt(riscv_t *rv);
440440
/* return the halt state */
441441
bool rv_has_halted(riscv_t *rv);
442442

443+
#if RV32_HAS(ARCH_TEST)
444+
/* Set tohost/fromhost addresses for architectural testing */
445+
void rv_set_tohost_addr(riscv_t *rv, uint32_t addr);
446+
void rv_set_fromhost_addr(riscv_t *rv, uint32_t addr);
447+
#endif
448+
443449
enum {
444450
/* run and trace instructions and print them out during emulation */
445451
RV_RUN_TRACE = 1,

src/riscv_private.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,12 @@ struct riscv_internal {
229229
*/
230230
uint32_t last_csr_sepc;
231231
#endif
232+
233+
#if RV32_HAS(ARCH_TEST)
234+
/* RISC-V architectural test support: tohost/fromhost addresses */
235+
uint32_t tohost_addr;
236+
uint32_t fromhost_addr;
237+
#endif
232238
};
233239

234240
/* sign extend a 16 bit value */

src/rv32_template.c

Lines changed: 72 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -705,7 +705,11 @@ RVOP(
705705
sb,
706706
{
707707
const uint32_t addr = rv->X[ir->rs1] + ir->imm;
708-
rv->io.mem_write_b(rv, addr, rv->X[ir->rs2]);
708+
const uint32_t value = rv->X[ir->rs2];
709+
rv->io.mem_write_b(rv, addr, value);
710+
#if RV32_HAS(ARCH_TEST)
711+
check_tohost_write(rv, addr, value);
712+
#endif
709713
},
710714
GEN({
711715
mem;
@@ -722,7 +726,11 @@ RVOP(
722726
{
723727
const uint32_t addr = rv->X[ir->rs1] + ir->imm;
724728
RV_EXC_MISALIGN_HANDLER(1, STORE, false, 1);
725-
rv->io.mem_write_s(rv, addr, rv->X[ir->rs2]);
729+
const uint32_t value = rv->X[ir->rs2];
730+
rv->io.mem_write_s(rv, addr, value);
731+
#if RV32_HAS(ARCH_TEST)
732+
check_tohost_write(rv, addr, value);
733+
#endif
726734
},
727735
GEN({
728736
mem;
@@ -739,7 +747,11 @@ RVOP(
739747
{
740748
const uint32_t addr = rv->X[ir->rs1] + ir->imm;
741749
RV_EXC_MISALIGN_HANDLER(3, STORE, false, 1);
742-
rv->io.mem_write_w(rv, addr, rv->X[ir->rs2]);
750+
const uint32_t value = rv->X[ir->rs2];
751+
rv->io.mem_write_w(rv, addr, value);
752+
#if RV32_HAS(ARCH_TEST)
753+
check_tohost_write(rv, addr, value);
754+
#endif
743755
},
744756
GEN({
745757
mem;
@@ -1501,8 +1513,12 @@ RVOP(
15011513
*/
15021514
const uint32_t addr = rv->X[ir->rs1];
15031515
RV_EXC_MISALIGN_HANDLER(3, STORE, false, 1);
1504-
rv->io.mem_write_w(rv, addr, rv->X[ir->rs2]);
1516+
const uint32_t value = rv->X[ir->rs2];
1517+
rv->io.mem_write_w(rv, addr, value);
15051518
rv->X[ir->rd] = 0;
1519+
#if RV32_HAS(ARCH_TEST)
1520+
check_tohost_write(rv, addr, value);
1521+
#endif
15061522
},
15071523
GEN({
15081524
assert; /* FIXME: Implement */
@@ -1519,6 +1535,9 @@ RVOP(
15191535
if (ir->rd)
15201536
rv->X[ir->rd] = value1;
15211537
rv->io.mem_write_w(rv, addr, value2);
1538+
#if RV32_HAS(ARCH_TEST)
1539+
check_tohost_write(rv, addr, value2);
1540+
#endif
15221541
},
15231542
GEN({
15241543
assert; /* FIXME: Implement */
@@ -1536,6 +1555,9 @@ RVOP(
15361555
rv->X[ir->rd] = value1;
15371556
const uint32_t res = value1 + value2;
15381557
rv->io.mem_write_w(rv, addr, res);
1558+
#if RV32_HAS(ARCH_TEST)
1559+
check_tohost_write(rv, addr, res);
1560+
#endif
15391561
},
15401562
GEN({
15411563
assert; /* FIXME: Implement */
@@ -1553,6 +1575,9 @@ RVOP(
15531575
rv->X[ir->rd] = value1;
15541576
const uint32_t res = value1 ^ value2;
15551577
rv->io.mem_write_w(rv, addr, res);
1578+
#if RV32_HAS(ARCH_TEST)
1579+
check_tohost_write(rv, addr, res);
1580+
#endif
15561581
},
15571582
GEN({
15581583
assert; /* FIXME: Implement */
@@ -1570,6 +1595,9 @@ RVOP(
15701595
rv->X[ir->rd] = value1;
15711596
const uint32_t res = value1 & value2;
15721597
rv->io.mem_write_w(rv, addr, res);
1598+
#if RV32_HAS(ARCH_TEST)
1599+
check_tohost_write(rv, addr, res);
1600+
#endif
15731601
},
15741602
GEN({
15751603
assert; /* FIXME: Implement */
@@ -1587,6 +1615,9 @@ RVOP(
15871615
rv->X[ir->rd] = value1;
15881616
const uint32_t res = value1 | value2;
15891617
rv->io.mem_write_w(rv, addr, res);
1618+
#if RV32_HAS(ARCH_TEST)
1619+
check_tohost_write(rv, addr, res);
1620+
#endif
15901621
},
15911622
GEN({
15921623
assert; /* FIXME: Implement */
@@ -1606,6 +1637,9 @@ RVOP(
16061637
const int32_t b = value2;
16071638
const uint32_t res = a < b ? value1 : value2;
16081639
rv->io.mem_write_w(rv, addr, res);
1640+
#if RV32_HAS(ARCH_TEST)
1641+
check_tohost_write(rv, addr, res);
1642+
#endif
16091643
},
16101644
GEN({
16111645
assert; /* FIXME: Implement */
@@ -1625,6 +1659,9 @@ RVOP(
16251659
const int32_t b = value2;
16261660
const uint32_t res = a > b ? value1 : value2;
16271661
rv->io.mem_write_w(rv, addr, res);
1662+
#if RV32_HAS(ARCH_TEST)
1663+
check_tohost_write(rv, addr, res);
1664+
#endif
16281665
},
16291666
GEN({
16301667
assert; /* FIXME: Implement */
@@ -1642,6 +1679,9 @@ RVOP(
16421679
rv->X[ir->rd] = value1;
16431680
const uint32_t ures = value1 < value2 ? value1 : value2;
16441681
rv->io.mem_write_w(rv, addr, ures);
1682+
#if RV32_HAS(ARCH_TEST)
1683+
check_tohost_write(rv, addr, ures);
1684+
#endif
16451685
},
16461686
GEN({
16471687
assert; /* FIXME: Implement */
@@ -1659,6 +1699,9 @@ RVOP(
16591699
rv->X[ir->rd] = value1;
16601700
const uint32_t ures = value1 > value2 ? value1 : value2;
16611701
rv->io.mem_write_w(rv, addr, ures);
1702+
#if RV32_HAS(ARCH_TEST)
1703+
check_tohost_write(rv, addr, ures);
1704+
#endif
16621705
},
16631706
GEN({
16641707
assert; /* FIXME: Implement */
@@ -1688,7 +1731,11 @@ RVOP(
16881731
/* copy from float registers */
16891732
const uint32_t addr = rv->X[ir->rs1] + ir->imm;
16901733
RV_EXC_MISALIGN_HANDLER(3, STORE, false, 1);
1691-
rv->io.mem_write_w(rv, addr, rv->F[ir->rs2].v);
1734+
const uint32_t value = rv->F[ir->rs2].v;
1735+
rv->io.mem_write_w(rv, addr, value);
1736+
#if RV32_HAS(ARCH_TEST)
1737+
check_tohost_write(rv, addr, value);
1738+
#endif
16921739
},
16931740
GEN({
16941741
assert; /* FIXME: Implement */
@@ -2070,7 +2117,11 @@ RVOP(
20702117
{
20712118
const uint32_t addr = rv->X[ir->rs1] + (uint32_t) ir->imm;
20722119
RV_EXC_MISALIGN_HANDLER(3, STORE, true, 1);
2073-
rv->io.mem_write_w(rv, addr, rv->X[ir->rs2]);
2120+
const uint32_t value = rv->X[ir->rs2];
2121+
rv->io.mem_write_w(rv, addr, value);
2122+
#if RV32_HAS(ARCH_TEST)
2123+
check_tohost_write(rv, addr, value);
2124+
#endif
20742125
},
20752126
GEN({
20762127
mem;
@@ -2591,7 +2642,11 @@ RVOP(
25912642
{
25922643
const uint32_t addr = rv->X[rv_reg_sp] + ir->imm;
25932644
RV_EXC_MISALIGN_HANDLER(3, STORE, true, 1);
2594-
rv->io.mem_write_w(rv, addr, rv->X[ir->rs2]);
2645+
const uint32_t value = rv->X[ir->rs2];
2646+
rv->io.mem_write_w(rv, addr, value);
2647+
#if RV32_HAS(ARCH_TEST)
2648+
check_tohost_write(rv, addr, value);
2649+
#endif
25952650
},
25962651
GEN({
25972652
mem;
@@ -2622,7 +2677,11 @@ RVOP(
26222677
{
26232678
const uint32_t addr = rv->X[rv_reg_sp] + ir->imm;
26242679
RV_EXC_MISALIGN_HANDLER(3, STORE, false, 1);
2625-
rv->io.mem_write_w(rv, addr, rv->F[ir->rs2].v);
2680+
const uint32_t value = rv->F[ir->rs2].v;
2681+
rv->io.mem_write_w(rv, addr, value);
2682+
#if RV32_HAS(ARCH_TEST)
2683+
check_tohost_write(rv, addr, value);
2684+
#endif
26262685
},
26272686
GEN({
26282687
assert; /* FIXME: Implement */
@@ -2646,7 +2705,11 @@ RVOP(
26462705
{
26472706
const uint32_t addr = rv->X[ir->rs1] + (uint32_t) ir->imm;
26482707
RV_EXC_MISALIGN_HANDLER(3, STORE, false, 1);
2649-
rv->io.mem_write_w(rv, addr, rv->F[ir->rs2].v);
2708+
const uint32_t value = rv->F[ir->rs2].v;
2709+
rv->io.mem_write_w(rv, addr, value);
2710+
#if RV32_HAS(ARCH_TEST)
2711+
check_tohost_write(rv, addr, value);
2712+
#endif
26502713
},
26512714
GEN({
26522715
assert; /* FIXME: Implement */

0 commit comments

Comments
 (0)