2 个版本
0.1.1 | 2021 年 8 月 5 日 |
---|---|
0.1.0 | 2021 年 8 月 5 日 |
#157 in 模拟
51KB
1K SLoC
lib-rv32
Rust 库,用于模拟 32 位 RISC-V
库
此库可以针对实现所需特质的任何内存和寄存器文件执行指令(代码 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 将为每个测试
- 为 RISC-V 编译它
- 启动一个新的 MCU
- 用生成的二进制文件编程它
- 运行测试程序一段时间
- 进行断言
- 报告成功或失败
如果测试失败,它将描述导致崩溃的错误或失败的断言,并打印编译的测试二进制文件的对象转储。
...
[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