电子科大系统结构实验解决控制冒险.docx
- 文档编号:10676596
- 上传时间:2023-02-22
- 格式:DOCX
- 页数:11
- 大小:21.62KB
电子科大系统结构实验解决控制冒险.docx
《电子科大系统结构实验解决控制冒险.docx》由会员分享,可在线阅读,更多相关《电子科大系统结构实验解决控制冒险.docx(11页珍藏版)》请在冰豆网上搜索。
电子科大系统结构实验解决控制冒险
实验报告
课程名称:
计算机系统结构实验
学 院:
计算机科学与工程学院
专 业:
计算机科学与技术
指导教师:
好老师
学生姓名:
爱学习的大哥哥
实验成绩:
日 期:
2017年5月26日
电子科技大学计算机学院实验中心
电子科技大学
实验报告
一、实验项目名称:
解决控制冒险
二、实验室名称:
主楼A2-412实验时间:
2017年5月26日
三、实验目的
在给出的流水线代码基础上,增加ID级关闭写使能信号,以解决不正确分支指令的影响。
通过完成这次实验,加深对控制冒险现象的产生和消除控制冒险的原理的理解,提高编程和测试的能力。
四、实验原理
(一)转移相关问题
转移指令改变程序顺序执行的特性。
由于是流水线操作,在转移发生之前,若干条转移指令的后续指令已被取到流水线处理机中。
这就是所谓的转移相关问题(branchhazard),有时也称之为控制相关问题(controlhazard)。
回顾我们前面介绍的处理转移相关问题的4种技术:
以上任何一种方法都会使硬件固定,编译时会根据硬件机制和转移行为对代码进行调度,以获取最佳性能。
(二)消除无条件转移指令的后一条指令影响
每条指令在ID时判断在当前在EXE阶段的操作码暂存器的值是否是无条件转移指令:
如果是,那么不使能当前在ID阶段的那条指令的WZ、WMEM和WREG的信号,这样这条指令的执行就对程序的逻辑没有影响。
(三)条件转移指令
条件转移指令的实现思想与无条件转移指令有所类似,但不完全相同。
首先对于条件转移指令本身来说,需要判断Z标志是否能用。
若Z标志还没有准备好,则要暂停流水线一个时钟周期。
这一点和判断数据相关极为相似。
但由于转移指令只可能改变PC而不改变其它状态,因此用不着封锁WZ,WMEM,WREG(对转移指令来讲,这些信号原本就为0)。
因为如果处在译码级的是条件转移指令,而且处在EXE级的是ALU类型的指令(就要写Z标志到流水线寄存器Z了),则要等到ALU指令写完Z后,再判断转移与否,为此要暂停一个周期(或者如前所述,插入一条nop指令)。
对于条件转移指令的下一条指令的处理办法与无条件指令不同。
因为条件转移的下一条指令有可能执行也有可能不执行,需要在对无条件转移指令的处理策略上进行扩展:
条件转移的下一条指令在ID时判断在当前在EXE阶段的操作码暂存器的值是否是条件转移指令并且判断是否转移成功(Z的值没变),如果发现成功,那么不使能当前在ID阶段的那条指令的WZ、WMEM和WREG的信号,这条指令的执行就对程序的逻辑没有影响(与无条件处理方式相同);如果发现转移不成功,说明本条指令为有效指令,使能当前在ID阶段的那条指令的WZ、WMEM和WREG的信号,本条指令正常执行。
五、实验内容
在给出的流水线代码基础上,增加ID级关闭写使能信号,以解决不正确分支指令的影响。
六、实验器材(设备、元器件)
ISEDesignSuite集成开发环境,编程语言:
VerilogHDL硬件描述语言
七、实验步骤
1、新建项目,将上个实验完成的解决数据冒险与数据前推的代码拷贝进来
2、在直接跳转中,需要废除跳转指令的下一条(当译码出跳转指令时,下一条已经流出,所以要废除掉);而在条件跳转中,需要根据z的值来判断是否废除下一条指令。
在代码中译码级,pcsource定义如下
assignpcsource[1]=i_jr|i_j|i_jal;//选择下一条指令的地址,00选PC+4,01选转移地址,10选寄存器内地址,11选跳转地址
assignpcsource[0]=i_beq&rsrtequ|i_bne&~rsrtequ|i_j|i_jal;LOADDEPEN,BTAKEN,ID_branch);
如果是直接跳转,那么一定废除,pcsource=11,如果是条件跳转,废除的条件就是pcsource=01,暂不考虑jr指令,那么要废除下一条指令的条件就是pcsource=00;
3、在顶层模块添加变量
wirewz;//决定是否写z值
wire[1:
0]exepcsource;//exepcsource主要用在条件跳转
wz需要在id级计算出来,然后传递到exe级,如果废除指令那么wz=0;
exepcsource与之相反,从exe级传递到id级,用来指示下一条指令是否废除。
4、增加这两个变量后,顶层模块id级与exe级的代码如下
pipeidid_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,exepcsource,wz);
pipeexeexe_stage(wz,ealuc,ealuimm,ea,eb,eimm,eshift,ern0,epc4,//指令执行EXE
ejal,ern,ealu,z,
malu,wmo,exeadepend,exebdepend);
5、加入exepcsource后,根据步骤2的分析,如果pcsource!
=00,就废除掉下一条指令,即wreg、wmem、wz全部置0,这里需要注意的是,wz的值有多种表示方法,由于wz只在控制冒险中使用,并且在控制冒险中wreg=wmem=wz,所以这里可以直接将wreg的值赋给wz,也可以wz=exepcsource[0](pcsource[0]=i_beq&rsrtequ|i_bne&~rsrtequ|i_j|i_jal,在条件跳转中pcsource[0]=i_beq&rsrtequ|i_bne)
assignwreg=(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_andi|i_ori|i_xori|
i_lw|i_lui|i_jal)&wpc&(exepcsource[0]==0)&(exepcsource[1]==0);
assignwmem=i_sw&wpc&(exepcsource[0]==0)&(exepcsource[1]==0);//为1时写存储器,否则不写
assignwz=wreg
id级cu模块完整代码如下:
modulepipeidcu(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]exepcsource;
input[4:
0]exe_rd,mem_rd,rs,rt,rd;
inputexe_wreg,mem_wreg,exe_m2reg;
output[1:
0]idadepend,idbdepend;
outputwpc;
//wreg是否写寄存器
//dm2reg为1时将存储器数据写入寄存器,否则将ALU结果写入寄存器
//dwmem为1时写存储器,否则不写
////daluimm为1时ALUb输入端使用立即数
//dshift为1时ALUa输入端使用移位位数
//djal为1时执行jal指令,否则不是
inputrsrtequ;
input[5:
0]func,op;
outputwz,wreg,m2reg,wmem,regrt,aluimm,sext,shift,jal;
output[4:
0]aluc;
output[1:
0]pcsource;
wirei_add,i_sub,i_mul,i_and,i_or,i_xor,i_sll,i_srl,i_sra,i_jr;//对指令进行译码
wirei_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,~op[5],~op[4],~op[3],~op[2],~op[1],~op[0],~func[2],~func[1],func[0]);
and(i_sub,~op[5],~op[4],~op[3],~op[2],~op[1],~op[0],~func[2],func[1],~func[0]);
and(i_mul,~op[5],~op[4],~op[3],~op[2],~op[1],~op[0],~func[2],func[1],func[0]);
and(i_and,~op[5],~op[4],~op[3],~op[2],~op[1],op[0],~func[2],~func[1],func[0]);
and(i_or,~op[5],~op[4],~op[3],~op[2],~op[1],op[0],~func[2],func[1],~func[0]);
and(i_xor,~op[5],~op[4],~op[3],~op[2],~op[1],op[0],func[2],~func[1],~func[0]);
and(i_sra,~op[5],~op[4],~op[3],~op[2],op[1],~op[0],~func[2],~func[1],func[0]);
and(i_srl,~op[5],~op[4],~op[3],~op[2],op[1],~op[0],~func[2],func[1],~func[0]);
and(i_sll,~op[5],~op[4],~op[3],~op[2],op[1],~op[0],~func[2],func[1],func[0]);
and(i_jr,~op[5],~op[4],~op[3],~op[2],op[1],~op[0],func[2],~func[1],~func[0]);
and(i_addi,~op[5],~op[4],~op[3],op[2],~op[1],op[0]);
and(i_muli,~op[5],~op[4],~op[3],op[2],op[1],op[0]);
and(i_andi,~op[5],~op[4],op[3],~op[2],~op[1],op[0]);
and(i_ori,~op[5],~op[4],op[3],~op[2],op[1],~op[0]);
and(i_xori,~op[5],~op[4],op[3],op[2],~op[1],~op[0]);
and(i_lw,~op[5],~op[4],op[3],op[2],~op[1],op[0]);
and(i_sw,~op[5],~op[4],op[3],op[2],op[1],~op[0]);
and(i_beq,~op[5],~op[4],op[3],op[2],op[1],op[0]);
and(i_bne,~op[5],op[4],~op[3],~op[2],~op[1],~op[0]);
and(i_lui,~op[5],op[4],~op[3],~op[2],~op[1],op[0]);
and(i_j,~op[5],op[4],~op[3],~op[2],op[1],~op[0]);
and(i_jal,~op[5],op[4],~op[3],~op[2],op[1],op[0]);
wirei_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;
wirei_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;
////////////////////////////////////////////控制信号的生成/////////////////////////////////////////////////////////
assignwreg=(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_andi|i_ori|i_xori|
i_lw|i_lui|i_jal)&wpc&(exepcsource[0]==0)&(exepcsource[1]==0);
assignregrt=i_addi|i_muli|i_andi|i_ori|i_xori|i_lw|i_lui;//regrt为1时目的寄存器是rt,否则为rd
assignjal=i_jal;//为1时执行jal指令,否则不是
assignm2reg=i_lw;//为1时将存储器数据写入寄存器,否则将ALU结果写入寄存器
assignshift=i_sll|i_srl|i_sra;//为1时ALUa输入端使用移位位数
assignaluimm=i_addi|i_muli|i_andi|i_ori|i_xori|i_lw|i_lui|i_sw;//为1时ALUb输入端使用立即数
assignsext=i_addi|i_muli|i_lw|i_sw|i_beq|i_bne;//为1时符号拓展,否则零拓展
assignaluc[4]=i_sra;//ALU的控制码
assignaluc[3]=i_sub|i_or|i_ori|i_xor|i_xori|i_srl|i_sra|i_beq|i_bne;//ALU的控制码
assignaluc[2]=i_sll|i_srl|i_sra|i_lui;//ALU的控制码
assignaluc[1]=i_and|i_andi|i_or|i_ori|i_xor|i_xori|i_beq|i_bne;//ALU的控制码
assignaluc[0]=i_mul|i_muli|i_xor|i_xori|i_sll|i_srl|i_sra|i_beq|i_bne;//ALU的控制码
assignwmem=i_sw&wpc&(exepcsource[0]==0)&(exepcsource[1]==0);//为1时写存储器,否则不写
//assignwmem=i_sw&wpcir;
//判断相关性
assignrs1IsReg=i_and|i_andi|i_or|i_ori|i_add|i_addi|i_sub|i_lw|i_sw|i_sll|i_srl|i_sra;
assignrs2IsReg=i_and|i_or|i_add|i_sub|i_sll|i_sra|i_srl;
assignexe_a_depen=((rs==exe_rd)&(exe_wreg==1)&(rs1IsReg));
assignmem_a_depen=((rs==mem_rd)&(mem_wreg==1)&(rs1IsReg));
assignexe_b_depen=((rt==exe_rd)&(exe_wreg==1)&(rs2IsReg))|((rd==exe_rd)&(exe_wreg==1)&(i_sw));
assignmem_b_depen=((rt==mem_rd)&(mem_wreg==1)&(rs2IsReg))|((rd==mem_rd)&(mem_wreg==1)&(i_sw));
assignidadepend[0]=(mem_a_depen|0);
assignidadepend[1]=(mem_a_depen|exe_a_depen|0);
//a_depen和b_depen信号全部都需要在暂停流水线时候跟随检测
assignidbdepend[0]=(mem_b_depen|aluimm|0);
assignidbdepend[1]=(mem_b_depen|exe_b_depen|0);
//b_depen00b01imm10mem_wb11wb_c
assignstall=((rs==exe_rd)&exe_m2reg&rs1IsReg)|
((rt==exe_rd)&exe_m2reg&rs2IsReg)|
((rd==exe_rd)&exe_wreg&i_sw)|
((rd==mem_rd)&mem_wreg&i_sw);
assignwz=wreg;
assignwpc=~stall;
assignpcsource[1]=i_jr|i_j|i_jal;//选择下一条指令的地址,00选PC+4,01选转移地址,10选寄存器内地址,11选跳转地址
assignpcsource[0]=i_beq&rsrtequ|i_bne&~rsrtequ|i_j|i_jal;
endmodule
八、实验数据及结果分析
(一)画出修改后的流水线图
(二)写出增加的多路选择器的选择信号逻辑函数
增加的多路选择器信号逻辑函数如下:
//加上数据前推之后变成四选一的多路器
mux4x32alu_ina(ea,sa,malu,wmo,exe_a_depend,alua);
mux4x32alu_inb(eb,eimm,malu,wmo,exe_b_depend,alub);
mux2x32save_pc8(ealu0,epc8,ejal,ealu);//选择最后ALU结果的来源,ejal为0时是ALU内部算出的结果,为1时是PC+8
assignern=ern0|{5{ejal}};//当jal指令执行时,把返回地址写入31号寄存器
alual_unit(alua,alub,ealuc,ealu0,z,wz);//ALU
增加的多路选择器(四选一)的定义如下:
modulemux4x32(a0,a1,a2,a3,s,y
);
input[31:
0]a0,a1,a2,a3;
input[1:
0]s;
output[31:
0]y;
assigny=(s==2'b00)a0:
(s==2'b01)a1:
(s==2'b10)a2:
a3;//四选一
endmodule
(三)流水线仿真结果,对仿真结果作必要说明
1.首先测试无条件跳转jump指令,代码如下
//测试branch指令(无条件转移)
assignrom[6'h00]=;//jump,2;跳转到addr3,r1,r2
assignrom[6'h01]=32'h28003c62;//orir2,r3,15;
assignrom[6'h02]=32'h00100c22;//addr3,r1,r2;
assignrom[6'h03]=32'h00100c22;//addr3,r1,r2;
assignrom[6'h04]=32'h00100c22;//addr3,r1,r2;
assignrom[6'h05]=32'h00000000;
在指令中,第一条指令便是一条无条件跳转指令,要跳转到地址为2的指令,控制冒险应废除掉ori指令,即r2不写入r3|15(15),到了add指令时,alu结果应为0
运行程序,观察结果
分析一下,在300ns时,计算出ori指令的值为15,但是并没有写入寄存器,因为在400ns时alu的值为0,故证明了无条件跳转的控制冒险消除成功。
2.测试条件跳转branch,代码如下
//测试branch指令的停顿
assignrom[6'h00]=;//luir1,00
assignrom[6'h01]=32'h3c100422;//beqnext(beqr1r21)
assignrom[6'h02]=;//orir4,r1,8080
assignrom[6'h03]=32'h00202124;//subr8,r9,r4fff
assignrom[6'h04]=;//addir5,r0,44
assignrom[6'h05]=;//storer2,0x0(r4)80
在代码中,可以看到beq判断r1,r2是否相同,因为二者都是0,自然要跳转到下一条语句,也就是sub语句,因此ori指令没有执行,ori指令也正是前面提到要废除的指令,ori中将r4的值设为r1|80(80),如果控制冒险消除正确,r4的值不会发生改变,也就是执行到sub指令时,alu计算出r8的值仍然为0。
运行程序,查看测试结果:
接下来,进行分析,在第400ns,alu的值为bf800050(80),但是此时因为检测到了控制冒险,因此该值并没有写入r4,这一点从图中在下一个时钟周期(500ns)alu的值为0可以得到验证,因为如果r4写入80,alu的值应为-80,因此,条件转移的控制冒险成功消除。
九、总结、改进建议及心得体会
(一)总结:
经过对代码的改写,包括添加变量、模块参数、修改模块代码、增改连线、反复测试、修改等,成功地通过WZ、WMEM、WREG信号消除了无条件转移语句和条件转移语句的后一条指令的影响,较好的完成了本次实验。
(二)改进建议:
如果能够有板子可以跑一下,就更有意思了,像之前的计算机组成原理那样,实验的最后一步是下载到板子上运行。
(三)心得体会:
1、先搞懂原理,画图,再编程
2、编写多组指令进行测试,并且注意查看内部寄存器的值,而不仅仅是查看结果。
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 电子科 系统 结构 实验 解决 控制 冒险