2025-10-15
今天进度还可以,完成了ftrace功能。实现ftrace的时候犯了一个错误:我认为凡是调用jalr或者jal的就是函数调用或者返回,其实不是这样,函数内部也会有跳转,所以函数返回要通过检测跳转的目的地址是否在某个函数的范围内而不是只检测目的地址是否是某个函数的其实地址。完成ftrace之后AM运行时环境计算完成了。
这个过程对整个系统有了新的理解,所谓nemu是一个模拟器,它模拟的就是一个可以执行程序的机器,或者说它是指令集的一种实现形式,后面要设计的npc也是指令集的一种实现形式。一生一芯之所以要在项目的前期安排这么多C语言的编程任务,一是让学习者可以在设计电路之前能理解cpu工作的原理,因为后面的npc和前面的nemu都只是不同的实现形式而已,如果理解了工作原理,后面的硬件设计也会容易一些;第二点是先实现一个标准模型来辅助后面的npc设计,即讲义中提到的differential testing。因为最近做了一个小项目的UVM验证环境我才对这种differential testing有了具体的体会,用UVM的话来说nemu就是后面npc的reference model,所以一生一芯前面安排的c语言编程任务,包括完善nemu和实现一些“基础设施”是很合理的。
nemu或者npc是执行程序的工具,和程序怎么生成的无关,而程序生成这又属于是另一块的知识了。这部分内容一生一芯大部分都帮我们实现好了,我们需要做的就是实现klib里的一些库函数还有为不同的执行工具生成合适的程序镜像(现在我的进度只看到了这些,后续可能还有其他的)。
开始实现npc的RTL实现,中间发现一个现象:在编译测试程序的时候,如果目标设置成riscv32e-npc,那么编译出的程序最后一条指令没有ebreak而是一个死循环。这个现象的原因是不同ARCH的halt函数定义不同,例如nemu的halt定义如下

而npc的halt定义如下

所以npc程序结束时就是死循环。为了方便测试打算在pnc读入程序镜像的时候将最后一条指令替换为ebreak。objcopy生成的bin文件有全0的指令,原因是objcopy默认会把所有的段都复制出来,如果只需要保存代码的话可以用下面的命令
objcopy -O binary -j .text xxx.elf xxx.bin
elf文件的各个段的作用还需要再详细学习总结一下
浙公网安备 33010602011771号