自己动手写CPU(8)转移指令+延迟槽解决流水线控制相关

延迟槽

流水线中存在的三种相关:数据相关、结构相关、控制相关。其中控制相关是指流水线中的转移指令或者其他需要改写PC的指令造成的相关。这些指令改写了PC的值,所以导致后面已经进入流水线的几条指令无效。

比如当第一条指令为分支跳转指令,那么在执行阶段才会知道要不要跳转;但当时第二条指令已经进入译码;第三条指令已经进入取指阶段。在流水线执行阶段进行转移判断,并且转移发生,那么会有两条无效指令,导致浪费两个时钟周期,为减少损失发明了“延迟槽”

我们规定转移指令后面的指令位置为延迟槽

但是,即使加入延迟槽,在转移发生时仍然会导致已经进去取指阶段的指令无效,仍浪费一个时钟周期。所以我们可以在译码阶段进行转移判断,并且让延迟槽后一指令继续执行。

此时需要注意的是:

延迟槽里的指令,在目标跳转指令前面执行,所以延迟槽里的指令不能修改目标跳转指令会用到的寄存器或者变量的内容,否则会出错。

下面我们来介绍转移指令

其中跳转指令是绝对转移,分支指令是相对转移

跳转指令

指令格式

jr指令

用法:jr rs

作用:pc <- rs

将地址为rs的通用寄存器的值赋给寄存器PC,作为新的指令地址

jalr指令

用法:jalr rs 或者 jalr rd,rs 

作用:rd <- return_address,pc <- rs

将地址为rs的通用寄存器的值赋给寄存器PC,作为新的指令地址,同时将跳转指令后面第2条指令的地址作为返回地址保存到地址为rd的通用寄存器,如果没有在指令中指明rd,那么默认将返回地址保存到寄存器$31

j指令

用法:j target

作用:pc <- (pc+4)[31,28]||target||‘00’

转移到新的指令地址,其中新地址的低28位是target左移两位后的值,新指令地址高4位是后一指令的高四位

因为处理器按照字节寻址,二指令存储器每个地址是一个32bit字,所以要给指令中的立即数乘4,即左移两位

jal指令

用法:jal target

作用:pc <- (pc+4)[31,28]||target||‘00’

转移到新的指令地址,其中新地址的低28位是target左移两位后的值,新指令地址高4位是后一指令的高四位,jal指令要将跳转指令后面的一条指令地址(pc+4)写入$31寄存器

分支指令

指令格式

指令说明

beq、b、bgtz、blez、bne这5条指令可以直接依据指令中的指令码进行判断是哪一条指令,bltz、bltzal、bgez、bgezal、bal这5条指令指令码相同,依据指令中16~20bit的值进一步判断是哪一条指令

所有分支指令的第0~15bit存储的都是offset,如果发生转移,那么将offset左移2位,并符号扩展至32位

转移目标地址 = (signed_extend)(offset||‘00’)+(pc+4)

beq指令

用法:beq rs,rt,offset

作用:if rs = rt then branch

将地址为rs的通用寄存器的值与地址为rt的通用寄存器的值进行比较,如果相等,则发生转移

b指令

用法:b offset

作用:无条件转移

beq指令的rs,rt都为0时的情况,实现时不需要特意实现b指令,只需要实现beq即可

bgtz指令

用法:bgtz rs,offset

作用:if rs > 0 then branch

如果地址为rs的通用寄存器的值大于0,则发生转移

blez指令

用法:blez rs,offset

作用:if rs <= 0 then branch

如果地址为rs的通用寄存器的值小于等于0,则发生转移

bne指令

用法:bne rs,rt,offset

作用:if rs != rt then branch

将地址为rs的通用寄存器的值与地址为rt的通用寄存器的值进行比较,如果不相等,则发生转移

bltz指令

用法:bltz rs,offset

作用:if rs < 0 then branch

如果地址为rs的通用寄存器的值小于0,则发生转移

bltzal指令

用法:bltzal rs,offset

作用:if rs < 0 then branch

如果地址为rs的通用寄存器的值小于0,则发生转移,并且将指令后面的指令地址作为返回地址,保存到通用寄存器$31

bgez指令

用法:bgez rs,offset

作用:if rs >= 0 then branch

如果地址为rs的通用寄存器的值大于等于0,则发生转移

bgezal指令

用法:bgezal rs,offset

作用:if rs >= 0 then branch

如果地址为rs的通用寄存器的值大于等于0,则发生转移,并且将指令后面的指令地址作为返回地址,保存到通用寄存器$31

bal指令

用法:bal offset

作用:无条件转移

如果地址为rs的通用寄存器的值大于等于0,则发生转移,并且将指令后面的指令地址作为返回地址,保存到通用寄存器$31

bal是bgezal指令的特殊情况,即bgezal指令的rs为0,不用特意实现这个指令

代码的修改

  • 在译码阶段增加转移判断步骤,PC分成三种取值
  • 译码阶段增加延迟槽处理信号

