• 欢迎访问搞代码网站,推荐使用最新版火狐浏览器和Chrome浏览器访问本网站!
  • 如果您觉得本站非常有看点,那么赶紧使用Ctrl+D 收藏搞代码吧

自己动手写CPU之第八阶段(4)转移指令实现过程2

mysql 搞代码 4年前 (2022-01-09) 18次浏览 已收录 0个评论
文章目录[隐藏]

将陆续上传本人写的新书《 自己动手写CPU 》,今天是第36篇,我尽量每周四篇 开展晒书评送书活动,在亚马逊、京东、当当三大图书网站上,发表《自己动手写CPU》书评的前十名读者,均可获赠《步步惊芯——软核 处理器 内部 设计 分析 》一书,大家踊跃参与吧

将陆续上传本人写的新书《自己动手写CPU》,今天是第36篇,我尽量每周四篇

开展晒书评送书活动,在亚马逊、京东、当当三大图书网站上,发表《自己动手写CPU》书评的前十名读者,均可获赠《步步惊芯——软核处理器内部设计分析》一书,大家踊跃参与吧!活动时间:2014-9-11至2014-10-20

8.4.3 修改执行阶段的EX 模块

参考图8-6可知,EX模块需要增加一些接口,增加的接口描述如表8-4所示。

EX模块的代码主要修改如下,完整代码请参考本书附带光盘Code\Chapter8目录下的ex.v文件。

