QEMU 训练营 2026 专业阶段总结¶
主要贡献者
- 作者:2359912755
背景介绍¶
本人是从事驱动开发工作,但平时开发只着重于驱动自身,忽略 qemu 平台以及 model 自身,对这些东西不是很了解,故希望参加此次训练营,来补充这方面知识,提高自己对 qemu 平台的能力和对 model 的理解
专业阶段¶
完成的是专业阶段 GPGPU 方向的实验
¶
实验总共 10 个,其中从第 8 个实验开始才涉及 kernel 的执行,所以前 7 个实验基本都是来模拟 mmio 的实现
前面的实验开始需要理解 qemu object model,qemu 就是通过这个东西来实现面向对象。当我们注册并实现一个 pci 设备后,接下来就需要实现各自 bar 并映射 mmio 区域,目前只涉及 bar0 和 bar2 其中 bar0 主要用来暴露设备信息,控制寄存器,dma 以及 kernel 相关寄存器,大小为 1m,按部就班实现即可 bar2 主要用来 vram 访问使用,也可以直接通过 mmio 来实现
实现 1-7 需要注意的地方是有些寄存器每个 bit 可能有不同用处,清零时要只针对单个 bit,不能针对整个寄存器进行清零,还有就是需要做边界检查,包括 VRAM 的访问
从实验 8 开始就正式进入了 kernel 相关
当 mmio 写 dispatch 寄存器时候,就会触发 gpgpu core 开始执行,其相关实现都在 gpgpu_core.c 这个文件里
由于 GPU 的调度是以 warp 作为基本单位,所以我们必须遍历所有的 dim 来展开 warp,每个 warp 有 32 个 lane,每个 lane 包含 PC,gpr,fpr,hart id, activeFlag 等,warp 则包含所有的 lane,warp 的 active_mask(可以只激活部分 lane),thread_id_base,warp_id,block id 等
在 gpgpu_core_init_warp 这个 func 中需要实现为每个活跃 lane 设置 pc(指向入口),编码 hart id,寄存器清零,浮点状态初始化
gpgpu_core_exec_warp 则是真正的 warp 执行 func,需要实现取值,解码,执行,写回等 代码实现如下
while(cycle < max_cycles && warp->active_mask != 0)
{
uint32_t pc = lane0->pc;//简化设计
uint32_t fetch_addr = pc;
uint32_t ins = *(uint32_t *)(s->vram_ptr + fetch_addr);
//decode
uint32_t opcode = ins & 0x7f;
//...........
switch(opcode)
{
//......这里需要注意每条指令执行的时候由于我们也是基于 warp 的,所以也需要 loop 所有有效的 lane
}
lane0->pc += 4;
cycle++;
}
//另外在指令模拟时候最好每添加一条指令就加上指令的 log,不然后面 debug 十分麻烦
同时这里也学习了 risc v 指令,risc v 指令有如下 6 种指令格式
具体指令模拟的方法可以参考 vortex,或者 ai 给出
实验 9 这里涉及浮点指令模拟,需要注意的是我们 fpr 也是用 uint32_t 模拟,所以在模拟 FCVT.S.W 这种指令时候,需要使用 memcpy,不能直接赋值转换,FCVT.W.S 还需要注意舍入模式
实验 10 涉及一些特殊浮点数格式,主要有 BF16 E4M3 E5M2 E2M1
FP16:sign 1bit, exponent 5bit , fraction 10bit BF16:sign 1bit, exponent 8bit , fraction 7bit E4M3:sign 1bit, exponent 4bit , fraction 3bit E5M2:sign 1bit, exponent 5bit , fraction 2bit E2M1:sign 1bit, exponent 2bit , fraction 1bit
添加对应格式的转换函数即可,这个实验难点在于指令比较多,即使有 log,也会非常多,想偷懒可以交给 ai 审查代码
总结¶
通过本次实验学到了很多东西,比如 pci 设备模拟以及 riscv 指令解析,也学到了很多浮点数相关知识,对理解指令会很有帮助
由于时间原因,为了通过测试,简化了很多设计,只相当于了实现指令的解析,并没有真正完成 simt 栈的模拟,但这个相当于打开学习模拟器的入门,后续准备来学习真正的 gpu 模拟器来补充这方面知识。
建议后续学员学习时候 log 机制一定要一开始设计好,指令多起来后如果 log 比较混乱,观感会非常差,还有就是可以同时对比其他开源 GPU 模拟器来学习,这样更有助于理解