#risc-v #testing #emulator #simulator #cli-tool #file-path

bin+lib lib_rv32

用于模拟、测试和学习 RISC-V 的库和 CLI 工具

2 个版本

0.1.1 2021 年 8 月 5 日
0.1.0 2021 年 8 月 5 日

#157 in 模拟

自定义许可证

51KB
1K SLoC

lib-rv32

Rust 库,用于模拟 32 位 RISC-V

build tests

文档 在 docs.rs 上

打包 在 crates.io 上


此库可以针对实现所需特质的任何内存和寄存器文件执行指令(代码 lib_rv32::traits::{Memory, RegisterFile} 的内存和寄存器文件)。这是为了鼓励您使用任何所需的任何前端。

然而,在 lib_rv32::mcu 中提供了参考实现。该库提供从内存、寄存器读取和执行单个指令的函数。由于用户决定何时调用这些函数,因此这些函数可能适合大多数用例。

示例

my_app.rs:

use std::path::Path;

use lib_rv32::mcu::*;
use lib_rv32::exec_one;

fn main() {
    let mut mcu: Mcu = Mcu::new(1024 * 64);

    mcu.mem
        .program_from_file(&Path::from("./prog.bin"))
        .expect("Could not program MCU.");

    loop {
        exec_one(&mut mcu.pc, &mut mcu.mem, &mut mcu.rf).unwrap();
    }
}

CLI

用法

CLI 是如何在一个应用程序中使用核心库的一个示例。CLI 的主要用途是跟踪 RISC-V 程序的执行并对其行为进行断言。它目前仅支持简单的二进制内存镜像(不支持 ELF 二进制文件)。

USAGE:
    lrv-cli [FLAGS] [OPTIONS] <binary>

FLAGS:
    -h, --help       Prints help information
    -V, --version    Prints version information
    -v, --verbose    Enable verbose logging

OPTIONS:
    -a, --assertions <ASSERTIONS>    A JSON formatted set of assertions.
    -m, --mem <MEM_SIZE>             Set the size of the MCU memory (default 64 KB).
    -s, --stop <STOP_PC>             Set the program counter at which to stop emulation.

ARGS:
    <binary>    RISC-V binary to execute

示例

将断言输入 JSON 文件中(注意:所有数字都是字符串,以便允许十六进制或十进制基数)。

assert.json:

{
    "registers": {
        "x0": "0x0",
        "a0": "20"
    },
    "memory": {
        "0x0000": "0x00010117"
    }
}

然后运行

lrv-cli -v ./prog.bin -s 24 -a assert.json

这将执行 prog.bin,在 PC 值 0x24 处停止,然后从 assert.json 中进行断言。

程序将逐条指令跟踪执行

[0000]  00010117  |  auipc  sp, 0x10           |  sp <- 0x10000 (65536);
[0004]  fe010113  |  addi   sp, sp, -32        |  sp <- 0xffe0 (65504);
[0008]  00400513  |  addi   a0, zero, 4        |  a0 <- 0x4 (4);
[000c]  00500593  |  addi   a1, zero, 5        |  a1 <- 0x5 (5);
[0010]  00000097  |  auipc  ra, 0x0            |  ra <- 0x10 (16);
[0014]  018080e7  |  jalr   ra, (24)ra         |  ra <- 0x18 (24); pc <- 0x28;
...

完成时,将总结结果

...
[001c]  f0028293  |  addi   t0, t0, -256       |  t0 <- 0xf00 (3840);
[0020]  00a2a023  |  sw     a0, 0(t0)          |  (word *)0x00000f00 <- 0x14 (20);

Reached stop-PC.

a0 == 20
*0x00000000 == 65815

测试

该项目具有非常灵活的测试系统。

在适当的地方提供了单元测试。

此外,要测试整个系统,可以将测试程序添加到 tests/programs。测试只是一个包含 .c.s 源文件以及包含程序完成后 MCU 状态断言的 test_case.json 的目录。

测试过程中,Cargo 将为每个测试

  1. 为 RISC-V 编译它
  2. 启动一个新的 MCU
  3. 用生成的二进制文件编程它
  4. 运行测试程序一段时间
  5. 进行断言
  6. 报告成功或失败

如果测试失败,它将描述导致崩溃的错误或失败的断言,并打印编译的测试二进制文件的对象转储。

...
[001c]  f0028293  |  addi   t0, t0, -256       |  t0 <- 0xf00 (3840);
[0020]  00a2a023  |  sw     a0, 0(t0)          |  (word *)0x00000f00 <- 0x14 (20);
Stopping because the stop PC 0x24 was reached.


Failed test: tests/programs/mul@0x00000024: Register assertion failed: (x10=0x00000014) != 0x00000018.

prog.elf:     file format elf32-littleriscv


Disassembly of section .text.init:

00000000 <start>:
   0:   00010117                auipc   sp,0x10
   4:   fe010113                addi    sp,sp,-32 # ffe0 <__global_pointer$+0xf75c>
   8:   00400513                li      a0,4
   c:   00500593                li      a1,5
...

测试在持续集成环境中运行,但只要您的系统具有以下配置,也可以本地运行:riscv(32|64)-unknown-elf-gcc

待办事项

  • 基本/整数指令集架构(i)
    • 基本支持
    • CSR/中断指令
  • 乘法(m)
  • 原子操作(a)
  • 压缩(c)
  • 支持ELF二进制文件

依赖项

~1.1–1.7MB
~26K SLoC