Я пытался выяснить, какие части этого кода включают 2-битный счетчик, потому что я должен превратить его в 3-битный счетчик.
Для размера таблицы GSHARE_SIZE, я думаю, правильный размер для 3-битного счетчика будет 17 вместо 2-битного 18, потому что есть еще один счетчик и 18 слишком велик для выделенной памяти пробел (64k).
Кроме того, я считаю, что значение счетчика в разделе --- // предиктора обновления --- необходимо изменить с:
// update predictor
bool t = uop->br_taken;
if (t && gtable[gidx] < 1)
gtable[gidx] ++;
else if (!t && gtable[gidx] > -2)
gtable[gidx] --;
на
// update predictor
bool t = uop->br_taken;
if (t && gtable[gidx] < 2)
gtable[gidx] ++;
else if (!t && gtable[gidx] > -3)
gtable[gidx] --;
Кроме этих двух вещей, я не уверен, как преобразовать этот 2-битный счетчик в 3-битный. Ниже приведен код для 2-битного предиктора.
#include <stdio.h>
#include <cassert>
#include <string.h>
#include <inttypes.h>
using namespace std;
#include "cbp3_def.h"
#include "cbp3_framework.h"
#define GSHARE_SIZE 18 // 256K 2-bit counters = 64 KB cost
// predictor tables
int8_t *gtable;
// cost: depending on predictor size
uint32_t brh_fetch;
uint32_t brh_retire;
// count number of runs
uint32_t runs;
void PredictorInit() {
runs = 0;
gtable = new int8_t[1 << GSHARE_SIZE];
assert(gtable);
}
void PredictorReset() {
// this function is called before EVERY run
// it is used to reset predictors and change configurations
printf("Predictor:gshare\nconfig: %i counters, %i KB cost\n", 1 << GSHARE_SIZE, (1 << GSHARE_SIZE) * 2 / 8 / 1024);
for (int i = 0; i < (1 << GSHARE_SIZE); i ++)
gtable[i] = 0;
brh_fetch = 0;
brh_retire = 0;
}
void PredictorRunACycle() {
// get info about what uops are processed at each pipeline stage
const cbp3_cycle_activity_t *cycle_info = get_cycle_info();
// make prediction at fetch stage
for (int i = 0; i < cycle_info->num_fetch; i++) {
uint32_t fe_ptr = cycle_info->fetch_q[i];
const cbp3_uop_dynamic_t *uop = &fetch_entry(fe_ptr)->uop;
if (runs == 0 && uop->type & IS_BR_CONDITIONAL) {
// get prediction
uint32_t gidx = (brh_fetch ^ uop->pc) & ((1 << GSHARE_SIZE) - 1);
bool gpred = (gtable[gidx] >= 0);
assert(report_pred(fe_ptr, false, gpred));
}
// update fetch branch history
if (uop->type & IS_BR_CONDITIONAL)
brh_fetch = (brh_fetch << 1) | (uop->br_taken ? 1 : 0);
else if (uop_is_branch(uop->type))
brh_fetch = (brh_fetch << 1) | 1;
}
for (int i = 0; i < cycle_info->num_retire; i++) {
uint32_t rob_ptr = cycle_info->retire_q[i];
const cbp3_uop_dynamic_t *uop = &rob_entry(rob_ptr)->uop;
if (runs == 0 && uop->type & IS_BR_CONDITIONAL) {
uint32_t gidx = (brh_retire ^ uop->pc) & ((1 << GSHARE_SIZE) - 1);
// update predictor
bool t = uop->br_taken;
if (t && gtable[gidx] < 1)
gtable[gidx] ++;
else if (!t && gtable[gidx] > -2)
gtable[gidx] --;
// update retire branch history
if (uop->type & IS_BR_CONDITIONAL)
brh_retire = (brh_retire << 1) | (uop->br_taken ? 1 : 0);
else if (uop_is_branch(uop->type))
brh_retire = (brh_retire << 1) | 1;
}
}
void PredictorRunEnd() {
runs ++;
if (runs < 1) // set rewind_marked to indicate that we want more runs
rewind_marked = true;
}
void PredictorExit() {
delete [] gtable;
}
Я не уверен, какие части этого предиктора имеют отношение к компоненту "2-битного счетчика" этого предиктора.