链接
- https://gitee.com/Rui_He/qrio_handout.git
内容
Static Predictor
void branch(bool taken, unsigned long pc) override {
/* TODO 1: static predictor */
/* bool _predict: */
/* true: predict the branch will always be taken */
/* false: predict the branch will always be not-taken */
_total++;
if (_predict != taken) _miss++;
}
静态预测器中,将_predict
与taken
进行比较,如果不同,则_miss++
。
FlipFlopPredictor
void branch(bool taken, unsigned long pc) override {
/* TODO 2: flip-flop predictor */
/* char _hbt[N]: history branch table */
/* pc_bit: number of PC bits used to index the table */
_total++;
// 计算PC值对应的历史分支表项索引
unsigned long index = pc & ((1 << _pc_bit) - 1);
// 如果历史分支表项为“taken”,则预测下一次分支不会被执行;否则预测分支会被执行
bool prediction = (_hbt[index] == 1) ? true : false;
// 如果当前实际结果与预测结果不一致,则更新历史分支表项
if (taken != prediction) {
_miss++; // 统计预测失败次数
if (taken) {
_hbt[index] = (_hbt[index] << 1) | 0x1; // 更新历史分支表项为“taken”
} else {
_hbt[index] = (_hbt[index] << 1) & 0xFE; // 更新历史分支表项为“not-taken”
}
}
}
先计算当前PC值对应的历史分支表项索引。
然后,根据历史分支表项的值,来预测下一次分支是否被执行。如果历史分支表项值为1,则预测下一次分支会被执行;否则预测下一次分支不会被执行。
如果当前实际结果与预测结果不一致,则_miss++
,并更新历史分支表项。如果当前实际结果为"taken",则将历史分支表项左移一位并加1(即将最低位设为1),表示下一次分支会被执行;否则将历史分支表项左移一位并将最低位设为0,表示下一次分支不会被执行。
CorrelatePredictor
void branch(bool taken, unsigned long pc) override {
/* TODO 3: correlating predictor predictor */
/* (m,n)*T correlating predictor means a table with T n-bit predictors, */
/* m bits used to represent the taken/not-taken of the last m branches. */
/* Here, n is 2 that we use 2-bit predictors. */
/* */
/* char _hbt[N]: history branch table */
/* int _history: records taken/not-taken sequences of previous branches */
/* int _pc_bit: number of PC bits used to index the table */
/* int _history_bit: number of history bits used to index the table */
_total++;
unsigned long index = ((pc & ((1 << _pc_bit) - 1)) << _history_bit)
| (_history & ((1 << _history_bit) - 1));// 获取索引
int prediction = _hbt[index]; // 获取预测结果
_history = ((_history << 1) & ((1 << _history_bit) - 1)) | taken; // 更新历史记录
// 更新预测表格
if (taken) {
if (prediction < 3) {
prediction++;
}
} else {
if (prediction > 0) {
prediction--;
}
}
_hbt[index] = prediction;
if (taken != prediction) {
_miss++;
}
}
计算预测器表格的索引。其中,pc & ((1 << _pc_bit) - 1)
表示取出pc
的低_pc_bit
位,
_history & ((1 << _history_bit) - 1)
表示取出历史分支情况的低_history_bit
位。
获取预测结果。
更新历史分支情况。将历史分支情况左移1位,并将最低位的值更新为当前分支指令是否被执行,以此更新历史分支情况。因为历史分支情况只有_history_bit位,所以将高位清零。
根据真实结果和预测结果更新预测器表格。如果真实结果为taken,且预测结果小于3,则将预测结果加1;如果真实结果为not taken,且预测结果大于0,则将预测结果减1。
判断预测是否命中。如果真实结果和预测结果不同,则_miss++
。
GSharePredictor
void branch(bool taken, unsigned long pc) override {
/* TODO 4: GSharePredictor */
/* index = pc-bit XOR history-bit */
_total++;
unsigned long index = (_history ^ (pc & ((1 << _pc_bit) - 1)))
& ((1 << _pc_bit) - 1); // 获取索引
int prediction = _hbt[index]; // 获取预测结果
_history = ((_history << 1) | taken) & ((1 << _pc_bit) - 1); // 更新历史记录
// 更新预测表格
if (taken) {
if (prediction < 3) {
prediction++;
}
} else {
if (prediction > 0) {
prediction--;
}
}
_hbt[index] = prediction;
if (taken != prediction) {
_miss++;
}
}
与CorrelatePredictor
基本一致,不同在于索引生成的部分。
索引值通过求PC bits
和history bits
的异或值得到