我目前正在处理的问题是编写一个 gshare 模拟器,该模拟器接受分支指令地址和 2 位饱和计数器的已采用/未采用指令。意思是,我的输入看起来像这样:
0ffd7a78 1
我编写的 2 位饱和计数器程序正确计算了错误预测的数量以及错误预测率。我了解 2 位饱和计数器背后的逻辑。但是,我很难理解 gshare 模拟器的概念,在我的例子中,它使用 BHSR(分支历史移位寄存器),它由一个可变位索引与来自最低有效位的位数进行异或运算的指令地址。据我了解,BHSR 包含最后 n 次出现,用于索引模式历史表。模式历史表中的每个条目都包含其自己的 2 位饱和计数器,用于给出预测。我已经为此工作/考虑了几个小时,也许我只是想多了。如何实现我的 2 位饱和计数器来制作一个包含多个 2 位饱和计数器的表来填充模式历史表?这是我第一次在这里提问,所以我希望我遵循正确的格式。我的 2 位饱和计数器程序代码在这里:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#define RECORDS 4000000
int main(int argc, char *argv[]){
int bitIndex = atoi(argv[1]); //The argument entered by the user, defines bit index
int numEntries; //Number of entries as determined by bit index
numEntries = pow(2, bitIndex);
int bht[numEntries]; //Integer array that holds the Branch History Table
int count; //Used to clear out the Branch History Table
//Loop through the entire Branch History Table and make sure all cells are set to 0.
for(count = 0; count < numEntries; count++){
bht[count] = 0;
}
int i; //Set up our counter
int mispredict = 0; //Tells the number of mispredicts
int predict = 0; //Tells the number of correct predictions
//Branch Prediction Record
char hexAddress[8]; //Address in branch prediction record stored as a string
int direction; //The 0 or 1 will tell us whether to go up or down in a state change
for(i = 0; i < RECORDS; i++){
scanf("%s %d", hexAddress, &direction);
//printf("The address is %s\nThe direction is %d\n", hexAddress, direction);
//BEGIN NUMBER CONVERSION
//LOOKING FOR LEAST SIGNIFICANT BITS (bitIndex)
//CONVERT HEX ADDRESS TO BINARY
char originalHexAddress[8];
strcpy(originalHexAddress, hexAddress); //Preserve the original address
int j; //Counter for this internal loop
char binaryString[32] = {""}; //Sets up a "string" for the binary conversion
//Loop through the hex address and turn each component into its binary counterpart
for(j = 0; j < 8; j++){
if(hexAddress[j] == '0'){
if(binaryString[0] == '\0'){
strcpy(binaryString, "0000");
}
else{
strcat(binaryString, "0000");
}
}
if(hexAddress[j] == '1'){
if(binaryString[0] == '\0'){
strcpy(binaryString, "0001");
}
else{
strcat(binaryString, "0001");
}
}
if(hexAddress[j] == '2'){
if(binaryString[0] == '\0'){
strcpy(binaryString, "0010");
}
else{
strcat(binaryString, "0010");
}
}
if(hexAddress[j] == '3'){
if(binaryString[0] == '\0'){
strcpy(binaryString, "0011");
}
else{
strcat(binaryString, "0011");
}
}
if(hexAddress[j] == '4'){
if(binaryString[0] == '\0'){
strcpy(binaryString, "0100");
}
else{
strcat(binaryString, "0100");
}
}
if(hexAddress[j] == '5'){
if(binaryString[0] == '\0'){
strcpy(binaryString, "0101");
}
else{
strcat(binaryString, "0101");
}
}
if(hexAddress[j] == '6'){
if(binaryString[0] == '\0'){
strcpy(binaryString, "0110");
}
else{
strcat(binaryString, "0110");
}
}
if(hexAddress[j] == '7'){
if(binaryString[0] == '\0'){
strcpy(binaryString, "0111");
}
else{
strcat(binaryString, "0111");
}
}
if(hexAddress[j] == '8'){
if(binaryString[0] == '\0'){
strcpy(binaryString, "1000");
}
else{
strcat(binaryString, "1000");
}
}
if(hexAddress[j] == '9'){
if(binaryString[0] == '\0'){
strcpy(binaryString, "1001");
}
else{
strcat(binaryString, "1001");
}
}
if(hexAddress[j] == 'A'){
if(binaryString[0] == '\0'){
strcpy(binaryString, "1010");
}
else{
strcat(binaryString, "1010");
}
}
if(hexAddress[j] == 'B'){
if(binaryString[0] == '\0'){
strcpy(binaryString, "1011");
}
else{
strcat(binaryString, "1011");
}
}
if(hexAddress[j] == 'C'){
if(binaryString[0] == '\0'){
strcpy(binaryString, "1100");
}
else{
strcat(binaryString, "1100");
}
}
if(hexAddress[j] == 'D'){
if(binaryString[0] == '\0'){
strcpy(binaryString, "1101");
}
else{
strcat(binaryString, "1101");
}
}
if(hexAddress[j] == 'E'){
if(binaryString[0] == '\0'){
strcpy(binaryString, "1110");
}
else{
strcat(binaryString, "1110");
}
}
if(hexAddress[j] == 'F'){
if(binaryString[0] == '\0'){
strcpy(binaryString, "1111");
}
else{
strcat(binaryString, "1111");
}
}
if(hexAddress[j] == 'a'){
if(binaryString[0] == '\0'){
strcpy(binaryString, "1010");
}
else{
strcat(binaryString, "1010");
}
}
if(hexAddress[j] == 'b'){
if(binaryString[0] == '\0'){
strcpy(binaryString, "1011");
}
else{
strcat(binaryString, "1011");
}
}
if(hexAddress[j] == 'c'){
if(binaryString[0] == '\0'){
strcpy(binaryString, "1100");
}
else{
strcat(binaryString, "1100");
}
}
if(hexAddress[j] == 'd'){
if(binaryString[0] == '\0'){
strcpy(binaryString, "1101");
}
else{
strcat(binaryString, "1101");
}
}
if(hexAddress[j] == 'e'){
if(binaryString[0] == '\0'){
strcpy(binaryString, "1110");
}
else{
strcat(binaryString, "1110");
}
}
if(hexAddress[j] == 'f'){
if(binaryString[0] == '\0'){
strcpy(binaryString, "1111");
}
else{
strcat(binaryString, "1111");
}
}
}
//printf("The binary string representation of %s is:\n%s\n", originalHexAddress, binaryString);
//Now we must convert the appropriate binary component into it's decimal representation
//CONVERT FROM BINARY TO DECIMAL
//First, must get to the end based on our bit index
int decimal = 0;
int stringpos;
//Loop starts at the appropriate value in the binary string and converts it to a decimal using bit shifting
for(stringpos = (32 - bitIndex); stringpos < strlen(binaryString); stringpos++){
decimal = decimal << 1;
if(binaryString[stringpos] == '1'){
decimal += 1;
}
}
//printf("The decimal value based off your bit index is %d\n", decimal);
//END NUMBER CONVERSION
//BEGIN WORK IN BHT
/*
LOGIC NOTE
If the state is 0 or 1, predict NOT TAKEN
If the state is 2 or 3, predict TAKEN
If prediction is correct, then note it.
If prediction is not correct, mark it as MISPREDICT.
*/
//2-BIT SATURATING COUNTER
//Based off our bit index, we will go to a specific cell in the table for each address
//bht[decimal] represents which state we are currently in - 0, 1, 2, or 3
//while(direction){
switch (direction){
//Lower state until saturate at 0
case 0:
//If state is 0 or 1, CORRECT PREDICTION, state will become 0
if((bht[decimal] == 0) || (bht[decimal] == 1)){
bht[decimal] = 0; //Keep or move to state 0
predict++; //CORRECT PREDICTION
//printf("Stayed in state 0.\n");
}
//If state is 2, MISPREDICT, lower to state 1
else if((bht[decimal] == 2)){
bht[decimal] = 1; //Move to state 1
mispredict++; //MISPREDICT
//printf("Lowered to state %d\n", state);
}
//If state is 3, MISPREDICT, lower to state 2
else if((bht[decimal] == 3)){
bht[decimal] = 2; //Move to state 2
mispredict++; //MISPREDICT
}
break;
//Increase state until saturate at 3
case 1:
//If state is 0, MISPREDICT, increase to state 1
if((bht[decimal] == 0)){
bht[decimal] = 1; //Move to state 1
mispredict++; //MISPREDICT
//printf("Stayed in state 3.\n");
}
//If state is 1, MISPREDICT, increase to state 2
else if((bht[decimal] == 1)){
bht[decimal] = 2; //Move to state 2
mispredict++; //MISPREDICT
//printf("Increased to state %d\n", state);
}
//If state is 2 or 3, CORRECT PREDICTION, state will become 3
else if((bht[decimal] == 2) || (bht[decimal] == 3)){
bht[decimal] = 3; //Keep or move to state 3
predict++; //CORRECT PREDICTION
}
break;
}
//}
//printf("Number of entries: %d\nPredicts: %d\nMispredicts: %d\n", numEntries, predict, mispredict);
//printf("The state is %d\n", bht[decimal]);
}
//Calculate rate
double rate;
rate = (((double)mispredict / 4000000) * 100);
printf("%d entries (%d-bit index): mispredicts = %d, rate = %.2lf%%\n", numEntries, bitIndex, mispredict, rate);
return 0;
}
注意:我知道我可以简化到二进制的转换并节省大量空间,但在我编写该代码时,我只是在寻找一种让它工作的方法,确实如此。我觉得没有必要回去尝试修改它,所以请原谅长度。