【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing @163.com】

cpu按部就班地去取指执行是理想情况。很多时候,cpu的pc寄存器会跳来跳去的。跳转的情况很多,一般可以分成三种。第一,绝对跳转;第二,条件跳转;第三,异常跳转。绝对跳转,很容易理解,就是不得不做的跳转,比如在主函数里面调用子函数这种就属于绝对跳转。当然,函数调用的时候还需要把返回的地址保存一下。条件跳转,这种也很常见,就是对数据进行判断后,根据结果来分析下是否需要跳转。而异常跳转,就是发生异常情况不得不做的跳转,比如指令错误,数据除0,访存地址不对齐等等。这些都算是异常跳转。

今天我们分析的是绝对跳转和条件跳转。根据cpu五级流水线的理论,跳转的地址判断需要在ex阶段才能给出来。但是这个时候pc已经连续给出了两个地址了。也就是说,如果关于跳转的地址计算只能在ex阶段给出,那么cpu还必须要执行跳转指令后面的两条指令。否则的话,cpu就要采取flush流水线的方法来进行解决,这对整个cpu的性能来说,其实是很伤的。

那mips是怎么做的呢?目前来说,针对跳转问题,mips采取了两个方法。第一,引入延迟槽的概念,也就是说跳转指令后面的指令也会被强制执行;第二,就是把地址的判断和输入提前到译码阶段来进行。当然,既然跳转指令后面的延迟槽指令也会被强制执行,这部分要么用nop代替,要么就要编译器帮忙,引入一些有用的指令了。

1、绝对跳转

             `EXE_J:            beginwreg_o <= `WriteDisable;      aluop_o <= `EXE_J_OP;alusel_o <= `EXE_RES_JUMP_BRANCH; reg1_read_o <= 1'b0;  reg2_read_o <= 1'b0;link_addr_o <= `ZeroWord;branch_target_address_o <= {pc_plus_4[31:28], inst_i[25:0], 2'b00};branch_flag_o <= `Branch;next_inst_in_delayslot_o <= `InDelaySlot;         instvalid <= `InstValid;   end

这是译码阶段的verilog代码。从代码可以看出,这个时候其实已经把给pc的jump地址准备好了,也就是branch_target_address_o。同时,branch_flag_o也置为真。

2、条件跳转

             `EXE_BEQ:          beginwreg_o <= `WriteDisable;      aluop_o <= `EXE_BEQ_OP;alusel_o <= `EXE_RES_JUMP_BRANCH; reg1_read_o <= 1'b1;    reg2_read_o <= 1'b1;instvalid <= `InstValid;  if(reg1_o == reg2_o) beginbranch_target_address_o <= pc_plus_4 + imm_sll2_signedext;branch_flag_o <= `Branch;next_inst_in_delayslot_o <= `InDelaySlot;         endend

这是条件跳转,和绝对跳转不同的是,这里多了一个reg1_o和reg2_o的判断。也就是只有两个数据相等的时候,才会进行跳转处理。这个时候,细心的同学还会发现,除了设置branch_target_address_o和branch_flag_o之外,还有一个next_inst_in_delayslot_o的输出?这个数值是做什么用的。其实,这个数值是给异常处理用的。因为异常处理的时候,如果发现此时处理的指令是延迟槽的指令,那么就是做pc-4的处理,其中原因大家可以好好思考一下。

3、函数调用式跳转

`EXE_JALR: beginwreg_o <= `WriteEnable;        aluop_o <= `EXE_JALR_OP;alusel_o <= `EXE_RES_JUMP_BRANCH;   reg1_read_o <= 1'b1; reg2_read_o <= 1'b0;wd_o <= inst_i[15:11];link_addr_o <= pc_plus_8;branch_target_address_o <= reg1_o;branch_flag_o <= `Branch;next_inst_in_delayslot_o <= `InDelaySlot;instvalid <= `InstValid; end 

