分享一个我最近完成过的小项目--64位的单周期 RISC-V 模拟器,这个项目我最近参与一生一芯计划过程中完成的一个小项目。

需要用到的相关知识:Verilog、Verilator、计算机组成原理、汇编、RISC-V、C语言、C++、编译与链接、Mekfile、Linux、Shell


1. 于开始前

由于一生一芯计划的性质以及学术诚信的原因,该项目不会开源,本文章重在分享该项目的实现思路。当然,如果你在尝试复现该项目时,遇到了问题可以发给我邮箱(1439627984@qq.com),如何提问可以参考这个网站


2.项目简介

该项目使用 Verilog 来实现单周期 RISC-V CPU 的行为,C 语言实现相关外设以及存储器的功能,外设包括 VGA、时钟、串口等。
最终的完整项目可以运行任意 C 语言程序,甚至可以跑一个红白机模拟器。


3.项目组成

该项目可以分为两个部分:
【1】使用 Verilog 编写的 RTL 代码:该部分实现了 CPU 除存储器之外所有功能。(这里我后面简称为npc)
【2】PA实验提供的框架代码:南京大学一个超硬核的编程实验(一个用来折磨人的实验


4.项目实现思路

【1】完成 PA 实验

完成 PA 实验至少到 PA2,做到熟悉 PA 实验提供的代码框架,便于后续的使用。


【2】编写 npc

使用 Verilog 实现一个64位单周期 RISC-V CPU除存储器之外所有功能,具体实现可以参考南京大学的数电实验


【3】将 npc 接入 PA 框架中

完成上面的俩步后,便是需要将npc接入到PA提供的框架代码中了。具体可以细分为几步:


① 熟悉编译过程

通过阅读 Verilator 编译生成的 Makefile,能给自己编写一个新的 Makefile 实现 C 语言仿真 Verilog,即调用通过 Verilator 生成的 C++ 文件,为后续把 npc 接入到 PA 框架中做好基础


② 改写 NEMU

改写 PA 中 NEMU 代码,具体的是,先改写 KConfig 配置文件,使其支持一个新 ISA-npc。作为验证,应先是直接复制在 PA2 中已经实现的 RISC-V64,改写对应的代码,完成编译。


③ 封装 npc 并调用

通过编写 API,封装 Verilog 编译生成的 C++文件,再改写 NEMU 中 inst.c 的实现,使其是调用我们刚刚封装的 API 实现正常工作的。


【4】调试与优化

这步时,我们已经有了一个完成的框架了,接着要做的就是不断的调试加优化了,而在调试时我们可以复用PA提供的一切的基础设施、外设与测试环境,这就是为什么要引用 PA 框架代码的原因之一。