1、实验报告课程名称:计算机系统结构实验学 院:计算机科学与工程学院专 业:计算机科学与技术指导教师:好老师学生姓名:爱学习的大哥哥 2014666666666实验成绩:日 期:2017 年 5 月 26 日电子科技大学计算机学院实验中心1 / 9电 子 科 技 大 学实 验 报 告一、 实验项目名称:解决控制冒险二、 实验室名称:主楼 A2-412 实验时间:2017 年 5 月 26 日三、 实验目的在给出的流水线代码基础上,增加 ID 级关闭写使能信号,以解决不正确分支指令的影响。通过完成这次实验,加深对控制冒险现象的产生和消除控制冒险的原理的理解,提高编程和测试的能力。四、 实验原理(一)
2、 转移相关问题转移指令改变程序顺序执行的特性。由于是流水线操作,在转移发生之前,若干条转移指令的后续指令已被取到流水线处理机中。这就是所谓的转移相关问题(branch hazard ) ,有时也称之为控制相关问题(control hazard ) 。回顾我们前面介绍的处理转移相关问题的 4 种技术:以上任何一种方法都会使硬件固定,编译时会根据硬件机制和转移行为对代码进行调度,以获取最佳性能。(二) 消除无条件转移指令的后一条指令影响每条指令在 ID 时判断在当前在 EXE 阶段的操作码暂存器的值是否是无条件转移指令:如果是,那么不使能当前在 ID 阶段的那条指令的 WZ、WMEM 和 WREG
3、 的信号,这2 / 9样这条指令的执行就对程序的逻辑没有影响。(三) 条件转移指令条件转移指令的实现思想与无条件转移指令有所类似,但不完全相同。首先对于条件转移指令本身来说,需要判断 Z 标志是否能用。若 Z 标志还没有准备好,则要暂停流水线一个时钟周期。这一点和判断数据相关极为相似。但由于转移指令只可能改变 PC 而不改变其它状态,因此用不着封锁 WZ,WMEM ,WREG(对转移指令来讲,这些信号原本就为 0) 。因为如果处在译码级的是条件转移指令,而且处在 EXE 级的是 ALU 类型的指令(就要写 Z 标志到流水线寄存器 Z 了) ,则要等到 ALU 指令写完 Z 后,再判断转移与否,
4、为此要暂停一个周期( 或者如前所述,插入一条 nop 指令)。对于条件转移指令的下一条指令的处理办法与无条件指令不同。因为条件转移的下一条指令有可能执行也有可能不执行,需要在对无条件转移指令的处理策略上进行扩展:条件转移的下一条指令在 ID 时判断在当前在 EXE 阶段的操作码暂存器的值是否是条件转移指令并且判断是否转移成功(Z 的值没变),如果发现成功,那么不使能当前在 ID 阶段的那条指令的 WZ、WMEM 和 WREG 的信号,这条指令的执行就对程序的逻辑没有影响(与无条件处理方式相同);如果发现转移不成功,说明本条指令为有效指令,使能当前在 ID 阶段的那条指令的 WZ、WMEM 和
5、WREG 的信号,本条指令正常执行。五、 实验内容在给出的流水线代码基础上,增加 ID 级关闭写使能信号,以解决不正确分支指令的影响。六、 实验器材(设备、元器件)ISE Design Suite 14.7 集成开发环境,编程语言:Verilog HDL 硬件描述语言七、 实验步骤1、新建项目,将上个实验完成的解决数据冒险与数据前推的代码拷贝进来3 / 92、在直接跳转中,需要废除跳转指令的下一条(当译码出跳转指令时,下一条已经流出,所以要废除掉) ;而在条件跳转中,需要根据 z 的值来判断是否废除下一条指令。在代码中译码级,pcsource 定义如下assign pcsource1=i_jr
6、|i_j|i_jal;/选择下一条指令的地址,00 选 PC+4,01 选转移地址,10选寄存器内地址,11 选跳转地址assign pcsource0=i_beqLOADDEPEN,BTAKEN,ID_branch );如果是直接跳转,那么一定废除,pcsource=11,如果是条件跳转,废除的条件就是pcsource=01,暂不考虑 jr 指令,那么要废除下一条指令的条件就是 pcsource=00;3、在顶层模块添加变量wire wz;/决定是否写 z 值wire 1:0 exepcsource;/exe pcsource 主要用在条件跳转wz 需要在 id 级计算出来,然后传递到 ex
7、e 级,如果废除指令那么 wz=0;exepcsource 与之相反,从 exe 级传递到 id 级,用来指示下一条指令是否废除。4、增加这两个变量后,顶层模块 id 级与 exe 级的代码如下pipeid id_stage (dpc4,inst, /指令译码 ID 级wrn,wdi,wwreg,clock,resetn,bpc,jpc,pcsource,dwreg,dm2reg,dwmem,daluc,daluimm,da,db,dimm,drn,dshift,djal,z,ern,mrn,ewreg,mwreg,idadepend,idbdepend,em2reg,wpc,exepcsou
8、rce,wz);pipeexe exe_stage (wz,ealuc,ealuimm,ea,eb,eimm,eshift,ern0,epc4,/指令执行 EXEejal,ern,ealu,z,malu,wmo,exeadepend,exebdepend); 5、加入 exepcsource 后,根据步骤 2 的分析,如果 pcsource!=00,就废除掉下一条指令,即 wreg、wmem 、wz 全部置 0,这里需要注意的是,wz 的值有多种表示方法,由于wz 只在控制冒险中使用,并且在控制冒险中 wreg=wmem=wz,所以这里可以直接将 wreg的值赋给 wz,也可以 wz=exep
9、csource0(pcsource0=i_beqassign wmem=i_sw /为 1 时写存储器,否则不写assign wz=wregid 级 cu 模块完整代码如下:4 / 9module pipeidcu(rsrtequ,func,op,wreg,m2reg,wmem,aluc,regrt,aluimm,sext,pcsource,shift,jal,/*数据前推加入的参数*/exe_rd,mem_rd,exe_wreg,mem_wreg,idadepend,idbdepend,rs,rt,rd,exe_m2reg,wpc,exepcsource,wz);input 1:0 exep
10、csource;input 4:0 exe_rd,mem_rd,rs,rt,rd;input exe_wreg,mem_wreg,exe_m2reg;output 1:0 idadepend,idbdepend;output wpc;/wreg 是否写寄存器/dm2reg 为 1 时将存储器数据写入寄存器,否则将 ALU 结果写入寄存器/dwmem 为 1 时写存储器,否则不写/daluimm 为 1 时 ALUb 输入端使用立即数/dshift 为 1 时 ALUa 输入端使用移位位数/djal 为 1 时执行 jal 指令,否则不是input rsrtequ;input 5:0 func,
11、op;output wz,wreg,m2reg,wmem,regrt,aluimm,sext,shift,jal;output 4:0 aluc;output 1:0 pcsource;wire i_add,i_sub,i_mul,i_and,i_or,i_xor,i_sll,i_srl,i_sra,i_jr; /对指令进行译码wire i_addi,i_muli,i_andi,i_ori,i_xori,i_lw,i_sw,i_beq,i_bne,i_lui,i_j,i_jal;and(i_add,op5,op4,op3,op2,op1,op0,func2,func1,func0);and(i
12、_sub,op5,op4,op3,op2,op1,op0,func2,func1,func0);and(i_mul,op5,op4,op3,op2,op1,op0,func2,func1,func0);and(i_and,op5,op4,op3,op2,op1,op0,func2,func1,func0);and(i_or,op5,op4,op3,op2,op1,op0,func2,func1,func0);and(i_xor,op5,op4,op3,op2,op1,op0,func2,func1,func0);and(i_sra,op5,op4,op3,op2,op1,op0,func2,f
13、unc1,func0);and(i_srl,op5,op4,op3,op2,op1,op0,func2,func1,func0);and(i_sll,op5,op4,op3,op2,op1,op0,func2,func1,func0);and(i_jr,op5,op4,op3,op2,op1,op0,func2,func1,func0);and(i_addi,op5,op4,op3,op2,op1,op0);and(i_muli,op5,op4,op3,op2,op1,op0);and(i_andi,op5,op4,op3,op2,op1,op0);and(i_ori,op5,op4,op3,
14、op2,op1,op0);and(i_xori,op5,op4,op3,op2,op1,op0);and(i_lw,op5,op4,op3,op2,op1,op0);5 / 9and(i_sw,op5,op4,op3,op2,op1,op0);and(i_beq,op5,op4,op3,op2,op1,op0);and(i_bne,op5,op4,op3,op2,op1,op0);and(i_lui,op5,op4,op3,op2,op1,op0);and(i_j,op5,op4,op3,op2,op1,op0);and(i_jal,op5,op4,op3,op2,op1,op0);wire
15、i_rs=i_add|i_sub|i_mul|i_and|i_or|i_xor|i_jr|i_addi|i_muli|i_andi|i_ori|i_xori|i_lw|i_sw|i_beq|i_bne;wire i_rt=i_add|i_sub|i_mul|i_and|i_or|i_xor|i_sra|i_srl|i_sll|i_sw|i_beq|i_bne;/控制信号的生成/assign wreg=(i_add|i_sub|i_mul|i_and|i_or|i_xor|i_sll| /wreg 为 1 时写寄存器堆中某一寄存器,否则不写i_srl|i_sra|i_addi|i_muli|i_
16、andi|i_ori|i_xori|i_lw|i_lui|i_jal) assign regrt=i_addi|i_muli|i_andi|i_ori|i_xori|i_lw|i_lui; /regrt 为 1 时目的寄存器是 rt,否则为 rdassign jal=i_jal; /为 1 时执行 jal 指令,否则不是assign m2reg=i_lw; /为 1 时将存储器数据写入寄存器,否则将 ALU 结果写入寄存器assign shift=i_sll|i_srl|i_sra;/为 1 时 ALUa 输入端使用移位位数assign aluimm=i_addi|i_muli|i_andi|
17、i_ori|i_xori|i_lw|i_lui|i_sw;/为 1 时ALUb 输入端使用立即数assign sext=i_addi|i_muli|i_lw|i_sw|i_beq|i_bne;/为 1 时符号拓展,否则零拓展assign aluc4=i_sra;/ALU 的控制码assign aluc3=i_sub|i_or|i_ori|i_xor|i_xori| i_srl|i_sra|i_beq|i_bne;/ALU 的控制码assign aluc2=i_sll|i_srl|i_sra|i_lui;/ALU 的控制码assign aluc1=i_and|i_andi|i_or|i_ori|
18、i_xor|i_xori|i_beq|i_bne;/ALU 的控制码assign aluc0=i_mul|i_muli|i_xor|i_xori|i_sll|i_srl|i_sra|i_beq|i_bne;/ALU 的控制码assign wmem=i_sw /为 1 时写存储器,否则不写/assign wmem=i_sw /判断相关性assign rs1IsReg=i_and | i_andi | i_or | i_ori | i_add | i_addi | i_sub | i_lw | i_sw | i_sll | i_srl | i_sra;assign rs2IsReg=i_and |
19、 i_or | i_add | i_sub | i_sll | i_sra | i_srl;assign exe_a_depen=(rs=exe_rd) assign mem_a_depen=(rs=mem_rd) 6 / 9assign exe_b_depen=(rt=exe_rd) assign mem_b_depen=(rt=mem_rd) assign idadepend0= (mem_a_depen | 0);assign idadepend1=(mem_a_depen | exe_a_depen | 0) ;/a_depen 和 b_depen 信号全部都需要在暂停流水线时候跟随检
20、测assign idbdepend0=(mem_b_depen | aluimm | 0 );assign idbdepend1=(mem_b_depen | exe_b_depen | 0 );/b_depen 00 b 01 imm 10 mem_wb 11 wb_cassign stall =(rs=exe_rd) assign wz=wreg;assign wpc = stall;assign pcsource1=i_jr|i_j|i_jal;/选择下一条指令的地址,00 选 PC+4,01 选转移地址,10 选寄存器内地址,11 选跳转地址assign pcsource0=i_beq
21、endmodule八、 实验数据及结果分析(一) 画出修改后的流水线图(二) 写出增加的多路选择器的选择信号逻辑函数7 / 9增加的多路选择器信号逻辑函数如下:/加上数据前推之后变成四选一的多路器mux4x32 alu_ina (ea,sa,malu,wmo,exe_a_depend,alua);mux4x32 alu_inb (eb,eimm,malu,wmo,exe_b_depend,alub);mux2x32 save_pc8(ealu0,epc8,ejal,ealu);/选择最后 ALU 结果的来源,ejal 为 0 时是ALU 内部算出的结果,为 1 时是 PC+8assign er
22、n=ern0|5ejal;/当 jal 指令执行时,把返回地址写入 31 号寄存器alu al_unit (alua,alub,ealuc,ealu0,z,wz);/ALU增加的多路选择器(四选一)的定义如下:module mux4x32(a0,a1,a2,a3,s,y);input 31:0 a0,a1,a2,a3;input 1:0 s;output 31:0 y;assign y=(s=2b00)?a0:(s=2b01)?a1:(s=2b10)?a2:a3;/四选一endmodule(三)流水线仿真结果,对仿真结果作必要说明1. 首先测试无条件跳转 jump 指令,代码如下/测试 bra
23、nch 指令(无条件转移)assign rom6h00=32h48000002;/ jump,2; 跳转到 add r3,r1,r2assign rom6h01=32h28003c62;/ ori r2,r3,15;assign rom6h02=32h00100c22;/ add r3,r1,r2;assign rom6h03=32h00100c22;/ add r3,r1,r2;assign rom6h04=32h00100c22;/ add r3,r1,r2;assign rom6h05=32h00000000;在指令中,第一条指令便是一条无条件跳转指令,要跳转到地址为 2 的指令,控制冒
24、险应废除掉 ori 指令,即 r2 不写入 r3|15(15),到了 add 指令时,alu 结果应为 0运行程序,观察结果分析一下,在 300ns 时,计算出 ori 指令的值为 15,但是并没有写入寄存器,因为在400ns 时 alu 的值为 0,故证明了无条件跳转的控制冒险消除成功。2. 测试条件跳转 branch,代码如下/测试 branch 指令的停顿assign rom6h00=32h44000001;/lui r1,0 0assign rom6h01=32h3c100422; /beq next(beq r1 r2 1)assign rom6h02=32h28014024;/or
25、i r4,r1,80 80assign rom6h03=32h00202124;/sub r8,r9,r4 fffassign rom6h04=32h14001005;/addi r5,r0,4 4assign rom6h05=32h38000082;/store r2,0x0(r4) 808 / 9在代码中,可以看到 beq 判断 r1,r2 是否相同,因为二者都是 0,自然要跳转到下一条语句,也就是 sub 语句,因此 ori 指令没有执行,ori 指令也正是前面提到要废除的指令,ori 中将 r4 的值设为 r1|80(80) ,如果控制冒险消除正确,r4 的值不会发生改变,也就是执行到
26、 sub 指令时,alu 计算出 r8 的值仍然为 0。运行程序,查看测试结果:接下来,进行分析,在第 400ns,alu 的值为 bf800050(80) ,但是此时因为检测到了控制冒险,因此该值并没有写入 r4,这一点从图中在下一个时钟周期(500ns)alu 的值为0 可以得到验证,因为如果 r4 写入 80,alu 的值应为-80,因此,条件转移的控制冒险成功消除。九、 总结、改进建议及心得体会(一) 总结:经过对代码的改写,包括添加变量、模块参数、修改模块代码、增改连线、反复测试、修改等,成功地通过 WZ、WMEM 、WREG 信号消除了无条件转移语句和条件转移语句的后一条指令的影响,较好的完成了本次实验。(二) 改进建议:如果能够有板子可以跑一下,就更有意思了,像之前的计算机组成原理那样,实验的最后一步是下载到板子上运行。(三) 心得体会:1、 先搞懂原理,画图,再编程2、 编写多组指令进行测试,并且注意查看内部寄存器的值,而不仅仅是查看结果。