PC的三种取值:

1.PC = PC + 4(下一条指令)

2.PC不变(流水线暂停)

3.PC等于转移判断的结果(如果是转移指令且满足转移条件,将转移目标给PC)

译码阶段:

如果处于译码阶段的指令是转移指令,并且满足转移条件,那么ID模块设置转移发生标志 branch_flag_o为 Branch,同时通过branch_target_address_o接口给出转移目的地址,送到PC模块,后者据此修改取指地址。

如果处于译码阶段的指令是转移指令,并且满足转移条件,那么ID模块还会设置next_inst_in_delayslot_o为 InDelaySlot,表示下一条指令是延迟槽指令,其中 InDelaySlot是一个宏定义。next_inst _in_delayslot_o信号会送入ID/EX模块,并在下一个时钟周期通过ID/EX模块的is_in_delayslot_o接口送回到ID模块,ID模块可以据此判断当前处于译码阶段的指令是否是延迟槽指令。

如果转移指令需要保存返回地址,那么译码模块还要计算返回地址,并通过link_addr_o接口输出,该值最终会传递到EX模块,作为要写入目的寄存器的值。

修改PC代码:

always @ (posedge clk) begin
    if (ce == `ChipDisable) begin
        pc <= 32'h00000000;
    end else if(stall[0] == `NoStop) begin
        if(branch_flag_i == `Branch) begin
        	pc <= branch_target_address_i;
        end else begin
        	pc <= pc + 4'h4;
        end
    end
end

总结

要注意延迟槽里的指令,在目标跳转指令前面执行,所以延迟槽里的指令不能修改目标跳转指令会用到的寄存器或者变量的内容,否则会出错。

还要在本次添加宏定义

`define Branch 1'b1				//发生转移
`define NotBranch 1'b0			//不发生转移
`define InDelaySlot 1'b1		//是延迟槽指令
`define NotInDelaySlot 1'b0		//不是延迟槽指令

  • 3
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
- 流水线技术:一种将一个任务分为多个步骤,每个步骤并行执行的技术。常见于计算机 CPU 中,可以提高 CPU 的执行效率。 - 指令流水线:将 CPU 中执行指令的不同阶段分为多个步骤,每个步骤并行执行的技术。 - 运算流水线:将 CPU 中执行运算的不同阶段分为多个步骤,每个步骤并行执行的技术。 - 流水寄存器:在 CPU流水线中,不同阶段之间需要传递数据,流水寄存器用于存储数据并在不同阶段之间传递数据。 - 流水时空图:用于表示 CPU 流水线中各个阶段的执行时间和资源占用情况的图表。 - 数据冲突:在 CPU 流水线中,由于指令之间的依赖关系,可能会导致某些指令需要等待前面的指令执行完毕才能执行,从而影响 CPU 的执行效率。 - 结构冲突:在 CPU 流水线中,由于不同指令需要使用相同的硬件资源,可能会导致资源争用,从而影响 CPU 的执行效率。 - 控制相关:在 CPU 流水线中,由于条件跳转等控制指令的存在,可能会导致指令的执行顺序发生变化,从而影响 CPU 的执行效率。 - 先后读冲突:在 CPU 流水线中,由于某些指令入数据再读取数据,可能会导致数据错误的问题。 - 先读后冲突:在 CPU 流水线中,由于某些指令先读取数据再入数据,可能会导致数据错误的问题。 - 冲突:在 CPU 流水线中,由于某些指令入数据再入相同的数据,可能会导致数据错误的问题。 - 气泡:在 CPU 流水线中,为了解决数据冲突等问题,可能需要在流水线中插入一些空指令,这些空指令称为气泡。 - 重定向:在 CPU 流水线中,为了解决数据冲突等问题,可能需要将某些指令的执行结果重定向到其他指令中使用。 - 延迟:在 CPU 流水线中,为了提高 CPU 的执行效率,可能会将跳转指令的下一条指令提前执行,这条指令称为延迟。 - 动态分支预测:一种 CPU 流水线技术,通过分析程序执行的历史记录来预测跳转指令的执行情况,从而提高 CPU 的执行效率。 - 超标量技术:一种 CPU 技术,可以在同一个时钟周期内执行多个指令,从而提高 CPU 的执行效率。 - 超流水线技术:一种 CPU 技术,可以将指令流水线划分为更多的阶段,从而提高 CPU 的执行效率。 - 动态多发射技术:一种 CPU 技术,可以根据当前程序的执行情况动态地发射多条指令,从而提高 CPU 的执行效率。 - 静态多发射技术:一种 CPU 技术,可以在编译时确定程序可以同时执行的指令,从而提高 CPU 的执行效率。 - 同步中断:一种 CPU 中断处理方式,即在指令执行完毕后,暂停当前任务,进入中断处理程序执行。 - 异步中断:一种 CPU 中断处理方式,即在任何时候,都可以接收到中断信号并进入中断处理程序执行。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值