您的位置:首页 > 其它

课程project复习 - CPU-hazard

2016-03-24 20:50 204 查看
一、什么是hazards

  hazards是CPU在当前周期无法获取所要取的寄存器的值的问题。出现情况主要分为以下三种:

1、一般计算



  第一个ADD将和赋给gr3,第二个ADD则是要用到gr3的值。如果第二个ADD想要gr3的值,必须等到第一个ADD执行到WB阶段,才能得到gr3被更新之后的值。所以还要等3个周期。因此,中间的三个ADD其实都应该换成nop,否则gr3就是更新之前的值,导致最后的结果不是我们实际想要的。

  软件的解决方法就是添加nop了,但现在要用硬件的解决办法:data_forwarding:其实不用等到第一个ADD执行到WB才能得到更新之后的gr3的值,因为这个值是在ID和EX之间(ALU)计算出来的,然后存入了ALUo,进而赋给reg_C、reg_C1,最后才到gr3。所以可以通过data forwarding,利用这些提前得到计算结果的中间变量给reg_A/B赋值,如下图所示:



2、LOAD指令

  通过data forwarding解决了两个计算指令之间的冲突,但是它不能解决所有的赋值问题。LOAD的问题就不能:



  因为LOAD指令是从内存中取值,所以ALU计算出来的ALUo和赋给的reg_C都只是从内存中取值的地址,而不是从内存中得到的值。这个值是在MEM阶段才得到的。所以中间必须等待一个周期,才能用data forwarding的方式,获取d_datain的值。这种方法就是Stall

  实现方式:在下个周期内,维持pc的值。然后id_ir赋为nop指令,也就是什么都不做。(所以其实和软件实现的思路一样……)



3、跳转指令

  如果当前指令已经是跳转指令了,那么,肯定不能让在指令内存中紧接着的指令执行了,否则可能会导致意想之外的情况发生。

  怎么解决呢?方法依然是Stall,因为要保持pc不变。

二、代码实现

  通过前面对hazards的两种情况的解释,应该对实现有一个大致的框架了:用组合逻辑实现,每次判断id_ir和ex_ir、mem_ir、wb_ir之间的关系,然后将判断结果写入变量中,供下一个周期到来时,CPU判断是否需要data forwarding或者stall。

1、data forwarding

① change_ex、change_mem、change_wb:判断前1~3条指令是否会修改r1的值(必要性:如果都不会修改寄存器的值,就不需要data forwarding了)



② spe_idir:大部分计算指令的reg_A对应的寄存器的地址都是id_ir的6~4位,但是ADDI、SUBI和LDIH这三个比较特殊,reg_A是10~8位,由于这个位置是接下来判断是否需要data forwarding的关键,所以要特别区分这种状态。



③ needForwardRegA、needForwardRegB:判断当前指令是否会修改r1的值



④ ForwardRegA、ForwardRegB:是否需要进行data forwarding,如果需要,又要判断和哪个指令发生了hazards,以确定reg_A/B应该取什么值



⑤ ForwardSmdr:这个是后来才发现的问题,别忘了ID阶段还对smdr赋值了,这个变量储存了执行STORE的时候储存进内存的值,它的值也是从寄存器中取的,所以也要进行data forwarding:



⑥ ID阶段,对reg_A、reg_B、smdr的赋值:

reg_A:


reg_B:


smdr:


2、Stall

① needRegA、needRegB:判断i_datain是不是需要从寄存器中取值



② stallPc、stallInstr:在needRegA和needRegB的基础上,判断id_ir是不是LOAD指令、寄存器地址是否对应、是不是跳转指令,进而判断是否需要stall



③ 在IF阶段对PC和id_ir的赋值



三、板上验证

  经过前面好多步骤终于写好了hazard,下一步就是验证它能不能工作了。测试代码就是修改instr_mem的指令,修改data_mem的数据。而指令都是类似汇编语言的指令,其实只要根据每一个指令的结构认真阅读,就可以理解了。

1、冒泡排序





2、最小公倍数、最大公约数





四、资料下载

代码&测试代码
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: