用 C 编写的、可选择 RV32IMA/RV64IMA 的五级流水模拟器,用于学习指令执行、流水线时序和处理器验证。提供命令行运行、流水轨迹 CSV 导出和 Spike 差分工具。
- 单核、单发射、顺序执行,支持数据相关停顿和分支冲刷。
- 实现 RV32I/RV64I、乘除法、原子指令,以及 CSR 访问和 M/S/U 特权级骨架;同步异常进入
mtvec陷阱处理程序,mret可返回。 - 支持匹配所选位宽的小端 ELF32(ILP32)或 ELF64(LP64)与原始二进制装载、提交与异常轨迹、定向测试和部分 RV32/RV64IM 指令的 Spike 差分。
目前用于 RV32/RV64 裸机程序验证,尚不能启动 xv6。支持物理地址访存、M 模式定时中断和自定义轮询 UART;暂不实现 MMU、S 模式陷阱/中断、PLIC 和磁盘设备。原子操作在 RV32 下支持 .W,RV64 下还支持 .D,通过总线访问 ELF 装载的程序内存。
需要 CMake 3.20+、支持 C11 和 __int128 的 GCC/Clang 编译器和 Python 3。Python 工具仅使用标准库。构建和运行都不需要 RISC-V 交叉工具链或 Spike,只有重新生成 programs/testcode/ 下的示例镜像才需要前者。
以下命令在项目根目录执行。默认 RISCV_XLEN=64;它选择客户机指令集位宽,不改变宿主机编译器位宽。
构建 RV32 并运行配套镜像:
cmake -S . -B build-rv32 -DRISCV_XLEN=32 -DCMAKE_BUILD_TYPE=Debug
cmake --build build-rv32 -j
./build-rv32/sim programs/testcode/prebuilt/rv32/diff_smoke.elf --stop-pc test_done
ctest --test-dir build-rv32 --output-on-failure建议两种位宽使用不同构建目录。重编示例时,make -B -C programs/testcode XLEN=32 输出到 prebuilt/rv32/,XLEN=64 输出到 prebuilt/rv64/。
cmake -S . -B build -DCMAKE_BUILD_TYPE=Debug
cmake --build build -j默认构建带轨迹功能。去掉它以及随之而来的逐拍开销:
cmake -S . -B build -DCMAKE_BUILD_TYPE=Debug -DENABLE_TRACE=OFF
cmake --build build -j这两个开关会被该构建拒绝:--stage-trace、--trace-json。
仓库提交了预编译的 programs/testcode/prebuilt/rv64/diff_smoke.elf,无需交叉工具链:
./build/sim programs/testcode/prebuilt/rv64/diff_smoke.elf --stop-pc test_done
ctest --test-dir build --output-on-failure正常结束时统计信息包含 retired=33 status=complete。--stop-pc 接受符号名或数字地址;test_done 之后是外部环境的退出序列和等待循环,必须让它退休后停止。ctest -N 可列出全部测试,任一失败则整体失败。镜像源码见 programs/testcode/diff_smoke.S,改动后用 make -C programs/testcode 重建并一并提交。
mkdir -p out
./build/sim programs/testcode/prebuilt/rv64/diff_smoke.elf --stop-pc test_done --stage-trace > out/trace.log
python3 tools/trace_csv.py out/trace.log -o out/trace.csv打开 out/trace.csv,查看各周期、各阶段的 PC 和机器码。这条路径需要默认构建(ENABLE_TRACE=ON)。
镜像位宽必须匹配模拟器:RV32 使用 ELF32/ILP32,RV64 使用 ELF64/LP64。裸镜像用 --base 指定装载地址;不支持压缩或浮点指令。完整参数可通过 ./build/sim --help 查看。
src/riscvsim/
main.c 主流程、镜像装载、结果输出与资源清理
cli.c/.h 命令行解析与配置检查
core/ CPU 状态、五级流水、指令执行与 CSR
system/ 机器接线与运行、RAM/MMIO、镜像装载及定时器
utils/ 阶段日志与提交轨迹
programs/ 被模拟机器的程序
testcode/ 汇编测试程序、链接脚本与 Makefile
prebuilt/ 预编译 ELF,按 rv32/rv64 分类
tests/ C 测试:指令、流水时序、装载与命令行契约;工具测试为 Python
tools/ 轨迹 CSV 导出与 Spike 差分
docs/ 功能设计说明
CMakeLists.txt 构建与测试入口
core/ 通过 SimBus 访问系统内存,不依赖具体后端。核心编为 riscv_core 静态库,内存模块编为 sim_memory;sim_machine 负责连接 CPU 和设备,并按模拟周期推进时间。阅读代码可从 main.c、machine.c 和 core.c 开始。
build/ 保存编译产物,out/ 保存生成的轨迹,均不纳入版本控制。
- xv6 支持工作计划:剩余功能、实施顺序与验收条件。
- RV32/RV64 编译选项设计:位宽选择、实现约定与镜像构建。
- UART 终端设备与回显程序设计:寄存器、宿主交互与程序行为。
- 轨迹工具:阶段日志 CSV 导出与 Spike 差分。
测试合并为五组,使用 ctest --test-dir build --output-on-failure 一次运行:
| 文件 | 覆盖范围 |
|---|---|
tests/test_core.c |
RV32/RV64IMA 指令、流水线停顿/冲刷、CSR、异常与返回 |
tests/test_devices.c |
RAM/MMIO、UART、定时器 |
tests/test_system.c |
高地址总线访存、原子保留、中断和机器运行 |
tests/test_image.c |
ELF32/ELF64 解析、段装载、符号和畸形镜像 |
tests/test_tools.py |
命令行、JSON 提交轨迹、CSV、反汇编和 Spike 工具 |
test_util.h 共用断言和指令编码器。关闭轨迹时仅跳过 Python 中依赖提交轨迹的用例,其余测试照常运行。
提交前在本地运行上述构建和回归测试。
安装 clang-format 后重新运行 CMake 配置,即可使用 cmake --build build --target fmt 格式化项目的 C 源码和头文件。格式规则见 .clang-format。