发布时间:2024-02-03 15:30
因为OpenMIPS设计乘累加、乘累减、除法指令在流水线执行阶段占用多个时钟周期,因此需要暂停流水线,以等待这些多周期指令执行完毕。
OpenMIPS采用的是一种改进的方法:假如位于流水线第n阶段的指令需要多个时钟周期,进而请求流水线暂停,那么需保持取指令地址PC的值不变,同时保持流水线第n阶段、第n阶段之前的各个阶段的寄存器不变,而第n阶段后面的指令继续运行。
为此设计添加了CTRL模块,其作用是接收各阶段传递过来的流水线暂停请求信号,从而控制流水线各阶段的运行。
CTRL的输入来自译码、执行阶段的请求暂停信号stallreq,对于OpenMIPS而言只有译码、执行会有暂停请求,而其他阶段都没有,因为指令的读取、数据存储器的读写都可以在一个时钟周期内完成。
当CTRL收到暂停信号时会对信号进行判断,然后输出流水线暂停信号stall给各个模块
要添加一个CTRL模块
注意暂停信号stall是一个宽度为6的信号,其含义为
stall[0]表示取址地址PC是否保持不变,为1保持不变
stall[1]表示流水线取指阶段是否暂停,为1表示暂停
stall[2]表示流水线译码阶段是否暂停,为1表示暂停
stall[3]表示流水线执行阶段是否暂停,为1表示暂停
stall[4]表示流水线访存阶段是否暂停,为1表示暂停
stall[5]表示流水线回写阶段是否暂停,为1表示暂停
乘累加、乘累减指令共4条,包括madd、maddu、msub、msubu。从图中可知,这4条指令的指令码都是SPECIAL2,第6~15bit都为0,可以依据第0~5bit的功能码确定是哪一种指令。
madd指令 -有符号乘累加
用法:madd rs, rt
作用:{HI, LO}<-{HI, LO}+ rs x rt
将地址为rs的通用寄存器的值与地址为rt的通用寄存器的值作为有符号数进行乘法运算,运算结果与{HI, LO}相加,相加的结果保存到{HI, LO}中。此处{HI, LO}表示 HI、LO寄存器连接形成的64位数,HI是高32位,LO是低32位
maddu指令 -无符号乘累加
用法:maddu rs, rt
作用: {HI, LO} <- {HI, LO} + rs × rt
将地址为rs的通用寄存器的值与地址为rt的通用寄存器的值作为无符号数进行乘法运算,运算结果与{HI, LO}相加,相加的结果保存到{HI,LO}中
msub指令 -有符号乘累减
用法:msub rs, rt
作用:{HI, LO}<-{HI,LO} - rs × rt
将地址为rs 的通用寄存器的值与地址为rt的通用寄存器的值作为有符号数进行乘法运算。然后使用{HI,LO}减去乘法结果,相减的结果保存到{HI,LO}中
msubu指令 -无符号乘累减
用法:msubu rs, rt
作用:{HI, LO} <-{HI, LO} - rs × rt,
将地址为rs的通用寄存器的值与地址为rt的通用寄存器的值作为无符号数进行乘法运算。然后使用{HI,LO}减去乘法结果,相减的结果保存到{HI,LO}中
乘累加与乘累减指令计划在流水线阶段采用两个时钟周期完成运算,所以必须要保存两个信息:
1.当前是第几个时钟周期
2.乘法结果。
所以OpenMIPS通过在EX/MEM模块添加两个寄存器cnt、hilo,分别保存上述信息。修改系统结构框图如下所示:
EX模块的输出hilo_temp_o是乘法结果,传递到EX/MEM模块,并在下一个时钟周期送回EX模块,参与第二个时钟周期
EX模块的输出cnt_o代表当前是第几个时钟周期,传递到EX/MEM模块,并在下一个时钟周期送回EX模块,参与第二个时钟周期
修改ID模块
译码阶段的ID模块要添加对乘累加、乘累减指令的分析,根据给出的指令格式可知,这4条指令都是 SPECIAL2类指令,可以依据功能码确定是哪一种指令。
修改EX模块
1.计算乘法结果:若计算为有符号乘法且乘数或被乘数为负的时候,将该值修改为补码。修改后得出临时结果
2.乘累加、乘累减:判断cnt在执行第几个周期,若为第一个则进行乘法,第二个则为加/减法
3.暂停流水线
4.修改HI、LO寄存器的写信息
OpenMIPS采用"试商法"实现除法运算,对于32位的除法,至少需要32个时钟周期才能得到除法结果
除法指令有2条,包括div、divu,从图中可知这2条指令的指令码都是SPECIAL,可根据功能码确定是哪种指令。
div指令 -有符号除法
用法:div rs,rt
作用:{HI, LO} <- rs/rt
将地址为rs的通用寄存器的值,与地址为rt的通用寄存器的值作为有符号数进行除法运算,将商保存到寄存器LO,余数保存到寄存器HI
divu指令 -无符号除法
用法:divu rs,rt
作用:{HI, LO} <- rs/rt
将地址为rs的通用寄存器的值,与地址为rt的通用寄存器的值作为无符号数进行除法运算,将商保存到寄存器LO,余数保存到寄存器HI
试商法其实就是一个模拟除法的过程
新建一个模块 DIV,在其中实现采用试商法的32位除法运算。当流水线执行阶段的EX模块发现当前指令是除法指令时,首先暂停流水线,然后将被除数、除数等信息送到DIV模块,开始除法运算。DIV模块在除法运算结束后,通知EX模块,并将除法结果送到EX模块,后者依据除法结果设置HI、LO寄存器的写信息,同时取消暂停流水线。
DIV模块的主要部分是一个状态机,共有四个状态
修改后的数据流图如下
MUX:增加一个选择器,用来确定PC的值。PC在下一个周期可以是PC+4,也可以不变(流水线暂停)。后面我们会学到转移指令时也会用这个模块进行判断。
修改后的系结构图如下
dividend的低32位保存的是被除数、中间结果,第k次迭代结束的时候dividend[k:0]保存到就是当前得到的中间结果,dividend[31:k+1]保存到就是除数中还没有参与运算的数据
DivFree:
除数为0
除数不为0:负数要取补码
DivByZero:
返回0,0
DivOn:
如果annul_i == 1,表示处理器取消除法运算,那么DIV模块直接回到DivFree
如果annul_i == 0,且cnt != 32, 表示试商法还没结束,此时若div_temp为负,则结果为0;若为正,则结果为1
如果annul_i == 0,且cnt ==32,表示试商法结束,如果是有符号除法且被除数、除数一正一负,那么将试商法的结果取补码,得到最终的结果,此时商、余数都要取补码。同时进入DivEnd状态
DivEnd:
结果64位,高32位存余数、低32存商
作者使用的是一段式的状态机,里面阻塞和非阻塞赋值交替使用,对于小白来说可以了解一下三段式的写法,这样虽然代码长了一点,但也便于理解。
ENVI_IDL:使用反距离权重法选取最近n个点插值(底层实现)并输出为Geotiff格式(效果等价于Arcgis中反距离权重插值)
JASMINER:创新突破存算一体核心技术,抢占高通量芯片制高点
软件测试mysql面试题:Delete,Truncate和Drop命令之间有什么区别?
CloudBees CI使用Velero进行灾备(DR)概念验证
Nginx 部署的虚拟主机如何使用 Let‘s Encrypt 来进行加密 https
cocos draw call 优化,内存优化,网络优化,宽高适配,包体优化
anaconda配置pytorch(无需单独安装python)
ERROR: THESE PACKAGES DO NOT MATCH THE HASHES FROM THE REQUIREMENTS FILE. If you have updated the