2025-11-04(ALU)

在NPC上运行RT-Thread的时候,通过difftest发现NPC和NEMU在运行bgeu指令时出现了结果不一致,经过检查发现是NPC的实现有问题,主要是ALU这里实现的有问题。现在ALU的主要代码如下 现在的电路只对比较置位(slt,slti,sltiu)设置了比较,而对与条件跳转bge,bgeu,blt,bltu,现在的电路是让ALU执行减法运算然后检查ALUResult的31位,这种实现
2025-11-04(ALU)

2025-10-31

RT-Thread这里,为什么传参是个问题呢? kcontext把函数的地址,参数等上下文数据都保存在了栈底,然后返回这个上下文的地址。yield( )开始执行后,会跳转到__am_asm_trap这个函数开始执行,__am_asm_trap函数是用汇编写的,它首先会把上下文保存到栈中,然后把栈指针放到$a0寄存器,再调用__am_irq_handle函数,这个函数的参数是上下文指针,实际上就是$
2025-10-31

2025-10-30

要学习一下riscv汇编函数调用参数选择的规则。 实现上下文切换 按照讲义里的提示做就可以,也就是在调用__am_irq_handle完成之后,先修改栈指针的位置再恢复现场。那么问题就是调用__am_irq_handle结束之后这个新的上下文指针在哪里呢?如果熟悉riscv汇编的话应该能知道这个返回值的位置,或者查看反汇编代码也能知道这个值就在寄存器$a0里 所以只需要在调用__am_irq_ha
2025-10-30

2025-10-29

riscv通过ecall指令发起自陷,ecall指令会将将pc跳转到mtvec寄存器中的地址。程序通过cte_init将异常处理函数注册到mtvec寄存器中,同时将应用程序传来的处理函数句柄保存下来。mtvec中保存的程序地址是在汇编中定义的__am_asm_trap函数,这个函数里面会调用句柄中的函数。现在我不明白的是mtvec这个寄存器要放到哪里呢? ->答案就是有物理寄存器,跟32个通
2025-10-29

2025-10-28

键盘实现也很简单,代码如下 需要注意从寄存器获取的值最高位代表是按下还是松开,需要去掉最高位再返回给应用程序,否则会产生数组越界。 VGA这部分做起来意外的顺利。屏幕大小寄存器就是vgactl_port_base寄存器,宽度在高16位,高度在低16位,那么自然同步寄存器就是vga_port_base了,按照nemu中vga的注释,同步寄存器这样使用 一开始我以为这个也要做成回调函数,但
2025-10-28

2025-10-27

发现一个奇怪的现象,timer返回值发生在回调函数被调用之前,这样应用程序永远没法获得最新的时间。 原先nemu的timer回调函数如下 代码第3行表示读高地址时才更新时间,这样的问题是如果只读时间的低32位则时间就永远是初始时间,去掉地址的判断,把第3行改成下面的代码 系统就可以正常工作了。这里其实我早就注意到了,对timer工作方式也理解了,但是竟然一直没觉得这样是不对的。 总结一下am-ke
2025-10-27

2025-10-26

今天测试microbench的时候出现了更奇怪的问题,在执行完一个测试项之后堆的结束地址竟然发生了变化,之前我发现很多问题是我自己实现的printf有问题导致的,所以这次我直接用putstr来打印信息,最后定位到堆结束是在一轮测试结束后打印测试时间时出错的,也就是还有可能是printf导致的,于是我把printf注释掉,果然就可以了。。 printf还需要重新写
2025-10-26

2025-10-25

Dhrystone测试中Timer应该是有点问题,循环次数设置成500000次运行的时间还是0ms,这是不可能的。
2025-10-25

2025-10-24

今天重新写了printf的实现, 关闭itrace,drystone就通过不了,进一步定位,只要没有反汇编就会出错。发现可能不是某一个,而是随机的。 原因是系统运行太快了,计算dhrystone的时候出现除0的问题,跟trace没有关系,添加了itrace后系统运行会变慢。问题是运行真的有这么快吗?
2025-10-24