好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

自己动手写CPU之第六阶段(2)移动操作指令实现思路

将陆续上传本人写的新书《自己动手写CPU》(尚未出版),今天是第21篇,我尽量每周四篇 6.2 移动操作指令实现思路 6.2.1 实现思路 这 6 条移动操作指令可以分为两类:一类是不涉及特殊寄存器 HI 、 LO 的指令,包括 movn 、 movz ;另一类是涉及特殊寄存器 H

将陆续上传本人写的新书《自己动手写CPU》(尚未出版),今天是第21篇,我尽量每周四篇


6.2 移动操作指令实现思路

6.2.1 实现思路

这 6 条移动操作指令可以分为两类:一类是不涉及特殊寄存器 HI 、 LO 的指令,包括 movn 、 movz ;另一类是涉及特殊寄存器 HI 、 LO 的指令,包括 mfhi 、 mflo 、 mthi 、 mtlo 。前一类很好实现,基本思路与第 5 章实现逻辑、移位操作指令时类似,只需要修改 ID 、 EX 模块即可。后一类涉及到特殊寄存器 HI 、 LO ,需要为 OpenMIPS 添加 HI 、 LO 寄存器,以及相应的读写控制。下面分别介绍各自的实现思路。

1 、 movn 、 movz 指令实现思路

与第 5 章逻辑、移位操作指令的实现过程类似。

( 1 )在译码阶段给出运算类型 alusel_o 、运算子类型 aluop_o 、要写入的目的寄存器地址 wd_o 等信号的值,同时读取地址为 rs 、 rt 的通用寄存器的值,但是这里需要新增一个步骤:依据读取的地址为 rt 的通用寄存器的值是否为 0 ,判断是否要写目的寄存器。将上述结果送到执行阶段。

( 2 )执行阶段依据传入的信号,确定最终要写目的寄存器的信息(包含:是否写、写入的目的寄存器地址、写入的值),并将这些信息传递到访存阶段。

( 3 )上述信息会一直传递到回写阶段。最后,依据这些信息修改目的寄存器,或者不作任何修改。

2 、 mthi 、 mtlo 指令实现思路

这 2 条指令需要写 HI 、 LO 寄存器,与之前实现的通用寄存器一样,对 HI 、 LO 寄存器的写操作放在回写阶段进行。

( 1 )在译码阶段依据指令,给出运算类型 alusel_o 、运算子类型 aluop_o 的值,同时读出地址为 rs 的通用寄存器的值。由于 mthi 、 mtlo 不写通用寄存器,所以 wreg_o 为 WriteDisable , wd_o 为 0 。

( 2 )在执行阶段确定要写 HI 、 LO 寄存器的情况,以及要写入的值,并将这些信息传递到访存阶段。

( 3 )访存阶段将这些信息再传递到回写阶段。

( 4 )回写阶段依据这些信息修改 HI 、 LO 寄存器的值。

3 、 mfhi 、 mflo 指令实现思路

这 2 条指令需要读 HI 、 LO 寄存器,设计在执行阶段才能读取到。

( 1 )在译码阶段依据指令,给出运算类型 alusel_o 、运算子类型 aluop_o 的值,同时因为有要写的目的寄存器,所以 wreg_o 为 WriteEnable , wd_o 为指令中 rd 的值,也就是目的寄存器地址。

( 2 )在执行阶段获取 HI 或 LO 寄存器的值,作为要写入目的寄存器的数据,并将这些信息传递到访存阶段。

( 3 )访存阶段将这些信息再传递到回写阶段。

( 4 )回写阶段依据这些信息修改目的寄存器。

添加移动操作指令后的数据流图如图 6-2 所示。


对比图 6-2 与图 5-7 可以发现有如下区别。

增加了 HILO 寄存器模块,并且该模块放在回写阶段。 将 HI 、 LO 寄存器的值传递到执行阶段,在执行阶段增加了一个选择模块,用于选择要参与运算的数据,如果是 mfhi 、 mflo 指令,那么就会选择传递过来的 HI 、 LO 寄存器的值。

6.2.2 新的数据相关情况的解决

进一步考虑 mfhi 、 mflo 指令的处理过程,这 2 条指令会在流水线执行阶段读取 HI 、 LO 寄存器的值,如果直接采用 HILO 模块给出的 HI 、 LO 寄存器的值,可能不是正确的 HI 、 LO 寄存器的值,因为此时处于访存、回写阶段的指令有可能会修改 HI 、 LO 寄存器,以如下程序为例。

1、    lui $1,0x0000          # $1 = 0x00000000
2、    lui $2,0xffff          # $1 = 0xffff0000
3、    mthi $0                # hi = 0x00000000
4、    mthi $1                # hi = 0x00000000
5、    mthi $2                # hi = 0xffff0000
6、    mfhi $4                # $4 = 0xffff0000 

指令 3 、 4 、 5 均要修改 HI 寄存器,当指令 6 处于执行阶段时,指令 5 处于访存阶段,指令 4 处于回写阶段,而此时 HI 寄存器的值是指令 3 刚刚写入的 0x00000000 , HILO 模块正是将该值传到执行阶段,如果采用这个值,那么就会出错,偏离程序设想,正确的值应该是当前处于访存阶段的指令 5 要写的数据,如图 6-3 所示。


似曾相识,是不是?这就是上一章介绍过的数据相关问题,解决措施还是使用数据前推。将处于访存阶段、回写阶段的指令对 HI 、 LO 寄存器的操作信息反馈到执行阶段,执行阶段依据这些信息,确定 HI 、 LO 寄存器的正确值。

为此,需要修改数据流图如图 6-4 所示,相比图 6-3 ,主要增加的部分就是将访存阶段、回写阶段的信息反馈到执行阶段,输入到执行阶段的选择模块(图中粗线所示),如果处于执行阶段的是 mfhi 、 mflo 指令,那么就会从中选择 HI 、 LO 寄存器的正确值。


6.2.3 系统结构的修改

为了实现移动操作指令需要对 OpenMIPS 系统结构进行补充完善,主要修改如图 6-5 所示。


主要有三个方面。

( 1 )增加了 HILO 模块,用于实现 HI 、 LO 寄存器。

( 2 )执行阶段的 EX 模块增加了 whilo_o 、 hi_o 、 lo_o 接口,分别表示是否要写 HILO 、要写入 HI 寄存器的值、要写入 LO 寄存器的值。这三个接口传递出来的,对 HI 、 LO 寄存器的修改信息会通过 EX/MEM 、 MEM 、 MEM/WB 三个模块一直传递到回写阶段,并最终传递给 HILO 模块。

( 3 )执行阶段的 EX 模块增加了与 HI 、 LO 寄存器有关的输入接口,包括为解决 HI 、 LO 寄存器的数据相关问题而引入的接口,在 6.3.3 节会有详细介绍。

下一次会介绍移动操作指令实现,并给出代码,敬请关注!

查看更多关于自己动手写CPU之第六阶段(2)移动操作指令实现思路的详细内容...

  阅读:48次