module ex(  ......  // 处于执行阶段的转移指令要保存的返回地址  input wire[`RegBus]           link_address_i,  // 当前执行阶段的指令是否位于延迟槽  input wire                    is_in_delayslot_i,		  ...... 	);	  ......  always @ (*) begin  ......	     case ( alusel_i )       `EXE_RES_LOGIC:		begin        wdata_o <= logicout;      end      `EXE_RES_SHIFT:		begin        wdata_o <= shiftres;      end	 	      `EXE_RES_MOVE:		begin        wdata_o <= moveres;      end	 	      `EXE_RES_ARITHMETIC:	begin        wdata_o <= arithmeticres;      end      `EXE_RES_MUL:		begin        wdata_o <= mulres[31:0];      end	 	      `EXE_RES_JUMP_BRANCH:	begin        wdata_o <= link_address_i;      end      default:					begin        wdata_o <= `ZeroWord;      end    endcaseend		......			endmodule

如果alusel_o为EXE_RES_JUMP_BRANCH,那么就将返回地址link_address_i作为要写入目的寄存器的值赋给wdata_o。

注意一点,此处并没有利用输入的信号is_in_delayslot_i,该信号表示当前处于执行阶段的指令是否是延迟槽指令,这个信号会在异常处理过程中使用到,本章暂时不需要。

8.4.4 修改OpenMIPS模块

因为有一些模块添加了接口,所以需要修改顶层模块OpenMIPS,以将这些新增加的接口按照图8-6所示的关系连接起来。具体修改也很简单,不在书中列出,读者可以参考本书附带光盘Code\Chapter8目录下的openmips.v文件。

8.5 测试转移指令的实现效果

本节将通过两个测试程序验证转移指令是否实现正确,这两个测试程序分别验证跳转指令、分支指令。

8.5.1 测试跳转指令

测试代码如下,源文件是本书光盘Code\Chapter8\AsmTest\Test1目录下的inst_rom.S文件。

.org 0x0.set noat.set noreorder      # 添加这个伪操作,指示编译器不要对程序做出任何优化或是改动.set nomacro        .global _start_start:   ori  $1,$0,0x0001   # (1)$1 = 0x1                   j    0x20           #  转移到0x20处   ori  $1,$0,0x0002<mark>来源gaodaimacom搞#^代%!码网</mark>   # (2)$1 = 0x2,这是延迟槽指令   ori  $1,$0,0x1111   ori  $1,$0,0x1100   .org 0x20   ori  $1,$0,0x0003   # (3)$1 = 0x3                  jal  0x40           #  转移到0x40处,同时设置$31为0x2c   div  $zero,$31,$1   # (4)此时$31 = 0x2c, $1 = 0x3,所以得到除法结果                       #     HI = 0x2, LO = 0xe,这是延迟槽指令   ori  $1,$0,0x0005   # (6)$1 = 0x5   ori  $1,$0,0x0006   # (7)$1 = 0x6   j    0x60           #  转移到0x60处   nop   .org 0x40   jalr $2,$31          #  此时$31为0x2c,所以转移到0x2c,同时设置$2为0x48   or   $1,$2,$0        # (5)$1 = 0x48,这是延迟槽指令   ori  $1,$0,0x0009    # (10)$1 = 0x9   ori  $1,$0,0x000a    # (11)$1 = 0xa   j 0x80               #  转移到0x80处   nop   .org 0x60   ori  $1,$0,0x0007    # (8)$1 = 0x7    jr   $2              #  此时$2为0x48,所以转移到0x48处   ori  $1,$0,0x0008    # (9)$1 = 0x8,这是延迟槽指令   ori  $1,$0,0x1111   ori  $1,$0,0x1100   .org 0x80   nop    _loop:   j _loop   nop

8.5.2 测试分支指令

测试代码如下,源文件是本书光盘Code\Chapter8\AsmTest\Test2目录下的inst_rom.S文件。

.org 0x0   .set noat   .set noreorder   .set nomacro   .global _start_start:   ori  $3,$0,0x8000   sll  $3,16               # 设置$3 = 0x80000000   ori  $1,$0,0x0001        #(1)$1 = 0x1                   b    s1                  # 转移到s1处   ori  $1,$0,0x0002        #(2)$1 = 0x2,这是延迟槽指令1:   ori  $1,$0,0x1111   ori  $1,$0,0x1100   .org 0x20s1:   ori  $1,$0,0x0003        #(3)$1 = 0x3   bal  s2                  # 转移到s2处,同时设置$31为0x2c   div  $zero,$31,$1        #(4)此时$31 = 0x2c, $1 = 0x3,所以除法结果为                            #    HI = 0x2, LO = 0xe,这是延迟槽指令   ori  $1,$0,0x1100   ori  $1,$0,0x1111   bne  $1,$0,s3   nop   ori  $1,$0,0x1100   ori  $1,$0,0x1111   .org 0x50   s2:   ori  $1,$0,0x0004      #(5)$1 = 0x4   beq  $3,$3,s3          # $3等于$3,所以会发生转移,目的地址是s3   or   $1,$31,$0         #(6)$1 = 0x2c,这是延迟槽指令   ori  $1,$0,0x1111   ori  $1,$0,0x11002:   ori  $1,$0,0x0007      #(9)$1 = 0x7   ori  $1,$0,0x0008      #(10)$1 = 0x8   bgtz $1,s4             # 此时$1为0x8,大于0,所以转移至标号s4处   ori  $1,$0,0x0009      #(11)$1 = 0x9,这是延迟槽指令   ori  $1,$0,0x1111   ori  $1,$0,0x1100   .org 0x80s3:   ori  $1,$0,0x0005      #(7)$1 = 0x5               bgez $1,2b             # 此时$1为0x5,大于0,所以转移至前面的标号2处   ori  $1,$0,0x0006      #(8)$1 = 0x6,这是延迟槽指令   ori  $1,$0,0x1111   ori  $1,$0,0x1100   .org 0x100s4:   ori  $1,$0,0x000a      #(12)$1 = 0xa                 bgezal $3,s3           # 此时$3为0x80000000,小于0,所以不发生转移   or   $1,$0,$31         #(13)$1 = 0x10c             ori  $1,$0,0x000b      #(14)$1 = 0xb   ori  $1,$0,0x000c      #(15)$1 = 0xc   ori  $1,$0,0x000d      #(16)$1 = 0xd   ori  $1,$0,0x000e      #(17)$1 = 0xe   bltz $3,s5             # 此时$3为0x80000000,小于0,所以发生转移,转移至s5处   ori  $1,$0,0x000f      #(18)$1 = 0xf,这是延迟槽指令   ori  $1,$0,0x1100   .org 0x130s5:   ori  $1,$0,0x0010      #(19)$1 = 0x10   blez $1,2b             # 此时$1为0x10,大于0,所以不发生转移   ori  $1,$0,0x0011      #(20)$1 = 0x11   ori  $1,$0,0x0012      #(21)$1 = 0x12   ori  $1,$0,0x0013      #(22)$1 = 0x13   bltzal $3,s6           # 此时$3为0x80000000,小于0,所以发生转移,转移到s6处   or   $1,$0,$31         #(23)$1 = 0x14c,这是延迟槽指令   ori  $1,$0,0x1100   .org 0x160s6:   ori $1,$0,0x0014       #(24)$1 = 0x14   nop          _loop:   j _loop   nop

上面的测试程序使用到了所有的分支指令,程序的注释给出了寄存器$1的变化情况,及指令执行顺序,注意寄存器$1的变化是按照注释中的序号顺序进行的。ModelSim仿真结果如图8-9所示,观察$1的变化可知OpenMIPS正确实现了分支指令。

至此,转移指令也实现完毕了,下一步将实现加载存储指令,敬请关注!


搞代码网(gaodaima.com)提供的所有资源部分来自互联网,如果有侵犯您的版权或其他权益,请说明详细缘由并提供版权或权益证明然后发送到邮箱[email protected],我们会在看到邮件的第一时间内为您处理,或直接联系QQ:872152909。本网站采用BY-NC-SA协议进行授权
转载请注明原文链接:自己动手写CPU之第八阶段(4)转移指令实现过程2

喜欢 (0)
[搞代码]
分享 (0)
发表我的评论
取消评论

表情 贴图 加粗 删除线 居中 斜体 签到

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址