基于 MIPS 指令集的 32 位模型机设计与 FPGA 实现
- 系统:Linux 平台,如 Ubuntu 22.4。
- Verilator: 可以从源码编译,也可以直接通过包管理器进行安装
- Surfer (VSCode 插件):用来查看波形图
- bear:配合 clangd 进行代码错误检查
- 需要安装的软件包有:
make
bear
mips-linux-gnu-gcc
(gcc-mips-linux-gnu
)
这是 CPU,通过 Verilog 代码实现电路逻辑。
这里面有很多的测试用例,将 C 代码交叉编译成 MIPS 平台的二进制,然后通过 Makefile 脚本转化成 XXX.hex
。然后将 XXX.hex
处理到 CPU 中的 InstMem.v
中,就可以进行测试了。至于怎么将 hex 文件中的字节导入到 InstMem 中,就看你的选择了,当然借助 AI 让他帮你搞是最好的选择。
好消息是,我通过 python 脚本已经自动化完成这件事了。你只需要在 cpu_test 中直接 make clean && make build ALL=sub
就能让 CPU 准备跑 sub 程序了,接着在项目目录中直接输入 make run
,如果 CPU 实现正确的话,你就能直接看到绿色的 HIT good trap!
。
更好的消息是,你可以直接在项目目录中直接输入 make runall
,测试所有测试案例:
make runall
...
[2025-02-28 18:32:22] 开始编译测试用例: fib
[2025-02-28 18:32:23] 开始运行测试用例: fib
运行时间: 0.471秒
测试通过: fib (耗时 1 秒)
[2025-02-28 18:32:23] 开始编译测试用例: matrix_mul
[2025-02-28 18:32:23] 开始运行测试用例: matrix_mul
运行时间: 0.558秒
测试通过: matrix_mul (耗时 1 秒)
[2025-02-28 18:32:24] 开始编译测试用例: bubble_sort
[2025-02-28 18:32:24] 开始运行测试用例: bubble_sort
运行时间: 0.366秒
测试通过: bubble_sort (耗时 0 秒)
[2025-02-28 18:32:24] 开始编译测试用例: div
[2025-02-28 18:32:24] 开始运行测试用例: div
运行时间: 0.613秒
测试通过: div (耗时 1 秒)
[2025-02-28 18:32:25] 开始编译测试用例: add
[2025-02-28 18:32:25] 开始运行测试用例: add
运行时间: 0.481秒
测试通过: add (耗时 0 秒)
[2025-02-28 18:32:26] 开始编译测试用例: or
[2025-02-28 18:32:26] 开始运行测试用例: or
运行时间: 0.481秒
测试通过: or (耗时 0 秒)
[2025-02-28 18:32:26] 开始编译测试用例: shift
[2025-02-28 18:32:26] 开始运行测试用例: shift
运行时间: 0.483秒
测试通过: shift (耗时 1 秒)
[2025-02-28 18:32:27] 开始编译测试用例: mult
[2025-02-28 18:32:27] 开始运行测试用例: mult
运行时间: 0.498秒
测试通过: mult (耗时 0 秒)
[2025-02-28 18:32:27] 开始编译测试用例: recursion
[2025-02-28 18:32:27] 开始运行测试用例: recursion
运行时间: 0.550秒
测试通过: recursion (耗时 1 秒)
[2025-02-28 18:32:28] 开始编译测试用例: danger
[2025-02-28 18:32:28] 开始运行测试用例: danger
运行时间: 0.582秒
测试通过: danger (耗时 1 秒)
[2025-02-28 18:32:29] 开始编译测试用例: pipeline_test
[2025-02-28 18:32:29] 开始运行测试用例: pipeline_test
运行时间: 0.528秒
测试通过: pipeline_test (耗时 0 秒)
[2025-02-28 18:32:29] 开始编译测试用例: return
[2025-02-28 18:32:29] 开始运行测试用例: return
运行时间: 0.487秒
测试通过: return (耗时 1 秒)
[2025-02-28 18:32:30] 开始编译测试用例: fact
[2025-02-28 18:32:30] 开始运行测试用例: fact
运行时间: 0.570秒
测试通过: fact (耗时 1 秒)
[2025-02-28 18:32:31] 开始编译测试用例: branch
[2025-02-28 18:32:31] 开始运行测试用例: branch
运行时间: 0.544秒
测试通过: branch (耗时 0 秒)
[2025-02-28 18:32:31] 开始编译测试用例: sub
[2025-02-28 18:32:31] 开始运行测试用例: sub
运行时间: 0.573秒
测试通过: sub (耗时 1 秒)
[2025-02-28 18:32:32] 测试结果汇总:
├── 总测试用例: 15
├── 通过用例: 15
└── 失败用例: 0
[2025-02-28 18:32:32] 执行清理操作...
目前能通过所有测试,这意味着,我们的 CPU 设计正确地实现了所有的指令。
这是利用 Verilator 将 CPU 中的所有 Verilog 代码仿真成 C++ 类库,然后在 main.cpp
中就可以利用这些库进行操控、监视、CPU 的行为等等,从而进行仿真,这也是 Verilator 的工作原理。它比 Vivado 等工具快几乎 100 倍,效率非常高。
在 Makefile 中所在的目录中运行 make run
即可。
之后就能看到多了一个 wave.vcd
文件。通过 surfer 插件打开,就能看到波形图了。目前为止,CPU 已经能识别所有已经实现的指令了。你可以自由探索 surfer 的各种用法。
通过对比实现流水线前后的 MIPS 对比来量化性能变动。
以测试案例 matrix_mul.c
为基准,目前它的 MIPS 为:
MIPS: 0.825649 MIPS