和前面的跳转一样,这里也对branch_target_address_o、branch_flag_o、next_inst_in_delayslot_o进行了输出。但是除此之外,还增加了一个link_addr_o输出。这主要是因为在函数调用的时候,cpu不光要跳转到指定的地址执行,还需要知道返回来的pc地址。而这个link_addr_o就是返回来的地址,它在wb阶段会写入指定的寄存器中。当然函数调用和异常返回,虽然都会回到之前的函数继续执行,但是函数调用不会flush流水线,而中断、异常发生的时候会对整个的流水线进行flush处理,这就是最大的区别。另外需要注意的是,因为延迟槽的关系,返回的pc地址是当前pc+8,而不是pc+4,这个和一般的cpu处理器不太一样。

4、修改pc_reg.v代码

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

有了译码阶段给出的branch_target_address_i和branch_flag_i,这个时候pc就可以按照我们之前的设计跳转到合适的地方了。

5、准备汇编测试代码

   .org 0x0.set noat.set noreorder.set nomacro.global _start
_start:ori  $1,$0,0x0001   # $1 = 0x1                j    0x20ori  $1,$0,0x0002   # $1 = 0x2ori  $1,$0,0x1111ori  $1,$0,0x1100.org 0x20ori  $1,$0,0x0003   # $1 = 0x3               jal  0x40div  $zero,$31,$1   # $31 = 0x2c, $1 = 0x3# HI = 0x2, LO = 0xe ori  $1,$0,0x0005   # r1 = 0x5ori  $1,$0,0x0006   # r1 = 0x6j    0x60nop.org 0x40jalr $2,$31           or   $1,$2,$0        # $1 = 0x48ori  $1,$0,0x0009    # $1 = 0x9ori  $1,$0,0x000a    # $1 = 0xaj 0x80nop.org 0x60ori  $1,$0,0x0007    # $1 = 0x7                jr   $2           ori  $1,$0,0x0008    # $1 = 0x8ori  $1,$0,0x1111ori  $1,$0,0x1100.org 0x80nop_loop:j _loopnop

6、翻译成指令文件

34010001
08000008
34010002
34011111
34011100
00000000
00000000
00000000
34010003
0c000010
03e1001a
34010005
34010006
08000018
00000000
00000000
03e01009
00400825
34010009
3401000a
08000020
00000000
00000000
00000000
34010007
00400008
34010008
34011111
34011100
00000000
00000000
00000000
00000000
08000021
00000000

8、开始波形仿真和测试

利用iverilog、vvp、gtkwave工具进行编译、运行和显示之后,就可以判断一下跳转的功能有没有实现了。整个波形当中最关键的指标非pc寄存器莫属。当然,我们分析的时候还是一步一步来。

首先查看rst结束,接着就是ce置位,然后就是pc寄存器数值的更替。通过观察,我们发现pc的地址依次是0x0、0x4、0x8、0x20这样的。这个时候可以看一下测试的汇编代码。第一条汇编代码是ori  $1,$0,0x0001 ,第二条指令是j    0x20,第三条指令是ori  $1,$0,0x0002。而此时,0x20出的代码是,

 .org 0x20ori  $1,$0,0x0003

这说明两点。第一,pc跳转到0x20是完全正确的,获取的指令也是正确的。第二,在pc发生跳转的时候,当前指令的下一条指令,也就是延迟槽的指令也是被执行的。从上面的图形看,0x4是j 0x20,按照道理来说,下一条指令pc应该修改成了0x20。但是,我们发现pc在递增到0x8之后,才会真正修改为0x20,这说明延迟槽起了作用。

在实际应用中,延迟槽发挥了很大的作用,但是也给我们后续处理带来了一些麻烦,比如在发生异常中断的时候就要对延迟槽做特别的处理,而且要非常小心才行。

