“一生一芯”计划 预学习阶段
“一生一芯”计划 预学习阶段
贯穿计算机专业本科课程(数字逻辑、计算机组成原理、计算机体系结构、操作系统、计算机系统设计)很厉害的项目。
难度较大,希望自己能够坚持下去。
阅读两篇关于如何提问的文章并编写一篇不少于800字的读后感(2022.7.5)
已完成阅读,读后感见 (隐私手动打码)-提问的智慧读后感.pdf。
Linux 系统安装 (PA0) 和基本使用(2022.7.5)
安装 Linux 操作系统
暂时使用虚拟机 VMware 中安装 64 位的 Ubuntu 21.04。
根据 PA0 讲义 安装好这些工具
1 | apt-get install build-essential # build-essential packages, include binary utilities, gcc, make, and so on |
不想用 Vim,用开源版本的 VSCodium 多好啊(
Write a “Hello World” program under GNU/Linux
先随便新建并进入一个目录中
创建一个源代码文件:touch helloworld.cpp
代码截图如下:
直接在命令行编译并运行如下:
Write a Makefile to compile the “Hello World” program
小菜一碟。
Makefile 截图如下:
使用 make 命令编译并运行:
Learn to use GDB
就是一个调试器,之后在 PA1 中也会完成一个类似的。
获取“一生一芯”框架代码
在自己创好的目录下执行git clone -b ysyx2204 git@github.com:OSCPU/ysyx-workbench.git
完成好 git config
测试环境变量 $NEMU_HOME
和 $AM_HOME
,发现一切正常。
Compiling and Running NEMU
在得到 NEMU 代码后,运行 make menuconfig
,报错。发现缺少了 bison
和 flex
这两个软件。
再用 apt
命令安装上即可。
学习 Linux 基本使用
略
复习 C 语言知识
略
搭建 Verilator 仿真环境(2022.7.5)
首先设置好环境变量 $NPC_HOME
STFW+RTFM
认识 Verilator
查找官方文档,简单概括一下。
Verilator 是高性能 Verilog HDL 模拟器,允许用户通过 C++/SystemC 对 RTL 进行验证。
使用时会生成一系列 C++/SystemC 文件,这些文件由 C++ 编译器进行编译,并通过最终生成的可执行文件执行设计模拟。
安装 Verilator
具体安装教程可以参考官方安装教程,通过 git 获取源码安装。
切换到要求的 4.210 版本分支
再根据教程使用命令安装,最终安装成功。
运行示例
手册中包含的 C++ 网址
新建一个文件 our.v
,具体代码如下
1 | module our; |
新建一个文件 sim_main.cpp
,具体代码如下:
1 |
|
top->eval();
是为了在每个时钟周期获取对应的输出数据contextp
是专门用来设置仿真环境的指针
编译命令为:verilator -Wall --cc --exe --build sim_main.cpp our.v
编译完成后,生成了一个文件夹obj_dir
,可以运行其中的可执行文件 Vour
。
示例:双控开关
根据实验手册的提示,创建并完善代码。
verilog 代码 top.v
1 | module top( |
对双控开关进行仿真
根据提示的伪代码修改得到的 C++ 文件 sim_main.cpp
1 |
|
运行编译命令 verilator -Wall --cc --exe --build sim_main.cpp top.v
生成 obj_dir 文件夹。运行 /obj_dir/Vtop
运行可执行程序,发现能正确输出。
理解 RTL 仿真的行为
Verilator 编译出的 C++ 代码在 /obj_dir/Vtop.cpp
和 /obj_dir/Vtop.h
中。
在头文件中可以看到,模块 top 的输入和输出被绑定好了。执行时调用 eval 函数。
打印波形并查看
按照手册提示安装好 GTKWave。
要输出波形图,还需要对代码进行稍微修改,加入 trace 波形的相关变量和代码。
1 |
|
生成目标文件夹 obj_dir:verilator -Wno-fatal top.v sim_main.cpp --top-module top --cc --trace --exe
。其中 --trace 代表追踪波形以便于后续生成。
编译链接编译出的文件:make -C obj_dir -f Vtop.mk Vtop
运行可执行文件并生成波形图:/obj_dir/Vtop
查看波形图:gtkwave wave.vcd
。
查看结果如下,经检查,波形正确:
编写 Makefile 进行一键仿真
尝试为 npc/Makefile 编写规则 sim,实现一键仿真,如键入 make sim
即可进行上述仿真。
接入 NVBoard
虚拟 FPGA 板卡项目,可以在 RTL 仿真环境中提供一个虚拟板卡的界面。支持拨码开关、LED灯、VGA 显示等功能。
先根据手册提示获取 NVBoard 代码。
运行 NVBoard 示例
在 example 文件夹中,键入命令 make run
运行示例。发现是一个循环显示数码和循环显示 LED 的板子和一张南京大学校内的照片。
在 NVBoard 上实现双控开关
仿照示例下的 C++ 文件和 Makefile 编写我的 C++ 文件和 Makefile。并编写约束文件分配输入输出引脚。
C++ 文件代码如下:
1 |
|
Makefile 文件基本复制样例,并做了一点点修改
1 | include $(NVBOARD_HOME)/scripts/nvboard.mk |
实现引脚绑定的约束文件 /constr/top.nxdc,将两个输入绑定在了 0 号和 1 号开关上,输出结果绑定在 0 号 LED 灯上。
1 | top=top |
完成后,在目录下执行 make sim
将代码烧录到 NVBoard 上。运行 /build/top
效果如下:(结果显示正确)
示例:流水灯
流水灯是按照顺序依次亮起和熄灭的一组灯
将流水灯接入 NVBoard
流水灯 Verilog 文件直接照抄讲义上的代码,C++ 文件根据讲义上的伪代码编写如下:
1 |
|
约束文件 top.nxdc
如下:
1 | top=top |
完成代码后,在目录下 make sim
,编译完成后 /build/top
,就能看到灯从右端往左端依次亮起并熄灭。
理解 RTL 仿真的行为
Verilator 的思路是把 rtl 文件当作一个可以执行的“函数”,通过对其抽象为对象来执行各种操作。
数字电路基础实验 2022.7.7~2022.7.12
本部分将借助 NVBoard 完成南京大学的数电与计组实验。
你需要完成"CPU数据通路"之前的大部分实验内容, 除了以下例外
- "在线测试"的内容需要加入相关课程才能完成, 目前可以忽略
- 计数器和时钟: 由于仿真环境下无法提供精确的时钟, 时钟部分的实验难以准确进行, 因此可作为阅读材料进行了解
- 寄存器组及存储器: 讲义中建议通过工具相关的IP核实现存储器, 但仿真环境下不存在这样的IP核, 无法开展实验, 因此可作为阅读材料进行了解
- 关于"CPU数据通路"及其后续内容, "一生一芯"将会有所改动, 因此在预学习阶段无需完成
我完成的具体代码链接在此。
由于实验七、八、九没什么思路,暂时战术跳过。
完成 PA1 阶段 1 2022.7.13~2022.7.15
阅读 PA 讲义中的 FAQ(常见问题):略
根据讲义内容,使用 make menuconfig
命令,将 Basic ISA 切换成 riscv64。
进入 nemu 目录下,先 make run
,发现报错,根据提示找到代码,将 assert(0)
的地方注释掉,再运行,发现能成功运行。命令 help
显示支持的命令;命令 c
表示继续执行到程序结束,输入该命令可以看到 hit good trap
的提示,说明程序正常执行结束;命令 q
表示退出 NEMU。
基础设施:简易调试器
由于在刚结束的这一学期,我在所学专业必修的课程《计算机系统设计》已经完成地做完一个 x86 版本的 PA 实验。因此,二周目的时候偷了一些懒,参考了自己之前的一些思路。发现新版本的 PA 实验还是有些区别的。
实现单步执行
在 sdb.c 代码文件,先在 cmd_table 中加入该指令的描述。
然后在外部实现 cmd_si
指令。
具体思路是,利用 strtok
函数对输入按空格进行分词,将判断是否有参数传入。如果没有参数,就只执行一次 cpu_exec(1)
,如果有参数,将参数转化成十进制表示,并传入 cpu_exec
中,执行对应的次数。
实现结果如下:
实现打印寄存器
在 sdb.c 代码文件,先在 cmd_table 中加入该指令的描述。
然后在外部实现 cmd_info
指令。
参数有 r 和 w,此处暂时实现 r 参数对应的操作,不管 w 参数。直接调用 isa_reg_display()
函数。~~果然,“升级版本”的 PA 实验函数封装得更完善。~~该函数需要自己实现,在 reg.c 中。此时和之前我完成的 x86 版本就不一样了。RISC-V 体系结构的寄存器完全不一样。通过 RTFSC 查看可调用的 api 接口 gpr()
,该接口为 reg.h 中的宏定义,根据索引取出对应编号寄存器的值。为了方便展示,同时打印出了寄存器值的十六进制和十进制。
info r
指令的实现结果如下:
实现扫描内存
在 sdb.c 代码文件,先在 cmd_table 中加入该指令的描述。
然后在外部实现 cmd_x
指令。
首先需要通过分词检查参数个数是否合法。
然后得到第二个值。第二个值表示扫描的长度。
第三个值本来应该是一个表达式,此处为了简化,暂时处理为一个十六进制的数字。
调用 vaddr_read
函数对内存进行读取,再输出即可。
该指令的实现结果如下:经查阅相关文档发现,RISC-V 和 x86 一样,也是小端模式编址。
预学习阶段到此结束🎆🎆🎆