Chisel芯片开发入门系列 -- 17. CPU芯片开发和解释7(5级流水线指令原理)
进展很快----本文来到了CPU的多级流水线!如果不用Chisel语言而是使用Verilog语言,什么时候才能到CPU的多级流水线呢?而使用Chisel语言,在前面Level-0级别的入门九篇(1~9)之后,真正开始Leve-1级别CPU芯片开发入门是从第10篇开始,到现在的第17篇总共8篇就来到了CPU多级流水线!
按照此前针对Chipcamp的riscv-chisel-book项目下的chisel-template/src/main/scala目录的说明,其01->02->03->04->05都是在包含原有内容的基础上“增量”更新的!06和05基本一样。而06->07则又又又是“递增”的!也就是说,07_pipeline在05_riscvtests的基础上(或06_ctest的基础上)是递增的!我们看一下07和06的Core.scala文件的差异,主要就是增加了几段 stage_x_reg := stage_y_reg的代码!比如在Stage1和Stage2之间增加了Stage_2_reg := Stage_1_reg的代码!
难道这就是“多级流水线CPU”?是的!这就是多级流水线的CPU的“全部秘密”、“全部套路”!在Chisel代码中,多级流水线的“边界”,比如取指、译码、指令执行、写回,它们之间的边界,就是对代表寄存器的变量使用:=赋值的时候。每次对寄存器使用 :=
赋值时,代表数据从组合逻辑域进入时序逻辑域,形成流水级间的节点和界面。
说起来也简单,但要准确理解“多级流水线”,则需要实测,只有实测了才能整整理解。甚至在这个过程中,要有一些“踩坑”和“弯路”之后才能准确理解。下面结合实测来理解一下!
(1)先使用此前05_riscvtests用例所使用的hex文件!这个hex文件是在05_riscvtests时精心手搓生成并在05_riscvtests中测试通过的文件,一共包括Load1~Load6、Add1~Add5、Store1共12条指令(48行)。但这个文件在07_pipeline的测试例中则不能按照此前的预期实现6个整数的累加,这正是在作者在测试和理解CPU多级流水线时已经预期到的“弯路”和“坑”!!将这个指令序列命名为pipeline_bad.hex,其中最后的一个指令0x00001073在07_pipeline的电路代码中是一个用于结束测试的UNIMP指令,参见07_pipeline/Core.sala的io.exit := (id_reg_init === UNIMP)这一行。
看一下使用这个pipeline_bad.hex时的输出。这些输出打印的信息已经经过了代码修改以便于本文使用这些打印出来的调试信息进行解释。
$ sbt "testOnly pipeline.HexTest"
io.imem.addr=0x00000000, io.imem.inst=0x000c2203, io.dmem.addr=0x00000000, io.dmem.rdata=0x000c2203. //T0时刻 & Instruction1!
******** T_0 (IFetch): if_reg_pc = 0, if_inst = 0x000c2203 !!! //Fetch(Inst1)
******** T_1(IDecode): inst_code = 00000000. //Decode(null)
******** T_2(EXE): op1_data = 0, op2_data = 0, exe_alu_out = 0.
**** T_5(WB) LW/ADD WriteBack Finished: see the following regfile(wb_addr) where wb_addr= 0 !!!
if_reg_pc (T+0) : 0x00000000, inst_code: 0 (01 LW, 02 SW, 03 ADD)!
id_reg_pc (T+1) : 0x00000000
id_reg_inst : 0x00000000
exe_reg_pc (T+2) : 0x00000000
exe_reg_op1_data : 0x00000000
exe_reg_op2_data : 0x00000000
exe_alu_out : 0x00000000
mem_reg_pc (T+3) : 0x00000000
mem_wb_data : 0x00000000
**regfiles (T+5) : wb_addr= 0, regfiles(4/6/8/10/12/14)= 0 0 0 0 0 0 ****
---------END
io.imem.addr=0x00000004, io.imem.inst=0x004c2303, io.dmem.addr=0x00000000, io.dmem.rdata=0x000c2203. //T1时刻 & Instruction2
******** T_0 (IFetch): if_reg_pc = 4, if_inst = 0x004c2303 !!! //Fetch(inst2)
******** T_1(IDecode): inst_code = 00000001. //Decode(inst1)
******** T_2(EXE): op1_data = 0, op2_data = 0, exe_alu_out = 0.
******** T_3(Mem): Load(LW) PUT wire addr/wen/wdata = 0 0 0!!!
**** T_5(WB) LW/ADD WriteBack Finished: see the following regfile(wb_addr) where wb_addr= 0 !!!
if_reg_pc (T+0) : 0x00000004, inst_code: 1 (01 LW, 02 SW, 03 ADD)!
id_reg_pc (T+1) : 0x00000000
id_reg_inst : 0x000c2203
exe_reg_pc (T+2) : 0x00000000
exe_reg_op1_data : 0x00000000
exe_reg_op2_data : 0x00000000
exe_alu_out : 0x00000000
mem_reg_pc (T+3) : 0x00000000
mem_wb_data : 0x00000000
**regfiles (T+5) : wb_addr= 0, regfiles(4/6/8/10/12/14)= 0 0 0 0 0 0 ****
---------END
io.imem.addr=0x00000008, io.imem.inst=0x008c2403, io.dmem.addr=0x00000000, io.dmem.rdata=0x000c2203. //T2时刻 & Instruction3
******** T_0 (IFetch): if_reg_pc = 8, if_inst = 0x008c2403 !!! //Fetch(inst3)
******** T_1(IDecode): inst_code = 00000001. //Decode(inst2)
******** T_2(EXE): op1_data = 196, op2_data = 0, exe_alu_out = 196. //EX(inst1)
******** T_3(Mem): Load(LW) PUT wire addr/wen/wdata = 0 0 0!!!
**** T_5(WB) LW/ADD WriteBack Finished: see the following regfile(wb_addr) where wb_addr= 0 !!!
if_reg_pc (T+0) : 0x00000008, inst_code: 1 (01 LW, 02 SW, 03 ADD)!
id_reg_pc (T+1) : 0x00000004
id_reg_inst : 0x004c2303
exe_reg_pc (T+2) : 0x00000000
exe_reg_op1_data : 0x000000c4
exe_reg_op2_data : 0x00000000
exe_alu_out : 0x000000c4
mem_reg_pc (T+3) : 0x00000000
mem_wb_data : 0x00000000
**regfiles (T+5) : wb_addr= 0, regfiles(4/6/8/10/12/14)= 0 0 0 0 0 0 ****
---------END
io.imem.addr=0x0000000c, io.imem.inst=0x00cc2503, io.dmem.addr=0x000000c4, io.dmem.rdata=0x0000000a. //T3时刻 & Instruction4
******** T_0 (IFetch): if_reg_pc = 12, if_inst = 0x00cc2503 !!! //Fetch(inst4)
******** T_1(IDecode): inst_code = 00000001. //Decode(inst3)
******** T_2(EXE): op1_data = 196, op2_data = 4, exe_alu_out = 200. //Ex(inst2)
******** T_3(Mem): Load(LW) PUT wire addr/wen/wdata = 196 0 0!!! //Mem(inst1)
**** T_5(WB) LW/ADD WriteBack Finished: see the following regfile(wb_addr) where wb_addr= 0 !!!
if_reg_pc (T+0) : 0x0000000c, inst_code: 1 (01 LW, 02 SW, 03 ADD)!
id_reg_pc (T+1) : 0x00000008
id_reg_inst : 0x008c2403
exe_reg_pc (T+2) : 0x00000004
exe_reg_op1_data : 0x000000c4
exe_reg_op2_data : 0x00000004
exe_alu_out : 0x000000c8
mem_reg_pc (T+3) : 0x00000000
mem_wb_data : 0x0000000a
**regfiles (T+5) : wb_addr= 0, regfiles(4/6/8/10/12/14)= 0 0 0 0 0 0 ****
---------END
io.imem.addr=0x00000010, io.imem.inst=0x010c2603, io.dmem.addr=0x000000c8, io.dmem.rdata=0x0000000b. //T4时刻 & instruction5
******** T_0 (IFetch): if_reg_pc = 16, if_inst = 0x010c2603 !!! //Fetch(inst5)
******** T_1(IDecode): inst_code = 00000001. //Decode(inst4)
******** T_2(EXE): op1_data = 196, op2_data = 8, exe_alu_out = 204.//Ex(inst3)
******** T_3(Mem): Load(LW) PUT wire addr/wen/wdata = 200 0 0!!! //Mem(inst2)
**** T_4(WB) LW/ADD WriteBack (Need +1 to finish): wb_addr =4, wb_data = 10 !!! //Wb(inst1)
**** T_5(WB) LW/ADD WriteBack Finished: see the following regfile(wb_addr) where wb_addr= 4 !!!
if_reg_pc (T+0) : 0x00000010, inst_code: 1 (01 LW, 02 SW, 03 ADD)!
id_reg_pc (T+1) : 0x0000000c
id_reg_inst : 0x00cc2503
exe_reg_pc (T+2) : 0x00000008
exe_reg_op1_data : 0x000000c4
exe_reg_op2_data : 0x00000008
exe_alu_out : 0x000000cc
mem_reg_pc (T+3) : 0x00000004
mem_wb_data : 0x0000000b
**regfiles (T+5) : wb_addr= 4, regfiles(4/6/8/10/12/14)= 0 0 0 0 0 0 ****
---------END
io.imem.addr=0x00000014, io.imem.inst=0x014c2703, io.dmem.addr=0x000000cc, io.dmem.rdata=0x00000016. //T5时刻 & instruction6
******** T_0 (IFetch): if_reg_pc = 20, if_inst = 0x014c2703 !!! //Fetch(inst6)
******** T_1(IDecode): inst_code = 00000001. //Decode(inst5)
******** T_2(EXE): op1_data = 196, op2_data = 12, exe_alu_out = 208.//Ex(inst4)
******** T_3(Mem): Load(LW) PUT wire addr/wen/wdata = 204 0 0!!! //Mem(inst3)
**** T_4(WB) LW/ADD WriteBack (Need +1 to finish): wb_addr = 6, wb_data = 11 !!! //Wb(inst2)
**** T_5(WB) LW/ADD WriteBack Finished: see the following regfile(wb_addr) where wb_addr= 6 !!! //WbFinished(inst1) --刚刚把10这个数字写到reg4中。
if_reg_pc (T+0) : 0x00000014, inst_code: 1 (01 LW, 02 SW, 03 ADD)!
id_reg_pc (T+1) : 0x00000010
id_reg_inst : 0x010c2603
exe_reg_pc (T+2) : 0x0000000c
exe_reg_op1_data : 0x000000c4
exe_reg_op2_data : 0x0000000c
exe_alu_out : 0x000000d0
mem_reg_pc (T+3) : 0x00000008
mem_wb_data : 0x00000016
**regfiles (T+5) : wb_addr= 6, regfiles(4/6/8/10/12/14)= 10 0 0 0 0 0 ****
---------END
io.imem.addr=0x00000018, io.imem.inst=0x00620233, io.dmem.addr=0x000000d0, io.dmem.rdata=0x00000021. //T6时刻 &instruction 7。
******** T_0 (IFetch): if_reg_pc = 24, if_inst = 0x00620233 !!! //Fetch(inst7)
******** T_1(IDecode): inst_code = 00000001. //Decode(inst6)--Decode出(code=1)。
******** T_2(EXE): op1_data = 196, op2_data = 16, exe_alu_out = 212. //Ex(inst5)
******** T_3(Mem): Load(LW) PUT wire addr/wen/wdata = 208 0 0!!! //Mem(inst4)
**** T_4(WB) LW/ADD WriteBack (Need +1 to finish): wb_addr = 8, wb_data = 22 !!! //Wb(inst3)
**** T_5(WB) LW/ADD WriteBack Finished: see the following regfile(wb_addr) where wb_addr= 8 !!! //WbFinished(inst2) --刚刚把11这个数字写到reg6中。
if_reg_pc (T+0) : 0x00000018, inst_code: 1 (01 LW, 02 SW, 03 ADD)!
id_reg_pc (T+1) : 0x00000014
id_reg_inst : 0x014c2703
exe_reg_pc (T+2) : 0x00000010
exe_reg_op1_data : 0x000000c4
exe_reg_op2_data : 0x00000010
exe_alu_out : 0x000000d4
mem_reg_pc (T+3) : 0x0000000c
mem_wb_data : 0x00000021
**regfiles (T+5) : wb_addr= 8, regfiles(4/6/8/10/12/14)= 10 11 0 0 0 0 ****
---------END
io.imem.addr=0x0000001c, io.imem.inst=0x00820233, io.dmem.addr=0x000000d4, io.dmem.rdata=0x0000002c. //T7时刻 &instruction 8。
******** T_0 (IFetch): if_reg_pc = 28, if_inst = 0x00820233 !!! //Fetch(inst8)
******** T_1(IDecode): inst_code = 00000003. //Decode(inst7)
******** T_2(EXE): op1_data = 196, op2_data = 20, exe_alu_out = 216. //Ex(inst6)
**** T_4(WB) LW/ADD WriteBack (Need +1 to finish): wb_addr =10, wb_data = 33 !!! //Wb(inst4)
**** T_5(WB) LW/ADD WriteBack Finished: see the following regfile(wb_addr) where wb_addr= 10 !!! //WbFinished(inst3)
if_reg_pc (T+0) : 0x0000001c, inst_code: 3 (01 LW, 02 SW, 03 ADD)!
id_reg_pc (T+1) : 0x00000018
id_reg_inst : 0x00620233
exe_reg_pc (T+2) : 0x00000014
exe_reg_op1_data : 0x000000c4
exe_reg_op2_data : 0x00000014
exe_alu_out : 0x000000d8
mem_reg_pc (T+3) : 0x00000010
mem_wb_data : 0x0000002c
**regfiles (T+5) : wb_addr= 10, regfiles(4/6/8/10/12/14)= 10 11 22 0 0 0 ****
---------END
io.imem.addr=0x00000020, io.imem.inst=0x00a20233, io.dmem.addr=0x000000d8, io.dmem.rdata=0x00000037. //T8时刻 &instruction 9。
******** T_0 (IFetch): if_reg_pc = 32, if_inst = 0x00a20233 !!! //Fetch(inst9)
******** T_1(IDecode): inst_code = 00000003. //Decode(inst8)
******** T_2(EXE): op1_data = 10, op2_data = 11, exe_alu_out = 21. //Ex(inst7)
**** T_4(WB) LW/ADD WriteBack (Need +1 to finish): wb_addr =12, wb_data = 44 !!! //Wb(inst5)
**** T_5(WB) LW/ADD WriteBack Finished: see the following regfile(wb_addr) where wb_addr= 12 !!! //WbFinished(inst4)
if_reg_pc (T+0) : 0x00000020, inst_code: 3 (01 LW, 02 SW, 03 ADD)!
id_reg_pc (T+1) : 0x0000001c
id_reg_inst : 0x00820233
exe_reg_pc (T+2) : 0x00000018
exe_reg_op1_data : 0x0000000a
exe_reg_op2_data : 0x0000000b
exe_alu_out : 0x00000015
mem_reg_pc (T+3) : 0x00000014
mem_wb_data : 0x00000037
**regfiles (T+5) : wb_addr= 12, regfiles(4/6/8/10/12/14)= 10 11 22 33 0 0 ****
---------END
io.imem.addr=0x00000024, io.imem.inst=0x00c20233, io.dmem.addr=0x00000015, io.dmem.rdata=0x33014c27. //T9时刻 &instruction 10。
******** T_0 (IFetch): if_reg_pc = 36, if_inst = 0x00c20233 !!! //Fetch(inst10)
******** T_1(IDecode): inst_code = 00000003. //Decode(inst9)
******** T_2(EXE): op1_data = 10, op2_data = 22, exe_alu_out = 32. //Ex(inst8)
**** T_4(WB) LW/ADD WriteBack (Need +1 to finish): wb_addr =14, wb_data = 55 !!! //Wb(inst6)
**** T_5(WB) LW/ADD WriteBack Finished: see the following regfile(wb_addr) where wb_addr= 14 !!! //WbFinished(inst5) ----此时44被Load到regfile12中。
if_reg_pc (T+0) : 0x00000024, inst_code: 3 (01 LW, 02 SW, 03 ADD)!
id_reg_pc (T+1) : 0x00000020
id_reg_inst : 0x00a20233
exe_reg_pc (T+2) : 0x0000001c
exe_reg_op1_data : 0x0000000a
exe_reg_op2_data : 0x00000016
exe_alu_out : 0x00000020
mem_reg_pc (T+3) : 0x00000018
mem_wb_data : 0x00000015
**regfiles (T+5) : wb_addr= 14, regfiles(4/6/8/10/12/14)= 10 11 22 33 44 0 ****
---------END
io.imem.addr=0x00000028, io.imem.inst=0x00e20233, io.dmem.addr=0x00000020, io.dmem.rdata=0x00a20233. //T10时刻 &instruction 11。
******** T_0 (IFetch): if_reg_pc = 40, if_inst = 0x00e20233 !!! //Fetch(inst11)
******** T_1(IDecode): inst_code = 00000003. //Decode(inst10)
******** T_2(EXE): op1_data = 10, op2_data = 33, exe_alu_out = 43.//Ex(inst9)
**** T_4(WB) LW/ADD WriteBack (Need +1 to finish): wb_addr = 4, wb_data = 21 !!! //Wb(inst7)
**** T_5(WB) LW/ADD WriteBack Finished: see the following regfile(wb_addr) where wb_addr= 4 !!! //WbFinished(inst6) ----此时最后一个Load指令获得的数55被写入到寄存器regfile14中!
if_reg_pc (T+0) : 0x00000028, inst_code: 3 (01 LW, 02 SW, 03 ADD)!
id_reg_pc (T+1) : 0x00000024
id_reg_inst : 0x00c20233
exe_reg_pc (T+2) : 0x00000020
exe_reg_op1_data : 0x0000000a
exe_reg_op2_data : 0x00000021
exe_alu_out : 0x0000002b
mem_reg_pc (T+3) : 0x0000001c
mem_wb_data : 0x00000020
**regfiles (T+5) : wb_addr= 4, regfiles(4/6/8/10/12/14)= 10 11 22 33 44 55 ****
---------END
io.imem.addr=0x0000002c, io.imem.inst=0x04402023, io.dmem.addr=0x0000002b, io.dmem.rdata=0x40202300. //T11时刻 &instruction 12。
******** T_0 (IFetch): if_reg_pc = 44, if_inst = 0x04402023 !!! //Fetch(inst12)
******** T_1(IDecode): inst_code = 00000003. //Decode(inst11)
******** T_2(EXE): op1_data = 10, op2_data = 44, exe_alu_out = 54. //Ex(inst10)
**** T_4(WB) LW/ADD WriteBack (Need +1 to finish): wb_addr = 4, wb_data = 32 !!! //Wb(inst8)
**** T_5(WB) LW/ADD WriteBack Finished: see the following regfile(wb_addr) where wb_addr= 4 !!! //WbFinished(inst7) ----此时regfile4 + regfile 6 -> regfile4完成写入regfile4(值为21)。
if_reg_pc (T+0) : 0x0000002c, inst_code: 3 (01 LW, 02 SW, 03 ADD)!
id_reg_pc (T+1) : 0x00000028
id_reg_inst : 0x00e20233
exe_reg_pc (T+2) : 0x00000024
exe_reg_op1_data : 0x0000000a
exe_reg_op2_data : 0x0000002c
exe_alu_out : 0x00000036
mem_reg_pc (T+3) : 0x00000020
mem_wb_data : 0x0000002b
**regfiles (T+5) : wb_addr= 4, regfiles(4/6/8/10/12/14)= 21 11 22 33 44 55 ****
---------END
io.imem.addr=0x00000030, io.imem.inst=0xc0001073, io.dmem.addr=0x00000036, io.dmem.rdata=0x00000000. //T12时刻 &instruction 13(UNIMP指令)。
******** T_0 (IFetch): if_reg_pc = 48, if_inst = 0xc0001073 !!! //Fetch(inst13)
******** T_1(IDecode): inst_code = 00000002. //Decode(inst12)
******** T_2(EXE): op1_data = 21, op2_data = 55, exe_alu_out = 76. //Ex(inst10)-错误。
******** T_3(Mem): Store(SW) PUT wire addr/wen/wdata = 54 0 44!!! //Mem(inst9)
**** T_4(WB) LW/ADD WriteBack (Need +1 to finish): wb_addr = 4, wb_data = 43 !!! //Wb(inst8)
**** T_5(WB) LW/ADD WriteBack Finished: see the following regfile(wb_addr) where wb_addr= 4 !!! //WbFinished(inst7) -错误。此时regfile4中填入的值是32,预期10+11+22=43才对!
if_reg_pc (T+0) : 0x00000030, inst_code: 2 (01 LW, 02 SW, 03 ADD)!
id_reg_pc (T+1) : 0x0000002c
id_reg_inst : 0x04402023
exe_reg_pc (T+2) : 0x00000028
exe_reg_op1_data : 0x00000015
exe_reg_op2_data : 0x00000037
exe_alu_out : 0x0000004c
mem_reg_pc (T+3) : 0x00000024
mem_wb_data : 0x00000036
**regfiles (T+5) : wb_addr= 4, regfiles(4/6/8/10/12/14)= 32 11 22 33 44 55 ****
---------END
[info] HexTest:
[info] mycpu
[info] - should work through hex
[info] Run completed in 1 second, 853 milliseconds.
[info] Total number of tests run: 1
[info] Suites: completed 1, aborted 0
[info] Tests: succeeded 1, failed 0, canceled 0, ignored 0, pending 0
[info] All tests passed.
[success] Total time: 3 s, completed 2025骞?鏈?鏃?13:34:20
[0J
上面的注释虽然繁琐冗余,却是理解流水线、找出错误根源的“简单”方法!搜索【CPU Pipeline Stage Table】固然可以看到很好的图,但若没有上面繁琐冗余的trace过程则“体会”和“理解”就不会深。当然上面的注释也是参照了这个图以后做出的,就是怎么【梳理】并使用【文字/注释】表达出来、便于阅读理解和对CPU x-Stage Pipeline这一“前沿技术”的记忆的形成。
通过上面的注释和梳理出来的错误,简单总结一下:略。
解决的方法,在每个ADD指令之后,使用3个空指令(这里使用0x22222222, 0x22222222, 0x22222222),让5级流水线的指令走4步(ADD指令1步,空指令3步,此时WbFinished还没有完成,但已经非常接近了,wb_addr, wb_en, wb_data都已经就绪了,就剩下把它们的值传输到regfile4中,而这个“剩下”的工作,在下一个ADD指令到来的时候会“瞬间完成”!也可以认为它最先完成!比ADD指令中的regfile4+regfileX->regfile4的执行还要早!也比Store指令中的regfile4->memoryX的执行还要早!)。当然,在Store指令之后也增加3个空指令(同样使用0x22222222,0x44444444,0x22222222)。
参见下面的pipeline_bad.hex和pipeline_ok.hex的对比(在每个ADD指令及Store指令后增加3个无效指令作为空指令,保证在下一个ADD之前对reg4的WriteBack已经完成):
使用这个pipeline_ok.hex以后的测试结果:
$ sbt "testOnly pipeline.HexTest"
io.imem.addr=0x00000000, io.imem.inst=0x000c2203, io.dmem.addr=0x00000000, io.dmem.rdata=0x000c2203. //Instruction1--Fetch(dest=reg4, src=mem(reg(24)+0)
******** T_0 (IFetch): if_reg_pc = 0, if_inst = 0x000c2203 !!!
******** T_1(IDecode): inst_code = 00000000.
******** T_2(EXE): op1_data = 0, op2_data = 0, exe_alu_out = 0.
**** T_5(WB) LW/ADD WriteBack Finished: see the following regfile(wb_addr) where wb_addr= 0 !!!
if_reg_pc (T+0) : 0x00000000, inst_code: 0 (01 LW, 02 SW, 03 ADD)!
id_reg_pc (T+1) : 0x00000000
id_reg_inst : 0x00000000
exe_reg_pc (T+2) : 0x00000000
exe_reg_op1_data : 0x00000000
exe_reg_op2_data : 0x00000000
exe_alu_out : 0x00000000
mem_reg_pc (T+3) : 0x00000000
mem_wb_data : 0x00000000
**regfiles (T+5) : wb_addr= 0, regfiles(4/6/8/10/12/14)= 0 0 0 0 0 0 ****
---------END
io.imem.addr=0x00000004, io.imem.inst=0x004c2303, io.dmem.addr=0x00000000, io.dmem.rdata=0x000c2203. //Instruction2--Fetch(dest=reg6, src=mem(reg(24)+4)
******** T_0 (IFetch): if_reg_pc = 4, if_inst = 0x004c2303 !!!
******** T_1(IDecode): inst_code = 00000001.
******** T_2(EXE): op1_data = 0, op2_data = 0, exe_alu_out = 0.
******** T_3(Mem): Load(LW) PUT wire addr/wen/wdata = 0 0 0!!!
**** T_5(WB) LW/ADD WriteBack Finished: see the following regfile(wb_addr) where wb_addr= 0 !!!
if_reg_pc (T+0) : 0x00000004, inst_code: 1 (01 LW, 02 SW, 03 ADD)!
id_reg_pc (T+1) : 0x00000000
id_reg_inst : 0x000c2203
exe_reg_pc (T+2) : 0x00000000
exe_reg_op1_data : 0x00000000
exe_reg_op2_data : 0x00000000
exe_alu_out : 0x00000000
mem_reg_pc (T+3) : 0x00000000
mem_wb_data : 0x00000000
**regfiles (T+5) : wb_addr= 0, regfiles(4/6/8/10/12/14)= 0 0 0 0 0 0 ****
---------END
io.imem.addr=0x00000008, io.imem.inst=0x008c2403, io.dmem.addr=0x00000000, io.dmem.rdata=0x000c2203. //Instruction3--Fetch(dest=reg8, src=mem(reg(24)+8))
******** T_0 (IFetch): if_reg_pc = 8, if_inst = 0x008c2403 !!!
******** T_1(IDecode): inst_code = 00000001.
******** T_2(EXE): op1_data = 196, op2_data = 0, exe_alu_out = 196.
******** T_3(Mem): Load(LW) PUT wire addr/wen/wdata = 0 0 0!!!
**** T_5(WB) LW/ADD WriteBack Finished: see the following regfile(wb_addr) where wb_addr= 0 !!!
if_reg_pc (T+0) : 0x00000008, inst_code: 1 (01 LW, 02 SW, 03 ADD)!
id_reg_pc (T+1) : 0x00000004
id_reg_inst : 0x004c2303
exe_reg_pc (T+2) : 0x00000000
exe_reg_op1_data : 0x000000c4
exe_reg_op2_data : 0x00000000
exe_alu_out : 0x000000c4
mem_reg_pc (T+3) : 0x00000000
mem_wb_data : 0x00000000
**regfiles (T+5) : wb_addr= 0, regfiles(4/6/8/10/12/14)= 0 0 0 0 0 0 ****
---------END
io.imem.addr=0x0000000c, io.imem.inst=0x00cc2503, io.dmem.addr=0x000000c4, io.dmem.rdata=0x0000000a. //Instruction4--Fetch(dest=reg10, src=mem(reg(24)+12))
******** T_0 (IFetch): if_reg_pc = 12, if_inst = 0x00cc2503 !!!
******** T_1(IDecode): inst_code = 00000001.
******** T_2(EXE): op1_data = 196, op2_data = 4, exe_alu_out = 200.
******** T_3(Mem): Load(LW) PUT wire addr/wen/wdata = 196 0 0!!!
**** T_5(WB) LW/ADD WriteBack Finished: see the following regfile(wb_addr) where wb_addr= 0 !!!
if_reg_pc (T+0) : 0x0000000c, inst_code: 1 (01 LW, 02 SW, 03 ADD)!
id_reg_pc (T+1) : 0x00000008
id_reg_inst : 0x008c2403
exe_reg_pc (T+2) : 0x00000004
exe_reg_op1_data : 0x000000c4
exe_reg_op2_data : 0x00000004
exe_alu_out : 0x000000c8
mem_reg_pc (T+3) : 0x00000000
mem_wb_data : 0x0000000a
**regfiles (T+5) : wb_addr= 0, regfiles(4/6/8/10/12/14)= 0 0 0 0 0 0 ****
---------END
io.imem.addr=0x00000010, io.imem.inst=0x010c2603, io.dmem.addr=0x000000c8, io.dmem.rdata=0x0000000b. //Instruction5--Fetch(dest=reg12, src=mem(reg(24)+16))
******** T_0 (IFetch): if_reg_pc = 16, if_inst = 0x010c2603 !!!
******** T_1(IDecode): inst_code = 00000001.
******** T_2(EXE): op1_data = 196, op2_data = 8, exe_alu_out = 204.
******** T_3(Mem): Load(LW) PUT wire addr/wen/wdata = 200 0 0!!!
**** T_4(WB) LW/ADD WriteBack (Need +1 to finish): wb_addr = 4, wb_data = 10 !!!
**** T_5(WB) LW/ADD WriteBack Finished: see the following regfile(wb_addr) where wb_addr= 4 !!!
if_reg_pc (T+0) : 0x00000010, inst_code: 1 (01 LW, 02 SW, 03 ADD)!
id_reg_pc (T+1) : 0x0000000c
id_reg_inst : 0x00cc2503
exe_reg_pc (T+2) : 0x00000008
exe_reg_op1_data : 0x000000c4
exe_reg_op2_data : 0x00000008
exe_alu_out : 0x000000cc
mem_reg_pc (T+3) : 0x00000004
mem_wb_data : 0x0000000b
**regfiles (T+5) : wb_addr= 4, regfiles(4/6/8/10/12/14)= 0 0 0 0 0 0 ****
---------END
io.imem.addr=0x00000014, io.imem.inst=0x014c2703, io.dmem.addr=0x000000cc, io.dmem.rdata=0x00000016. //Instruction6--Fetch(dest=reg14, src=mem(reg(24)+20))
******** T_0 (IFetch): if_reg_pc = 20, if_inst = 0x014c2703 !!!
******** T_1(IDecode): inst_code = 00000001.
******** T_2(EXE): op1_data = 196, op2_data = 12, exe_alu_out = 208.
******** T_3(Mem): Load(LW) PUT wire addr/wen/wdata = 204 0 0!!!
**** T_4(WB) LW/ADD WriteBack (Need +1 to finish): wb_addr = 6, wb_data = 11 !!!
**** T_5(WB) LW/ADD WriteBack Finished: see the following regfile(wb_addr) where wb_addr= 6 !!!
if_reg_pc (T+0) : 0x00000014, inst_code: 1 (01 LW, 02 SW, 03 ADD)!
id_reg_pc (T+1) : 0x00000010
id_reg_inst : 0x010c2603
exe_reg_pc (T+2) : 0x0000000c
exe_reg_op1_data : 0x000000c4
exe_reg_op2_data : 0x0000000c
exe_alu_out : 0x000000d0
mem_reg_pc (T+3) : 0x00000008
mem_wb_data : 0x00000016
**regfiles (T+5) : wb_addr= 6, regfiles(4/6/8/10/12/14)= 10 0 0 0 0 0 ****
---------END
io.imem.addr=0x00000018, io.imem.inst=0x00620233, io.dmem.addr=0x000000d0, io.dmem.rdata=0x00000021. //Instruction7--Add(src1=reg4, src2=reg6, dst=reg4)。
******** T_0 (IFetch): if_reg_pc = 24, if_inst = 0x00620233 !!!
******** T_1(IDecode): inst_code = 00000001.
******** T_2(EXE): op1_data = 196, op2_data = 16, exe_alu_out = 212.
******** T_3(Mem): Load(LW) PUT wire addr/wen/wdata = 208 0 0!!!
**** T_4(WB) LW/ADD WriteBack (Need +1 to finish): wb_addr = 8, wb_data = 22 !!!
**** T_5(WB) LW/ADD WriteBack Finished: see the following regfile(wb_addr) where wb_addr= 8 !!!
if_reg_pc (T+0) : 0x00000018, inst_code: 1 (01 LW, 02 SW, 03 ADD)!
id_reg_pc (T+1) : 0x00000014
id_reg_inst : 0x014c2703
exe_reg_pc (T+2) : 0x00000010
exe_reg_op1_data : 0x000000c4
exe_reg_op2_data : 0x00000010
exe_alu_out : 0x000000d4
mem_reg_pc (T+3) : 0x0000000c
mem_wb_data : 0x00000021
**regfiles (T+5) : wb_addr= 8, regfiles(4/6/8/10/12/14)= 10 11 0 0 0 0 ****
---------END
io.imem.addr=0x0000001c, io.imem.inst=0x22222222, io.dmem.addr=0x000000d4, io.dmem.rdata=0x0000002c. //Instruction--空指令1
******** T_0 (IFetch): if_reg_pc = 28, if_inst = 0x22222222 !!!
******** T_1(IDecode): inst_code = 00000003.
******** T_2(EXE): op1_data = 196, op2_data = 20, exe_alu_out = 216.
**** T_4(WB) LW/ADD WriteBack (Need +1 to finish): wb_addr = 10, wb_data = 33 !!!
**** T_5(WB) LW/ADD WriteBack Finished: see the following regfile(wb_addr) where wb_addr= 10 !!!
if_reg_pc (T+0) : 0x0000001c, inst_code: 3 (01 LW, 02 SW, 03 ADD)!
id_reg_pc (T+1) : 0x00000018
id_reg_inst : 0x00620233
exe_reg_pc (T+2) : 0x00000014
exe_reg_op1_data : 0x000000c4
exe_reg_op2_data : 0x00000014
exe_alu_out : 0x000000d8
mem_reg_pc (T+3) : 0x00000010
mem_wb_data : 0x0000002c
**regfiles (T+5) : wb_addr= 10, regfiles(4/6/8/10/12/14)= 10 11 22 0 0 0 ****
---------END
io.imem.addr=0x00000020, io.imem.inst=0x44444444, io.dmem.addr=0x000000d8, io.dmem.rdata=0x00000037. //Instruction--空指令2
******** T_0 (IFetch): if_reg_pc = 32, if_inst = 0x44444444 !!!
******** T_1(IDecode): inst_code = 00000000.
******** T_2(EXE): op1_data = 10, op2_data = 11, exe_alu_out = 21. //此时ADD1执行正确!
**** T_4(WB) LW/ADD WriteBack (Need +1 to finish): wb_addr = 12, wb_data = 44 !!!
**** T_5(WB) LW/ADD WriteBack Finished: see the following regfile(wb_addr) where wb_addr= 12 !!!
if_reg_pc (T+0) : 0x00000020, inst_code: 0 (01 LW, 02 SW, 03 ADD)!
id_reg_pc (T+1) : 0x0000001c
id_reg_inst : 0x22222222
exe_reg_pc (T+2) : 0x00000018
exe_reg_op1_data : 0x0000000a
exe_reg_op2_data : 0x0000000b
exe_alu_out : 0x00000015
mem_reg_pc (T+3) : 0x00000014
mem_wb_data : 0x00000037
**regfiles (T+5) : wb_addr= 12, regfiles(4/6/8/10/12/14)= 10 11 22 33 0 0 ****
---------END
io.imem.addr=0x00000024, io.imem.inst=0x22222222, io.dmem.addr=0x00000015, io.dmem.rdata=0x33014c27. //Instruction--空指令3 (此时ADD1的T3执行完成)
******** T_0 (IFetch): if_reg_pc = 36, if_inst = 0x22222222 !!!
******** T_1(IDecode): inst_code = 00000000.
******** T_2(EXE): op1_data = 10, op2_data = 0, exe_alu_out = 0.
**** T_4(WB) LW/ADD WriteBack (Need +1 to finish): wb_addr = 14, wb_data = 55 !!!
**** T_5(WB) LW/ADD WriteBack Finished: see the following regfile(wb_addr) where wb_addr= 14 !!!
if_reg_pc (T+0) : 0x00000024, inst_code: 0 (01 LW, 02 SW, 03 ADD)!
id_reg_pc (T+1) : 0x00000020
id_reg_inst : 0x44444444
exe_reg_pc (T+2) : 0x0000001c
exe_reg_op1_data : 0x0000000a
exe_reg_op2_data : 0x00000000
exe_alu_out : 0x00000000
mem_reg_pc (T+3) : 0x00000018
mem_wb_data : 0x00000015
**regfiles (T+5) : wb_addr= 14, regfiles(4/6/8/10/12/14)= 10 11 22 33 44 0 ****
---------END
io.imem.addr=0x00000028, io.imem.inst=0x00820233, io.dmem.addr=0x00000000, io.dmem.rdata=0x000c2203. //第二个ADD指令(此时ADD1的T4步执行完成,ADD2的EX/T2步尚未执行)!
******** T_0 (IFetch): if_reg_pc = 40, if_inst = 0x00820233 !!!
******** T_1(IDecode): inst_code = 00000000.
******** T_2(EXE): op1_data = 22, op2_data = 10, exe_alu_out = 0.
**** T_4(WB) LW/ADD WriteBack (Need +1 to finish): wb_addr = 4, wb_data = 21 !!!
**** T_5(WB) LW/ADD WriteBack Finished: see the following regfile(wb_addr) where wb_addr= 4 !!!
if_reg_pc (T+0) : 0x00000028, inst_code: 0 (01 LW, 02 SW, 03 ADD)!
id_reg_pc (T+1) : 0x00000024
id_reg_inst : 0x22222222
exe_reg_pc (T+2) : 0x00000020
exe_reg_op1_data : 0x00000016
exe_reg_op2_data : 0x0000000a
exe_alu_out : 0x00000000
mem_reg_pc (T+3) : 0x0000001c
mem_wb_data : 0x00000000
**regfiles (T+5) : wb_addr= 4, regfiles(4/6/8/10/12/14)= 10 11 22 33 44 55 ****
---------END
io.imem.addr=0x0000002c, io.imem.inst=0x22222222, io.dmem.addr=0x00000000, io.dmem.rdata=0x000c2203. //Instruction--空指令1(此时ADD1的T5步执行完毕, ADD2的EX/T2步尚未执行!!)
******** T_0 (IFetch): if_reg_pc = 44, if_inst = 0x22222222 !!!
******** T_1(IDecode): inst_code = 00000003.
******** T_2(EXE): op1_data = 10, op2_data = 0, exe_alu_out = 0.
**** T_5(WB) LW/ADD WriteBack Finished: see the following regfile(wb_addr) where wb_addr= 4 !!!
if_reg_pc (T+0) : 0x0000002c, inst_code: 3 (01 LW, 02 SW, 03 ADD)!
id_reg_pc (T+1) : 0x00000028
id_reg_inst : 0x00820233
exe_reg_pc (T+2) : 0x00000024
exe_reg_op1_data : 0x0000000a
exe_reg_op2_data : 0x00000000
exe_alu_out : 0x00000000
mem_reg_pc (T+3) : 0x00000020
mem_wb_data : 0x00000000
**regfiles (T+5) : wb_addr= 4, regfiles(4/6/8/10/12/14)= 21 11 22 33 44 55 ****
---------END
io.imem.addr=0x00000030, io.imem.inst=0x44444444, io.dmem.addr=0x00000000, io.dmem.rdata=0x000c2203. //Instruction--空指令2
******** T_0 (IFetch): if_reg_pc = 48, if_inst = 0x44444444 !!!
******** T_1(IDecode): inst_code = 00000000.
******** T_2(EXE): op1_data = 21, op2_data = 22, exe_alu_out = 43.
**** T_5(WB) LW/ADD WriteBack Finished: see the following regfile(wb_addr) where wb_addr= 8 !!!
if_reg_pc (T+0) : 0x00000030, inst_code: 0 (01 LW, 02 SW, 03 ADD)!
id_reg_pc (T+1) : 0x0000002c
id_reg_inst : 0x22222222
exe_reg_pc (T+2) : 0x00000028
exe_reg_op1_data : 0x00000015
exe_reg_op2_data : 0x00000016
exe_alu_out : 0x0000002b
mem_reg_pc (T+3) : 0x00000024
mem_wb_data : 0x00000000
**regfiles (T+5) : wb_addr= 8, regfiles(4/6/8/10/12/14)= 21 11 22 33 44 55 ****
---------END
io.imem.addr=0x00000034, io.imem.inst=0x22222222, io.dmem.addr=0x0000002b, io.dmem.rdata=0x22222200. //Instruction--空指令3
******** T_0 (IFetch): if_reg_pc = 52, if_inst = 0x22222222 !!!
******** T_1(IDecode): inst_code = 00000000.
******** T_2(EXE): op1_data = 21, op2_data = 0, exe_alu_out = 0.
**** T_5(WB) LW/ADD WriteBack Finished: see the following regfile(wb_addr) where wb_addr= 4 !!!
if_reg_pc (T+0) : 0x00000034, inst_code: 0 (01 LW, 02 SW, 03 ADD)!
id_reg_pc (T+1) : 0x00000030
id_reg_inst : 0x44444444
exe_reg_pc (T+2) : 0x0000002c
exe_reg_op1_data : 0x00000015
exe_reg_op2_data : 0x00000000
exe_alu_out : 0x00000000
mem_reg_pc (T+3) : 0x00000028
mem_wb_data : 0x0000002b
**regfiles (T+5) : wb_addr= 4, regfiles(4/6/8/10/12/14)= 21 11 22 33 44 55 ****
---------END
io.imem.addr=0x00000038, io.imem.inst=0x00a20233, io.dmem.addr=0x00000000, io.dmem.rdata=0x000c2203. //ADD3指令。
******** T_0 (IFetch): if_reg_pc = 56, if_inst = 0x00a20233 !!!
******** T_1(IDecode): inst_code = 00000000.
******** T_2(EXE): op1_data = 22, op2_data = 21, exe_alu_out = 0.
**** T_4(WB) LW/ADD WriteBack (Need +1 to finish): wb_addr = 4, wb_data = 43 !!!
**** T_5(WB) LW/ADD WriteBack Finished: see the following regfile(wb_addr) where wb_addr= 4 !!!
if_reg_pc (T+0) : 0x00000038, inst_code: 0 (01 LW, 02 SW, 03 ADD)!
id_reg_pc (T+1) : 0x00000034
id_reg_inst : 0x22222222
exe_reg_pc (T+2) : 0x00000030
exe_reg_op1_data : 0x00000016
exe_reg_op2_data : 0x00000015
exe_alu_out : 0x00000000
mem_reg_pc (T+3) : 0x0000002c
mem_wb_data : 0x00000000
**regfiles (T+5) : wb_addr= 4, regfiles(4/6/8/10/12/14)= 21 11 22 33 44 55 ****
---------END
io.imem.addr=0x0000003c, io.imem.inst=0x22222222, io.dmem.addr=0x00000000, io.dmem.rdata=0x000c2203. //Instruction--空指令1
******** T_0 (IFetch): if_reg_pc = 60, if_inst = 0x22222222 !!!
******** T_1(IDecode): inst_code = 00000003.
******** T_2(EXE): op1_data = 21, op2_data = 0, exe_alu_out = 0.
**** T_5(WB) LW/ADD WriteBack Finished: see the following regfile(wb_addr) where wb_addr= 4 !!!
if_reg_pc (T+0) : 0x0000003c, inst_code: 3 (01 LW, 02 SW, 03 ADD)!
id_reg_pc (T+1) : 0x00000038
id_reg_inst : 0x00a20233
exe_reg_pc (T+2) : 0x00000034
exe_reg_op1_data : 0x00000015
exe_reg_op2_data : 0x00000000
exe_alu_out : 0x00000000
mem_reg_pc (T+3) : 0x00000030
mem_wb_data : 0x00000000
**regfiles (T+5) : wb_addr= 4, regfiles(4/6/8/10/12/14)= 43 11 22 33 44 55 ****
---------END
io.imem.addr=0x00000040, io.imem.inst=0x44444444, io.dmem.addr=0x00000000, io.dmem.rdata=0x000c2203. //Instruction--空指令2
******** T_0 (IFetch): if_reg_pc = 64, if_inst = 0x44444444 !!!
******** T_1(IDecode): inst_code = 00000000.
******** T_2(EXE): op1_data = 43, op2_data = 33, exe_alu_out = 76.
**** T_5(WB) LW/ADD WriteBack Finished: see the following regfile(wb_addr) where wb_addr= 8 !!!
if_reg_pc (T+0) : 0x00000040, inst_code: 0 (01 LW, 02 SW, 03 ADD)!
id_reg_pc (T+1) : 0x0000003c
id_reg_inst : 0x22222222
exe_reg_pc (T+2) : 0x00000038
exe_reg_op1_data : 0x0000002b
exe_reg_op2_data : 0x00000021
exe_alu_out : 0x0000004c
mem_reg_pc (T+3) : 0x00000034
mem_wb_data : 0x00000000
**regfiles (T+5) : wb_addr= 8, regfiles(4/6/8/10/12/14)= 43 11 22 33 44 55 ****
---------END
io.imem.addr=0x00000044, io.imem.inst=0x22222222, io.dmem.addr=0x0000004c, io.dmem.rdata=0x22222222. //Instruction--空指令3
******** T_0 (IFetch): if_reg_pc = 68, if_inst = 0x22222222 !!!
******** T_1(IDecode): inst_code = 00000000.
******** T_2(EXE): op1_data = 43, op2_data = 0, exe_alu_out = 0.
**** T_5(WB) LW/ADD WriteBack Finished: see the following regfile(wb_addr) where wb_addr= 4 !!!
if_reg_pc (T+0) : 0x00000044, inst_code: 0 (01 LW, 02 SW, 03 ADD)!
id_reg_pc (T+1) : 0x00000040
id_reg_inst : 0x44444444
exe_reg_pc (T+2) : 0x0000003c
exe_reg_op1_data : 0x0000002b
exe_reg_op2_data : 0x00000000
exe_alu_out : 0x00000000
mem_reg_pc (T+3) : 0x00000038
mem_wb_data : 0x0000004c
**regfiles (T+5) : wb_addr= 4, regfiles(4/6/8/10/12/14)= 43 11 22 33 44 55 ****
---------END
io.imem.addr=0x00000048, io.imem.inst=0x00c20233, io.dmem.addr=0x00000000, io.dmem.rdata=0x000c2203. //ADD4指令。
******** T_0 (IFetch): if_reg_pc = 72, if_inst = 0x00c20233 !!!
******** T_1(IDecode): inst_code = 00000000.
******** T_2(EXE): op1_data = 22, op2_data = 43, exe_alu_out = 0.
**** T_4(WB) LW/ADD WriteBack (Need +1 to finish): wb_addr = 4, wb_data = 76 !!!
**** T_5(WB) LW/ADD WriteBack Finished: see the following regfile(wb_addr) where wb_addr= 4 !!!
if_reg_pc (T+0) : 0x00000048, inst_code: 0 (01 LW, 02 SW, 03 ADD)!
id_reg_pc (T+1) : 0x00000044
id_reg_inst : 0x22222222
exe_reg_pc (T+2) : 0x00000040
exe_reg_op1_data : 0x00000016
exe_reg_op2_data : 0x0000002b
exe_alu_out : 0x00000000
mem_reg_pc (T+3) : 0x0000003c
mem_wb_data : 0x00000000
**regfiles (T+5) : wb_addr= 4, regfiles(4/6/8/10/12/14)= 43 11 22 33 44 55 ****
---------END
io.imem.addr=0x0000004c, io.imem.inst=0x22222222, io.dmem.addr=0x00000000, io.dmem.rdata=0x000c2203. //Instruction--空指令1
******** T_0 (IFetch): if_reg_pc = 76, if_inst = 0x22222222 !!!
******** T_1(IDecode): inst_code = 00000003.
******** T_2(EXE): op1_data = 43, op2_data = 0, exe_alu_out = 0.
**** T_5(WB) LW/ADD WriteBack Finished: see the following regfile(wb_addr) where wb_addr= 4 !!!
if_reg_pc (T+0) : 0x0000004c, inst_code: 3 (01 LW, 02 SW, 03 ADD)!
id_reg_pc (T+1) : 0x00000048
id_reg_inst : 0x00c20233
exe_reg_pc (T+2) : 0x00000044
exe_reg_op1_data : 0x0000002b
exe_reg_op2_data : 0x00000000
exe_alu_out : 0x00000000
mem_reg_pc (T+3) : 0x00000040
mem_wb_data : 0x00000000
**regfiles (T+5) : wb_addr= 4, regfiles(4/6/8/10/12/14)= 76 11 22 33 44 55 ****
---------END
io.imem.addr=0x00000050, io.imem.inst=0x44444444, io.dmem.addr=0x00000000, io.dmem.rdata=0x000c2203. //Instruction--空指令2
******** T_0 (IFetch): if_reg_pc = 80, if_inst = 0x44444444 !!!
******** T_1(IDecode): inst_code = 00000000.
******** T_2(EXE): op1_data = 76, op2_data = 44, exe_alu_out = 120.
**** T_5(WB) LW/ADD WriteBack Finished: see the following regfile(wb_addr) where wb_addr= 8 !!!
if_reg_pc (T+0) : 0x00000050, inst_code: 0 (01 LW, 02 SW, 03 ADD)!
id_reg_pc (T+1) : 0x0000004c
id_reg_inst : 0x22222222
exe_reg_pc (T+2) : 0x00000048
exe_reg_op1_data : 0x0000004c
exe_reg_op2_data : 0x0000002c
exe_alu_out : 0x00000078
mem_reg_pc (T+3) : 0x00000044
mem_wb_data : 0x00000000
**regfiles (T+5) : wb_addr= 8, regfiles(4/6/8/10/12/14)= 76 11 22 33 44 55 ****
---------END
io.imem.addr=0x00000054, io.imem.inst=0x22222222, io.dmem.addr=0x00000078, io.dmem.rdata=0xc0001073. //Instruction--空指令3
******** T_0 (IFetch): if_reg_pc = 84, if_inst = 0x22222222 !!!
******** T_1(IDecode): inst_code = 00000000.
******** T_2(EXE): op1_data = 76, op2_data = 0, exe_alu_out = 0.
**** T_5(WB) LW/ADD WriteBack Finished: see the following regfile(wb_addr) where wb_addr= 4 !!!
if_reg_pc (T+0) : 0x00000054, inst_code: 0 (01 LW, 02 SW, 03 ADD)!
id_reg_pc (T+1) : 0x00000050
id_reg_inst : 0x44444444
exe_reg_pc (T+2) : 0x0000004c
exe_reg_op1_data : 0x0000004c
exe_reg_op2_data : 0x00000000
exe_alu_out : 0x00000000
mem_reg_pc (T+3) : 0x00000048
mem_wb_data : 0x00000078
**regfiles (T+5) : wb_addr= 4, regfiles(4/6/8/10/12/14)= 76 11 22 33 44 55 ****
---------END
io.imem.addr=0x00000058, io.imem.inst=0x00e20233, io.dmem.addr=0x00000000, io.dmem.rdata=0x000c2203. //ADD5指令。
******** T_0 (IFetch): if_reg_pc = 88, if_inst = 0x00e20233 !!!
******** T_1(IDecode): inst_code = 00000000.
******** T_2(EXE): op1_data = 22, op2_data = 76, exe_alu_out = 0.
**** T_4(WB) LW/ADD WriteBack (Need +1 to finish): wb_addr = 4, wb_data = 120 !!!
**** T_5(WB) LW/ADD WriteBack Finished: see the following regfile(wb_addr) where wb_addr= 4 !!!
if_reg_pc (T+0) : 0x00000058, inst_code: 0 (01 LW, 02 SW, 03 ADD)!
id_reg_pc (T+1) : 0x00000054
id_reg_inst : 0x22222222
exe_reg_pc (T+2) : 0x00000050
exe_reg_op1_data : 0x00000016
exe_reg_op2_data : 0x0000004c
exe_alu_out : 0x00000000
mem_reg_pc (T+3) : 0x0000004c
mem_wb_data : 0x00000000
**regfiles (T+5) : wb_addr= 4, regfiles(4/6/8/10/12/14)= 76 11 22 33 44 55 ****
---------END
io.imem.addr=0x0000005c, io.imem.inst=0x22222222, io.dmem.addr=0x00000000, io.dmem.rdata=0x000c2203. //Instruction--空指令1
******** T_0 (IFetch): if_reg_pc = 92, if_inst = 0x22222222 !!!
******** T_1(IDecode): inst_code = 00000003.
******** T_2(EXE): op1_data = 76, op2_data = 0, exe_alu_out = 0.
**** T_5(WB) LW/ADD WriteBack Finished: see the following regfile(wb_addr) where wb_addr= 4 !!!
if_reg_pc (T+0) : 0x0000005c, inst_code: 3 (01 LW, 02 SW, 03 ADD)!
id_reg_pc (T+1) : 0x00000058
id_reg_inst : 0x00e20233
exe_reg_pc (T+2) : 0x00000054
exe_reg_op1_data : 0x0000004c
exe_reg_op2_data : 0x00000000
exe_alu_out : 0x00000000
mem_reg_pc (T+3) : 0x00000050
mem_wb_data : 0x00000000
**regfiles (T+5) : wb_addr= 4, regfiles(4/6/8/10/12/14)= 120 11 22 33 44 55 ****
---------END
io.imem.addr=0x00000060, io.imem.inst=0x44444444, io.dmem.addr=0x00000000, io.dmem.rdata=0x000c2203. //Instruction--空指令2
******** T_0 (IFetch): if_reg_pc = 96, if_inst = 0x44444444 !!!
******** T_1(IDecode): inst_code = 00000000.
******** T_2(EXE): op1_data = 120, op2_data = 55, exe_alu_out = 175.
**** T_5(WB) LW/ADD WriteBack Finished: see the following regfile(wb_addr) where wb_addr= 8 !!!
if_reg_pc (T+0) : 0x00000060, inst_code: 0 (01 LW, 02 SW, 03 ADD)!
id_reg_pc (T+1) : 0x0000005c
id_reg_inst : 0x22222222
exe_reg_pc (T+2) : 0x00000058
exe_reg_op1_data : 0x00000078
exe_reg_op2_data : 0x00000037
exe_alu_out : 0x000000af
mem_reg_pc (T+3) : 0x00000054
mem_wb_data : 0x00000000
**regfiles (T+5) : wb_addr= 8, regfiles(4/6/8/10/12/14)= 120 11 22 33 44 55 ****
---------END
io.imem.addr=0x00000064, io.imem.inst=0x22222222, io.dmem.addr=0x000000af, io.dmem.rdata=0x00000000. //Instruction--空指令3
******** T_0 (IFetch): if_reg_pc = 100, if_inst = 0x22222222 !!!
******** T_1(IDecode): inst_code = 00000000.
******** T_2(EXE): op1_data = 120, op2_data = 0, exe_alu_out = 0.
**** T_5(WB) LW/ADD WriteBack Finished: see the following regfile(wb_addr) where wb_addr= 4 !!!
if_reg_pc (T+0) : 0x00000064, inst_code: 0 (01 LW, 02 SW, 03 ADD)!
id_reg_pc (T+1) : 0x00000060
id_reg_inst : 0x44444444
exe_reg_pc (T+2) : 0x0000005c
exe_reg_op1_data : 0x00000078
exe_reg_op2_data : 0x00000000
exe_alu_out : 0x00000000
mem_reg_pc (T+3) : 0x00000058
mem_wb_data : 0x000000af
**regfiles (T+5) : wb_addr= 4, regfiles(4/6/8/10/12/14)= 120 11 22 33 44 55 ****
---------END
io.imem.addr=0x00000068, io.imem.inst=0x04402023, io.dmem.addr=0x00000000, io.dmem.rdata=0x000c2203. //Store指令!
******** T_0 (IFetch): if_reg_pc = 104, if_inst = 0x04402023 !!!
******** T_1(IDecode): inst_code = 00000000.
******** T_2(EXE): op1_data = 22, op2_data = 120, exe_alu_out = 0.
**** T_4(WB) LW/ADD WriteBack (Need +1 to finish): wb_addr = 4, wb_data = 175 !!!
**** T_5(WB) LW/ADD WriteBack Finished: see the following regfile(wb_addr) where wb_addr= 4 !!!
if_reg_pc (T+0) : 0x00000068, inst_code: 0 (01 LW, 02 SW, 03 ADD)!
id_reg_pc (T+1) : 0x00000064
id_reg_inst : 0x22222222
exe_reg_pc (T+2) : 0x00000060
exe_reg_op1_data : 0x00000016
exe_reg_op2_data : 0x00000078
exe_alu_out : 0x00000000
mem_reg_pc (T+3) : 0x0000005c
mem_wb_data : 0x00000000
**regfiles (T+5) : wb_addr= 4, regfiles(4/6/8/10/12/14)= 120 11 22 33 44 55 ****
---------END
io.imem.addr=0x0000006c, io.imem.inst=0x22222222, io.dmem.addr=0x00000000, io.dmem.rdata=0x000c2203. //Instruction--空指令1 (Store的T1执行完)
******** T_0 (IFetch): if_reg_pc = 108, if_inst = 0x22222222 !!!
******** T_1(IDecode): inst_code = 00000002.
******** T_2(EXE): op1_data = 120, op2_data = 0, exe_alu_out = 0.
******** T_3(Mem): Store(SW) PUT wire addr/wen/wdata = 0 0 120!!!
**** T_5(WB) LW/ADD WriteBack Finished: see the following regfile(wb_addr) where wb_addr= 4 !!!
if_reg_pc (T+0) : 0x0000006c, inst_code: 2 (01 LW, 02 SW, 03 ADD)!
id_reg_pc (T+1) : 0x00000068
id_reg_inst : 0x04402023
exe_reg_pc (T+2) : 0x00000064
exe_reg_op1_data : 0x00000078
exe_reg_op2_data : 0x00000000
exe_alu_out : 0x00000000
mem_reg_pc (T+3) : 0x00000060
mem_wb_data : 0x00000000
**regfiles (T+5) : wb_addr= 4, regfiles(4/6/8/10/12/14)= 175 11 22 33 44 55 ****
---------END
io.imem.addr=0x00000070, io.imem.inst=0x44444444, io.dmem.addr=0x00000000, io.dmem.rdata=0x000c2203. //Instruction--空指令2 (Store的T2执行完)
******** T_0 (IFetch): if_reg_pc = 112, if_inst = 0x44444444 !!!
******** T_1(IDecode): inst_code = 00000000.
******** T_2(EXE): op1_data = 0, op2_data = 64, exe_alu_out = 64.
**** T_5(WB) LW/ADD WriteBack Finished: see the following regfile(wb_addr) where wb_addr= 8 !!!
if_reg_pc (T+0) : 0x00000070, inst_code: 0 (01 LW, 02 SW, 03 ADD)!
id_reg_pc (T+1) : 0x0000006c
id_reg_inst : 0x22222222
exe_reg_pc (T+2) : 0x00000068
exe_reg_op1_data : 0x00000000
exe_reg_op2_data : 0x00000040
exe_alu_out : 0x00000040
mem_reg_pc (T+3) : 0x00000064
mem_wb_data : 0x00000000
**regfiles (T+5) : wb_addr= 8, regfiles(4/6/8/10/12/14)= 175 11 22 33 44 55 ****
---------END
io.imem.addr=0x00000074, io.imem.inst=0x22222222, io.dmem.addr=0x00000040, io.dmem.rdata=0x44444444. //Instruction--空指令3 (Store的T3执行完)
io.dmem.addr=0x00000040, io.dmem.wdata=0x000000af.
******** T_0 (IFetch): if_reg_pc = 116, if_inst = 0x22222222 !!!
******** T_1(IDecode): inst_code = 00000000.
******** T_2(EXE): op1_data = 175, op2_data = 0, exe_alu_out = 0.
**** T_5(WB) LW/ADD WriteBack Finished: see the following regfile(wb_addr) where wb_addr= 4 !!!
if_reg_pc (T+0) : 0x00000074, inst_code: 0 (01 LW, 02 SW, 03 ADD)!
id_reg_pc (T+1) : 0x00000070
id_reg_inst : 0x44444444
exe_reg_pc (T+2) : 0x0000006c
exe_reg_op1_data : 0x000000af
exe_reg_op2_data : 0x00000000
exe_alu_out : 0x00000000
mem_reg_pc (T+3) : 0x00000068
mem_wb_data : 0x00000040
**regfiles (T+5) : wb_addr= 4, regfiles(4/6/8/10/12/14)= 175 11 22 33 44 55 ****
---------END
io.imem.addr=0x00000078, io.imem.inst=0xc0001073, io.dmem.addr=0x00000000, io.dmem.rdata=0x000c2203. //UNIMP指令用于io.exit置位指示退出!此时Store指令T4执行完了。
******** T_0 (IFetch): if_reg_pc = 120, if_inst = 0xc0001073 !!!
******** T_1(IDecode): inst_code = 00000000.
******** T_2(EXE): op1_data = 22, op2_data = 175, exe_alu_out = 0.
**** T_5(WB) LW/ADD WriteBack Finished: see the following regfile(wb_addr) where wb_addr= 0 !!!
if_reg_pc (T+0) : 0x00000078, inst_code: 0 (01 LW, 02 SW, 03 ADD)!
id_reg_pc (T+1) : 0x00000074
id_reg_inst : 0x22222222
exe_reg_pc (T+2) : 0x00000070
exe_reg_op1_data : 0x00000016
exe_reg_op2_data : 0x000000af
exe_alu_out : 0x00000000
mem_reg_pc (T+3) : 0x0000006c
mem_wb_data : 0x00000000
**regfiles (T+5) : wb_addr= 0, regfiles(4/6/8/10/12/14)= 175 11 22 33 44 55 ****
---------END
[info] HexTest:
[info] mycpu
[info] - should work through hex
[info] Run completed in 2 seconds, 187 milliseconds.
[info] Total number of tests run: 1
[info] Suites: completed 1, aborted 0
[info] Tests: succeeded 1, failed 0, canceled 0, ignored 0, pending 0
[info] All tests passed.
[success] Total time: 3 s, completed 2025骞?鏈?鏃?14:33:55
[0J
至此,本文介绍了Chisel实现CPU的多级流水线的原理,并通过实际的指令序列的执行来理解CPU多级流水线的流水线冒险,指令空泡等现象。
本文所涉及的代码已经提交到项目库(ChipCamp/riscv-chisel-book)。请熟练使用gitcode并关注本项目,实际操作才能真正入门。