func_and_tools.hpp
:myspa
中放了所有需要的枚举类型、常量、功能函数(得到立即数和十六进制转十进制)。memory.hpp
:Memory_simu
类作为内存,把读入的指令放置在mem[]
中,initialize()
时把所有指令读入。program.hpp
: 在类program
中,Reg[]
指代寄存器。
- 当遇到data_hazard和部分control_hazard时暂停流水。
- 结构体
ID_Reg
,EXE_Reg
,MEM_Reg
,WB_Reg
分别用于暂存从IF()
到ID()
,从ID()
到EXE()
,从EXE()
到MEM()
,从MEM()
到WB()
的数据。 - 需要暂停流水时,在
IF()
时设置dReg.now_code
为-1,在ID()
时若dReg.now_code
为-1,则把eReg.type
设为NOType
,在接下来的函数中,若其类型为NOType
,则把它传给下一个函数的结构体中的type也设为NOType
,并return。这样流水就被暂停了一个回合。
cycle
用于在mem()
时用三周期模拟,当某条指令需要内存操作时,设置cycle
为3,接下来的循环中,IF()
时若cycle
不为0,就将cycle
减1并暂停流水。
- 使用两位饱和计数器,结构体
branch_pre_cache
用于缓存。 - 在
IF()
时判断上一条指令是否是B开头的指令,再根据缓存结构体的jud()
预测是否跳转,在这个过程中,用结构体中的pos_c
暂存该指令的位置,pc不改变。 - 在
EXE()
中跳转与不跳转的情况下分别对缓存结构体调用push()
函数。若预测成功则继续流水,若预测不成功则对dReg
重新取值,然后流水可以继续。 - 特别的,若读到的指令是结束指令,则不论是否预测成功,都当成不成功,直接把
pos_c
设为pc不可能变为的值,把dReg.now_code
设为-1。 - 调用函数
success_rate()
可输出成功率,最高能达到85%,最低只有17%,平均在60%左右。当然,对于分支预测成功率而言,小数据并没有意义,对于较大的数据,成功率可以达到75%左右。
- 在
ID()
时判断这一轮是否用到上一轮要修改的寄存器,如果用到,就把值从上一轮EXE()
时算出来的mReg.data
直接拿来。
- 含义:对于指令123,若2与1产生了data_hazard,而3与1、2独立,对1暂停流水时,可先执行3操作,然后再执行2操作。