大家是如何写程序的?
++--------------------------------------------------------------+
|+--------------------------------------------------+ |
||+---------------------------------+ | |
|||+----------------+ | | |
|||| | | | |
vvvv |N Y |N Y |N Y |
读代码 => 写代码 => 写完? --> 编译 => 正确? --> 运行 => 正确? --> 下一个功能
大家有没有想过
本次课内容: 提升开发/调试效率的工具和基础设施
很少人用记事本写代码
没错, 你需要一个方便的编辑器!
仅仅会用还不够, 你还需要学习一些高级功能
INSTPAT
实现了50条指令, 突然想批量修改:%! seq 1 50 | shuf | cat -n | awk '{print "\#define X" $1 " " $2}'
q1<C-a>jq # 将"本行数字加1"(<C-a>)和"光标移动到下一行"(j)记录到名字为"1"的宏中
49@1 # 将名字为"1"的宏回放49次
本质: 用编程取代重复劳动
也适用于文本处理
这没法加速吧…
AI帮你写代码 - Copilot
当然对学习来说, 这是违反学术诚信的
make
gcc
命令还能再快一些吗?
make -j $(nproc)
-j $(nproc)
alias make="make -j $(nproc)"
export MAKEFLAGS="-j $(nproc)"
.bashrc
中加入上述语句还能再快一些吗?
icecream
ccache
.c + 编译选项 -> .o
的关系
.c
之前用相同的选项编译过,
就直接取出.o
, 跳过gcc
的编译环节.cpp
文件gcc ...
-> ./a.out
tmux
管理多个窗口make run
自动编译运行inotifywait
- 这些课件就是这样生成的香山从改一行Chisel代码到verilator仿真跑起来, 涉及大量基础设施
.v
.cpp
clang
, ccache
等工具…即使这样, 也要将近20分钟
DDL是死的, 不想办法提升效率, 就很可能无法按时交付项目
很多同学觉得, 10s -> 1s的提升, 意义不大
脑科学研究表明: 人脑的短期记忆容量是有限的(7±2个单元)
可以持续工作的时间才是高质量的时间
使用工具/搭建基础设施, 都是短期投入, 长期回报
很多同学宁愿等100次10s,
也不愿意花3分钟设置一下ccache
说白了就是懒
克服惰性才能成长 - 习惯也是要锻炼的
问题: 怎么调试?
看波形? printf?
dummy
, sum
, add
这些,
不是很难hello-str
有几千条指令, 慢慢看还行microbench
的test规模跑几十万条指令, 笑容逐渐消失调试CPU = 找到第一条行为不正确的指令
但是波形/printf并不告诉你哪条指令开始出错, 你要自己找
将预期的正确行为直接写到程序中
跑程序出错 = 执行到最后人工assert
想要的 “金山游侠” = 提前自动assert
听上去很棒!
S = {<R, M>}
R = {PC, x0, x1, x2, ...}
PC
= 程序计数器 = 当前执行的指令位置M
= 内存
S0 = <R0, M0>
只需要检查这个状态机的状态是否正确
核心思想: 对于符合相同规范的两种实现, 给定有定义的相同输入, 两者行为应当一致
Differential Testing的应用:
对于符合RISC-V规范的两种实现, 输入正确的程序, 两者的状态变化应当一致
PA初代(2014年问世)只有x86可以选
尽管我们做了不少努力, 但编译器还是会偶尔编译出一些复杂指令
大家深受x86的折磨
为了在残酷的PA中存活下来, 同学们发明了 “自顶向下的替换调试法”
.c
逐个替换进来
.c
中有bug.c
的每个函数逐个替换进来
其实这是一个可以发顶级论文的想法
fork()
系统调用创建一个进程, 执行相同的二进制文件,
通过ptrace()
控制真机单步执行并获取寄存器状态书写了一周正确实现一个乱序发射乱序执行处理器, 成功运行自制分时多任务操作系统Nanos和仙剑奇侠传的神话
按位取反之前忘记零扩展
可惜其中一名队员摸鱼严重, 最后Linux只起了一半
学生代表作报告介绍果壳项目时, DiffTest均作为关键技术进行介绍
果壳调试Linux时, 在DiffTest的强力帮助下, 两天修复12个bug, 以至于没有留下印象深刻的bug
DiffTest捕捉到在Debian上运行GCC时的bug, 1分钟后定位到原因: 跨页指令取指缺页处理不正确
香山在开发早期(第二周)就搭建DiffTest框架, 之后便一直开启
【王凯帆、王华强】SMP-DiffTest:支持多处理器的差分测试方法 - 第一届 RISC-V 中国峰会
新增memory checker的assert
SMP DiffTest报告了新的硬件bug, 修复后香山成功启动多核Linux
2022龙芯杯第三期线上培训
Yinan Xu, et al. Towards Developing High Performance RISC-V Processors Using Agile Methodology
年份 | 项目 | 效果 |
---|---|---|
2017 | 南京大学PA实验 | 大幅降低了调试指令bug的难度 |
2018 | 南京大学参加龙芯杯 | 一周正确实现乱序发射乱序执行处理器, 并运行自制分时多任务操作系统和复杂应用仙剑奇侠传 |
2019 | 首期 “一生一芯”果壳处理器 | 5天成功启动Linux运行Busybox, 4天成功启动Debian运行GCC/QEMU |
2020 | 开源高性能RISC-V处理器香山 | 项目启动后第3周成功运行coremark, 第5周成功运行仙剑奇侠传, 第3个月成功启动Linux, 第4个月成功启动Debian |
2021 | 开源高性能RISC-V处理器香山 | 成功启动SMP Linux; 环境就绪后首次上FPGA即可正确跑完所有SPEC 2006 REF测试, 无需在板卡上调试任何处理器相关的bug |
2022 | 龙芯杯 | LoongArch赛道引入DiffTest帮助学生调试处理器, 团体赛不少启动Linux的队伍自发使用DiffTest |
2022 | 香山团队 | DiffTest工作被体系结构国际顶会MICRO录用 |
2021年RISC-V中国峰会, 工具类报告占香山团队报告总量55%(12/22)