#include "common.h" // 饱和计数器:加1 static inline UINT32 SatIncrement(UINT32 x, UINT32 max) { if (x0) return x - 1; return x; } #define BITS_OF_PC 13 // 选择13位的PC作为索引 #define STATE_MAX 3 #define STATE_INIT 2 UINT32 *State; // 状态数组,用于保存分支指令的状态机,实际只使用最低2位 UINT64 StateArraySize; void PREDICTOR_init(void) { StateArraySize = (1 << BITS_OF_PC); // 状态数组项数 State = (UINT32 *)malloc(StateArraySize * sizeof(UINT32)); // *********** 你需要在下面书写代码 *********** // 将状态数组,全部初始化为STATE_INIT for(UINT32 i = 0; i < StateArraySize; i++) { State[i] = 2; } // *********** 你需要在上面书写代码 *********** } // 2位状态的分支预测器(预测部分) char GetPrediction(UINT64 PC) { // *********** 你需要在下面书写代码 *********** // 将PC的低13位,去索引状态数组State,得到对应的饱和状态 // 如果该状态的值超过一半,则预测跳转 // 如果该状态的值低于一半,则预测不跳转 UINT32 index = PC>>2 & 0x1fff; if(State[index] == 0 || State[index] == 1) return NOT_TAKEN; return TAKEN; //return TAKEN; //return NOT_TAKEN; // *********** 你需要在上面书写代码 *********** } // 2位状态的分支预测器(更新部分) void UpdatePredictor(UINT64 PC, OpType opType, char resolveDir, char predDir, UINT64 branchTarget) { // *********** 你需要在下面书写代码 *********** // 根据分支指令实际执行结果,来更新对应的饱和计数器 // 如果结果为跳转,则对应的饱和计数器+1 // 如果结果为不跳转,则对应的饱和计数器-1 UINT32 index = PC>>2 & 0x1fff; if(resolveDir == 'T') { State[index] = SatIncrement(State[index], 3); } else { State[index] = SatDecrement(State[index]); } // *********** 你需要在上面书写代码 *********** } void PREDICTOR_free(void) { free(State); } #include "common.h" // 饱和计数器:加1 static inline UINT32 SatIncrement(UINT32 x, UINT32 max) { if (x0) return x - 1; return x; } #define BITS_OF_PC 13 // 选择13位的PC作为索引 #define STATE_MAX 7 #define STATE_INIT 3 UINT32 *State; // 状态数组,用于保存分支指令的状态机,实际只使用最低3位 UINT64 StateArraySize; void PREDICTOR_init(void) { StateArraySize = (1 << BITS_OF_PC); // 状态数组项数 State = (UINT32 *)malloc(StateArraySize * sizeof(UINT32)); // *********** 你需要在下面书写代码 *********** // 将状态数组,全部初始化为STATE_INIT for(UINT64 i = 0; i <= StateArraySize; i++) { State[i] = STATE_INIT; } // *********** 你需要在上面书写代码 *********** } // 2位状态的分支预测器(预测部分) char GetPrediction(UINT64 PC) { // *********** 你需要在下面书写代码 *********** // 将PC的低13位,去索引状态数组State,得到对应的饱和状态 // 如果该状态的值超过一半,则预测跳转 // 如果该状态的值低于一半,则预测不跳转 UINT64 index = (PC>>2) & 0x1fff; if(State[index] == 0 || State[index] == 1 || State[index] == 2 || State[index] == 3) return NOT_TAKEN; return TAKEN; //return TAKEN; //return NOT_TAKEN; // *********** 你需要在上面书写代码 *********** } // 2位状态的分支预测器(更新部分) void UpdatePredictor(UINT64 PC, OpType opType, char resolveDir, char predDir, UINT64 branchTarget) { // *********** 你需要在下面书写代码 *********** // 根据分支指令实际执行结果,来更新对应的饱和计数器 // 如果结果为跳转,则对应的饱和计数器+1 // 如果结果为不跳转,则对应的饱和计数器-1 UINT64 index = (PC>>2) & 0x1fff; if(resolveDir == 'T') { State[index] = SatIncrement(State[index], 7); } else { State[index] = SatDecrement(State[index]); } // *********** 你需要在上面书写代码 *********** } void PREDICTOR_free(void) { free(State); } #include "common.h" // 饱和计数器:加1 static inline UINT32 SatIncrement(UINT32 x, UINT32 max) { if (x < max) return x + 1; return x; } // 饱和计数器:减1 static inline UINT32 SatDecrement(UINT32 x) { if (x > 0) return x - 1; return x; } #define BITS_OF_PC 10 // 选择10位的PC作为索引 #define LOCAL_HIST_LEN 3 // 局部历史长度,3位 #define LOCAL_HIST_MASK ~(~0 << LOCAL_HIST_LEN) #define STATE_MAX 3 #define STATE_INIT 2 UINT32* pht; // pattern history table 模式历史表 UINT32 phtArraySize; // pht数组项数 UINT32* State; // 状态数组,用于保存分支指令的状态机,实际只使用最低2位 UINT64 StateArraySize; void PREDICTOR_init(void) { StateArraySize = (1 << (BITS_OF_PC + LOCAL_HIST_LEN)); // 状态数组项数 State = (UINT32*)malloc(StateArraySize * sizeof(UINT32)); phtArraySize = (1 << BITS_OF_PC); // pht数组项数 pht = (UINT32*)malloc(phtArraySize * sizeof(UINT32)); // *********** 你需要在下面书写代码 *********** // 将状态数组,全部初始化为STATE_INIT // 将模式历史表(pht)全部初始化为0 for(UINT64 i = 0; i < StateArraySize; i++) { State[i] = STATE_INIT; } for(UINT32 i = 0; i < phtArraySize; i++) { pht[i] = 0; } // *********** 你需要在上面书写代码 *********** } // 2位状态的分支预测器(预测部分) char GetPrediction(UINT64 PC) { // *********** 你需要在下面书写代码 *********** // 将PC的低10位,去索引模式历史表pht,得到对应的3位历史信息 UINT32 index1 = (PC>>2) & 0x3ff; // 将PC的低10位,与3位历史信息进行拼接,形成一个13位的状态数组索引(拼接需要使用C语言的移位、与、或等运算) //UINT64 index2 = (index1<<3) | (pht[index1]); //UINT64 index2 = (index1) | (pht[index1]<<10); UINT64 index2 = (index1 & 0x3ff) | (pht[index1]<<10 & 0x1c00); // 用13位去索引状态数组,得到对应的饱和状态 if(State[index2] == 0 || State[index2] == 1) return NOT_TAKEN; return TAKEN; // 如果该状态的值超过一半,则预测跳转 // 如果该状态的值低于一半,则预测不跳转 //return TAKEN; // return NOT_TAKEN; // *********** 你需要在上面书写代码 *********** } // 2位状态的分支预测器(更新部分) void UpdatePredictor(UINT64 PC, OpType opType, char resolveDir, char predDir, UINT64 branchTarget) { // *********** 你需要在下面书写代码 *********** // 根据分支指令实际执行结果,来更新对应的饱和计数器 // 如果结果为跳转,则对应的饱和计数器+1 // 如果结果为不跳转,则对应的饱和计数器-1 // 更新pht中的最近3次分支历史信息,使用移位寄存器来更新 // 将其更新到pht中 UINT32 index1 = (PC>>2) & 0x3ff; //UINT64 index2 = (index1<<3) | (pht[index1]); //UINT64 index2 = (index1) | (pht[index1]<<10); UINT64 index2 = (index1 & 0x3ff) | (pht[index1]<<10 & 0x1c00); if(resolveDir == 'T') { State[index2] = SatIncrement(State[index2], 3); pht[index1] = (pht[index1]<<1) | 0x1; } else { State[index2] = SatDecrement(State[index2]); pht[index1] = (pht[index1]<<1); } // *********** 你需要在上面书写代码 *********** } void PREDICTOR_free(void) { free(State); free(pht); } #include "common.h" // 饱和计数器:加1 static inline UINT32 SatIncrement(UINT32 x, UINT32 max) { if (x < max) return x + 1; return x; } // 饱和计数器:减1 static inline UINT32 SatDecrement(UINT32 x) { if (x > 0) return x - 1; return x; } #define BITS_OF_PC 9 // 选择9位的PC作为索引 #define LOCAL_HIST_LEN 4 // 局部历史长度,4位 #define LOCAL_HIST_MASK ~(~0 << LOCAL_HIST_LEN) #define STATE_MAX 3 #define STATE_INIT 2 UINT32* pht; // pattern history table 模式历史表 UINT32 phtArraySize; // pht数组项数 UINT32* State; // 状态数组,用于保存分支指令的状态机,实际只使用最低2位 UINT64 StateArraySize; void PREDICTOR_init(void) { StateArraySize = (1 << (BITS_OF_PC + LOCAL_HIST_LEN)); // 状态数组项数 State = (UINT32*)malloc(StateArraySize * sizeof(UINT32)); phtArraySize = (1 << BITS_OF_PC); // pht数组项数 pht = (UINT32*)malloc(phtArraySize * sizeof(UINT32)); // *********** 你需要在下面书写代码 *********** // 将状态数组,全部初始化为STATE_INIT // 将模式历史表(pht)全部初始化为0 for(UINT64 i = 0; i < StateArraySize; i++) { State[i] = STATE_INIT; } for(UINT32 i = 0; i < phtArraySize; i++) { pht[i] = 0; } // *********** 你需要在上面书写代码 *********** } // 2位状态的分支预测器(预测部分) char GetPrediction(UINT64 PC) { // *********** 你需要在下面书写代码 *********** // 将PC的低10位,去索引模式历史表pht,得到对应的3位历史信息 // 将PC的低10位,与3位历史信息进行拼接,形成一个13位的状态数组索引(拼接需要使用C语言的移位、与、或等运算) // 用13位去索引状态数组,得到对应的饱和状态 // 如果该状态的值超过一半,则预测跳转 // 如果该状态的值低于一半,则预测不跳转 UINT32 index1 = (PC>>2) & 0x1ff; UINT64 index2 = (index1 & 0x1ff) | (pht[index1]<<9 & 0x1e00); if(State[index2] == 0 || State[index2] == 1) return NOT_TAKEN; return TAKEN; //return TAKEN; // return NOT_TAKEN; // *********** 你需要在上面书写代码 *********** } // 2位状态的分支预测器(更新部分) void UpdatePredictor(UINT64 PC, OpType opType, char resolveDir, char predDir, UINT64 branchTarget) { // *********** 你需要在下面书写代码 *********** // 根据分支指令实际执行结果,来更新对应的饱和计数器 // 如果结果为跳转,则对应的饱和计数器+1 // 如果结果为不跳转,则对应的饱和计数器-1 // 更新pht中的最近3次分支历史信息,使用移位寄存器来更新 // 将其更新到pht中 UINT32 index1 = (PC>>2) & 0x1ff; UINT64 index2 = (index1 & 0x1ff) | (pht[index1]<<9 & 0x1e00); if(resolveDir == 'T') { State[index2] = SatIncrement(State[index2], 3); pht[index1] = (pht[index1]<<1) | 0x1; } else { State[index2] = SatDecrement(State[index2]); pht[index1] = (pht[index1]<<1); } // *********** 你需要在上面书写代码 *********** } void PREDICTOR_free(void) { free(State); free(pht); } #include "common.h" // 饱和计数器:加1 static inline UINT32 SatIncrement(UINT32 x, UINT32 max) { if (x < max) return x + 1; return x; } // 饱和计数器:减1 static inline UINT32 SatDecrement(UINT32 x) { if (x > 0) return x - 1; return x; } #define GLOBAL_HIST_LEN 13 // 全局历史长度,13位 #define GLOBAL_HIST_MASK ~(~0 << GLOBAL_HIST_LEN) #define STATE_MAX 3 #define STATE_INIT 2 UINT32 GHR; // Global History Register,全局历史寄存器 UINT32* State; // 状态数组,用于保存分支指令的状态机,实际只使用最低2位 UINT64 StateArraySize; void PREDICTOR_init(void) { StateArraySize = (1 << GLOBAL_HIST_LEN); // 状态数组项数 State = (UINT32*)malloc(StateArraySize * sizeof(UINT32)); // *********** 你需要在下面书写代码 *********** // 将状态数组,全部初始化为STATE_INIT // 将全局历史寄存器(GHR)初始化为0 for(UINT64 i = 0; i < StateArraySize; i++) { State[i] = STATE_INIT; } GHR = 0; // *********** 你需要在上面书写代码 *********** } // Gshare分支预测器(预测部分) char GetPrediction(UINT64 PC) { // *********** 你需要在下面书写代码 *********** // 用13位的GHR去索引状态数组,得到对应的饱和状态 // 如果该状态的值超过一半,则预测跳转 // 如果该状态的值低于一半,则预测不跳转 UINT64 index = GHR & 0x1fff; if(State[index] == 0 || State[index] == 1) return NOT_TAKEN; return TAKEN; // return TAKEN; // return NOT_TAKEN; // *********** 你需要在上面书写代码 *********** } // Gshare分支预测器(更新部分) void UpdatePredictor(UINT64 PC, OpType opType, char resolveDir, char predDir, UINT64 branchTarget) { // *********** 你需要在下面书写代码 *********** // 根据分支指令实际执行结果,来更新对应的饱和计数器 // 如果结果为跳转,则对应的饱和计数器+1 // 如果结果为不跳转,则对应的饱和计数器-1 // 更新GHR中的最近1次分支历史信息,使用移位寄存器来更新 UINT64 index = GHR & 0x1fff; if(resolveDir == 'T') { State[index] = SatIncrement(State[index], 3); GHR = GHR << 1 | 0x1; } else { State[index] = SatDecrement(State[index]); GHR = GHR << 1; } // *********** 你需要在上面书写代码 *********** } void PREDICTOR_free(void) { free(State); } #include "common.h" // 饱和计数器:加1 static inline UINT32 SatIncrement(UINT32 x, UINT32 max) { if (x < max) return x + 1; return x; } // 饱和计数器:减1 static inline UINT32 SatDecrement(UINT32 x) { if (x > 0) return x - 1; return x; } #define BITS_OF_PC 3 // 选择3位的PC作为索引 #define GLOBAL_HIST_LEN 10 // 全局历史长度,10位 #define STATE_INDEX_MASK ~(~0 << (BITS_OF_PC + GLOBAL_HIST_LEN)) #define STATE_MAX 3 #define STATE_INIT 2 UINT32 GHR; // Global History Register,全局历史寄存器 UINT32* State; // 状态数组,用于保存分支指令的状态机,实际只使用最低2位 UINT64 StateArraySize; void PREDICTOR_init(void) { StateArraySize = (1 << (BITS_OF_PC +GLOBAL_HIST_LEN)); // 状态数组项数 State = (UINT32*)malloc(StateArraySize * sizeof(UINT32)); // *********** 你需要在下面书写代码 *********** // 将状态数组,全部初始化为STATE_INIT // 将全局历史寄存器(GHR)初始化为0 for(UINT64 i = 0; i < StateArraySize; i++) { State[i] = STATE_INIT; } GHR = 0; // *********** 你需要在上面书写代码 *********** } // Gshare分支预测器(预测部分) char GetPrediction(UINT64 PC) { // *********** 你需要在下面书写代码 *********** // 将PC的低3位,与10位GHR进行拼接,形成一个13位的状态数组索引 // 用13位去索引状态数组,得到对应的饱和状态 // 如果该状态的值超过一半,则预测跳转 // 如果该状态的值低于一半,则预测不跳转 UINT64 index = (((PC>>2 & 0x7) << 10) & 0x1c00) | (GHR & 0x3ff); if(State[index] == 0 || State[index] == 1) return NOT_TAKEN; return TAKEN; // return TAKEN; // return NOT_TAKEN; // *********** 你需要在上面书写代码 *********** } // Gshare分支预测器(更新部分) void UpdatePredictor(UINT64 PC, OpType opType, char resolveDir, char predDir, UINT64 branchTarget) { // *********** 你需要在下面书写代码 *********** // 根据分支指令实际执行结果,来更新对应的饱和计数器 // 如果结果为跳转,则对应的饱和计数器+1 // 如果结果为不跳转,则对应的饱和计数器-1 // 更新GHR中的最近1次分支历史信息,使用移位寄存器来更新 UINT64 index = (((PC>>2 & 0x7) << 10) & 0x1c00) | (GHR & 0x3ff); if(resolveDir == 'T') { State[index] = SatIncrement(State[index], 3); GHR = GHR << 1 | 0x1; } else { State[index] = SatDecrement(State[index]); GHR = GHR << 1; } // *********** 你需要在上面书写代码 *********** } void PREDICTOR_free(void) { free(State); } #include "common.h" // 饱和计数器:加1 static inline UINT32 SatIncrement(UINT32 x, UINT32 max) { if (x < max) return x + 1; return x; } // 饱和计数器:减1 static inline UINT32 SatDecrement(UINT32 x) { if (x > 0) return x - 1; return x; } #define GLOBAL_HIST_LEN 13 // 全局历史长度,13位 #define GLOBAL_HIST_MASK ~(~0 << GLOBAL_HIST_LEN) #define STATE_MAX 3 #define STATE_INIT 2 UINT32 GHR; // Global History Register,全局历史寄存器 UINT32* State; // 状态数组,用于保存分支指令的状态机,实际只使用最低2位 UINT64 StateArraySize; void PREDICTOR_init(void) { StateArraySize = (1 << GLOBAL_HIST_LEN); // 状态数组项数 State = (UINT32*)malloc(StateArraySize * sizeof(UINT32)); // *********** 你需要在下面书写代码 *********** // 将状态数组,全部初始化为STATE_INIT // 将全局历史寄存器(GHR)初始化为0 for(UINT64 i = 0; i < StateArraySize; i++) { State[i] = STATE_INIT; } GHR = 0; // *********** 你需要在上面书写代码 *********** } // Gshare分支预测器(预测部分) char GetPrediction(UINT64 PC) { // *********** 你需要在下面书写代码 *********** // 将PC的低13位,与13位GHR进行异或,形成一个13位的状态数组索引 // 用13位去索引状态数组,得到对应的饱和状态 // 如果该状态的值超过一半,则预测跳转 // 如果该状态的值低于一半,则预测不跳转7] UINT64 nPC = (PC) & 0x1fff; UINT64 index = nPC ^ (GHR & 0x1fff); if(State[index] == 0 || State[index] == 1) return NOT_TAKEN; return TAKEN; // return TAKEN; // return NOT_TAKEN; // *********** 你需要在上面书写代码 *********** } // Gshare分支预测器(更新部分) void UpdatePredictor(UINT64 PC, OpType opType, char resolveDir, char predDir, UINT64 branchTarget) { // *********** 你需要在下面书写代码 *********** // 根据分支指令实际执行结果,来更新对应的饱和计数器 // 如果结果为跳转,则对应的饱和计数器+1 // 如果结果为不跳转,则对应的饱和计数器-1 // 更新GHR中的最近1次分支历史信息,使用移位寄存器来更新 UINT64 nPC = (PC) & 0x1fff; UINT64 index = nPC ^ (GHR & 0x1fff); if(resolveDir == 'T') { State[index] = SatIncrement(State[index], 3); GHR = GHR << 1 | 0x1; } else { State[index] = SatDecrement(State[index]); GHR = GHR << 1; } // *********** 你需要在上面书写代码 *********** } void PREDICTOR_free(void) { free(State); }