cpu设计和实现(pc跳转和延迟槽)相关推荐

  1. 【Computer Organization笔记10】单周期CPU设计:基于7条MIPS指令的数据通路

    本次笔记内容: P19 计算机组成原理(19) P20 计算机组成原理(20) 本节课对应幻灯片: 组成原理24 singlecycle.pptx 基于上节课的7条MIPS指令的数据通路,分别针对7条 ...

  2. 在VIVADO上实现的非常简易的RISC-V CPU设计(来自《Verilog数字系统设计》夏宇闻著)

    在VIVADO上实现的非常简易的RISC-V CPU设计 一.实验要求重述: 1.实验目的 2.实验要求: 二.学习准备: 1.什么cpu? 2.cpu需要具有哪些部件? 3.什么是RISC_CPU? ...

  3. 【中山大学计算机组成原理实验】单周期CPU设计与实现

    实验一 : 单周期CPU设计与实现 一. 实验目的 (1) 掌握单周期CPU数据通路图的构成.原理及其设计方法: (2) 掌握单周期CPU的实现方法,代码实现方法: (3) 认识和掌握指令与CPU的关 ...

  4. (Verilog)多周期CPU设计

    (Verilog)多周期CPU设计 写在前面:在参考别人的博客自己做了一遍单周期cpu后,觉得不是很难,于是自己尝试了做一下多周期cpu,然后被各种bug糊脸...果然,自己尝试和有大佬指路还是有很大 ...

  5. (Verilog)单周期CPU设计

    (Verilog)单周期CPU设计 首先是基础资料部分(借用学校资料): 一.实验内容 设计一个单周期CPU,该CPU至少能实现以下指令功能操作.需设计的指令与格式如下: ==> 算术运算指令 ...

  6. MIPS-单周期CPU设计

    MIPS-单周期CPU设计 设计一个单周期CPU,该CPU至少能实现以下指令功能操作.需设计的指令与格式如下: 实验原理 单周期CPU指的是一条指令的执行在一个时钟周期内完成,然后开始下一条指令的执行 ...

  7. 单周期CPU设计(Verilog)

    2017/06/08: 当时单周期cpu写的比较仓促,没有深入的进行调试,我准备在放假的时候重构一下代码, 然后把博文改进一下,现在实在没有时间,很抱歉~ 不过多周期我有调试过的,所以有需要的可以移步 ...

  8. Verilog流水线CPU设计(超详细)

    上篇:Verilog单周期CPU设计(超详细) 本篇完整工程下载链接,已于19.12.17更新 实验 流水线CPU 一.设计目的与要求 1.1 实验内容 1.2 实验要求 1.3 实验创新 二.课程设 ...

  9. 16位流水线CPU设计(部分)

    一.16位流水线CPU结构 概括:本文介绍一个16位的流水线CPU设计与模拟过程,该流水线CPU由IF.ID.EXE.MEM和WB五个功能段组成,结构如下图所示.在各功能段之间分别设计了四个锁存段,即 ...

最新文章

  1. 使用二次封装的openStack发行版本网卡至少有2个
  2. js 小数点 精准算法
  3. mvc:interceptor 不起作用的一个解决方法
  4. php数据趋势曲线,数据曲线图怎么做
  5. 为啥查询那么慢?看完你就明白了!
  6. 安装github for windows问题解决
  7. Cygwin-安装和配置ssh服务
  8. linux 3.11 虚拟摄像头 驱动,摄像头万能驱动-万能视频驱动-摄像头万能驱动下载 v2011.3官方版-完美下载...
  9. Uniapp打iOS离线包到出ipa安装思路
  10. 《东周列国志》第十六回 释槛囚鲍叔荐仲 战长勺曹刿败齐
  11. 开课吧 dubbo+zookeeper
  12. 失望时想起了你是什么歌_你是空你是空色即是空的空空什么歌 《想起了你》哪里听...
  13. iOS10新特性——————陈Hong鑫
  14. python学习笔记(七):运算符和流程控制
  15. sap 服务器 拷贝文件,本文示例如何使用SAP FTP Function将文件从应用服务器传输到另外一个FTP服务器上。...
  16. 浓缩德国奎尔鱼油 (QÜELL FISH OIL™ HIGHT EPA / DHA / D)
  17. 如何在线将XPS转换成PDF?
  18. tensorFlow2基本操作(三)
  19. IC验证中的force/release 学习整理(5)研究对 reg类型信号的影响
  20. 触发器的四个应用场景

热门文章

  1. 【智慧照明】宾馆智能照明控制系统
  2. css【详解】steps()函数
  3. java如何通过client客戶端http实现get/ post请求传递json参数到restful 服务接口
  4. rtx服务器设置 文件,rtx 服务器 文件传输 配置
  5. 云服务器价格比较,用哪家的比较划算?
  6. 启发式算法与元启发式算法的区别
  7. AHB总线介绍及其时序图
  8. 如何用数据找到下一家独角兽?
  9. 微信小程序云开发导出CSV文件时出现乱码
  10. idea设置类注释和方法注释模板