这是我的《自己动手写CPU》的学习记录,本书code可以从 https://github.com/Z-Y00/Examples-in-book-write-your-own-cpu 获取,感谢作者雷思磊的开源.
安装Modelsim ,配置环境 ,画框架图,了解mips
完成初始openmips_min
完成openmips_min_spoc并完成仿真验证第一条指令ori的实现
完成第四章
添加i指令和中断一些指令,并通过仿真验证
完成第五章
添加mov指令,并完成仿真验证
添加 movn movz mfhi mflo mthi mtlo指令
其中,在实现数据依赖时仿真mfhi和mflo时出现传递后要传入的寄存器清空为X,后经过验证查找发现是openmips调用时传错参数,还是要多看框架图
初步完成arth基本算术指令,其中 addi 出现问题,add &3, &3, 2时,寄存器3无变化,然后stimulate模拟全过程
观察id阶段指令aluop_i正确,立即数imm 2正确,ex 输出结果正确,mem阶段正确,wb写入正确,然后发现结果又对了。
(ps:可能是vscode和modelsim编程和仿真分离的原因。没有同步,导致使用之前未修改的版本导致的)
完成arth,其中slti 和sltiu 使用的是 slt和sltu的标识码,因为没有明显区分,所以可以调用,这里需要注意
还有mul指令乘数,被乘数,结果 的正负判断需要注意
完成ctrl指令,设计MADD,MADDU,MSUB,MSUBU 指令。
实现MADD,MADDU,MSUB,MSUBU,其中stallreq出现错误,ex中的stallreq忘记赋值导致错误。同时仿真发现MADD,MADDU可行,但是MSUB,MSUBU不可行,modelsim报错LOOP,但是实际不会进入循环(因为没有循环),让人费解
解决问题,通过计算并未发现问题,通过和作者源代码比较,发现只有
end else if ((aluop_i == `EXE_MSUB_OP) || (aluop_i == `EXE_MSUBU_OP)) begin
whilo_o <= `WriteEnable;
hi_o <=hilo_temp1[63:32];
lo_o <=hilo_temp1[31:0];
end else if ((aluop_i == `EXE_MADD_OP) || (aluop_i == `EXE_MADDU_OP)) begin
whilo_o <= `WriteEnable;
hi_o <=hilo_temp1[63:32];
lo_o <=hilo_temp1[31:0];
这段代码不同,我之前认为他们可以放在一起,因为他们功能一样,操作一样。现在看来可能是仿真模拟的时候是不一样的,导致错误。(奇怪,先搁置)
完成div.v试商法的设计,拓展testbench的时间。
实现div,divu指令,添加div,并仿真验证。
实现转移指令j b,通过延迟槽实现,并仿真验证。
load store 指令
完成load store,并仿真验证
loadstore指令中lwl,lwr类load指令需要从内存中读取到寄存器,可能造成数据依赖,所以需要对前一条指令进行记录,并流水线停顿id阶段等待。
修改id避免数据依赖。
完成 ll sc 原子操作指令和LLbit寄存器,并仿真验证